# Create a local module

Local modules are regular modules that are part of the host application build. They are independent modules that expose a registration function to the host application's bootstrapping code. A local module can be a standalone package, a sibling project (in a monorepo setup), or even a local folder within the host application.

Local modules have many uses but are especially useful when launching a new product with an unrefined business domain or migrating from a monolithic application to a distributed application.

Let's add a local module to demonstrate how it's done!

# Install the packages

Create a new application (we'll refer to ours as local-module), then open a terminal at the root of the new solution and install the following packages:

pnpm add -D typescript @types/react @types/react-dom
pnpm add @squide/firefly react react-dom react-router-dom @tanstack/react-query
yarn add -D typescript @types/react @types/react-dom
yarn add @squide/firefly react @squide/firefly react-dom react-router-dom @tanstack/react-query
npm add -D typescript @types/react @types/react-dom
npm install @squide/firefly react react-dom react-router-dom @tanstack/react-query

# Setup the application

First, create the following files:

local-modules
├── src
├──── register.tsx
├──── Page.tsx
├── package.json

Then, ensure that you are developing your module using ESM syntax by specifying type: module in your package.json file:

local-module/package.json
{
    "type": "module"
}

Finally, configure the package to be shareable by adding the name, version, and export fields to the package.json file:

local-module/package.json
{
    "name": "@getting-started/local-module",
    "version": "0.0.1",
    "exports": "./src/register.tsx"
}

For more information about the exports field, refer to this resource on Just-In-Time Packages.

# Routes registration

Next, register the local module routes and navigation items with registerRoute and registerNavigationItem functions:

local-module/src/register.tsx
import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly";
import { Page } from "./Page.tsx";

export const register: ModuleRegisterFunction<FireflyRuntime> = runtime => {
    runtime.registerRoute({
        path: "/local/page",
        element: <Page />
    });

    runtime.registerNavigationItem({
        $id: "local-page",
        $label: "Local/Page",
        to: "/local/page"
    });
}

Then, create the Page component:

local-module/src/Page.tsx
export function Page() {
    return (
        <div>Hello from Local/Page!</div>
    );
}

# Register the local module

Go back to the host application and add a dependency to the @getting-started/local-module package in the host application package.json file:

host/package.json
{
    "dependencies": {
        "@getting-started/local-module": "0.0.1"
    }
}

Then, register the local module with the bootstrap function:

host/src/bootstrap.tsx
import { createRoot } from "react-dom/client";
import { ConsoleLogger, RuntimeContext, FireflyRuntime, bootstrap, type RemoteDefinition } from "@squide/firefly";
import { register as registerMyLocalModule } from "@getting-started/local-module";
import { App } from "./App.tsx";
import { registerHost } from "./register.tsx";

// Define the remote modules.
const Remotes: RemoteDefinition[] = [
    { name: "remote1" }
];

// Create the shell runtime.
const runtime = new FireflyRuntime({
    loggers: [x => new ConsoleLogger(x)]
});

// Register the modules.
await bootstrap(runtime, {
    localModules: [registerHost, registerMyLocalModule],
    remotes: Remotes
})

const root = createRoot(document.getElementById("root")!);

root.render(
    <RuntimeContext.Provider value={runtime}>
        <App />
    </RuntimeContext.Provider>
);

# Try it 🚀

Start the host and remote-module applications in development mode using the dev script. You should notice an additional link labelled Local/Page in the navigation menu. Click on the link to navigate to the page of your new local module!

# Troubleshoot issues

If you are experiencing issues with this guide:

  • Open the DevTools console. You'll find a log entry for each registration that occurs and error messages if something went wrong:
    • [squide] The following route has been registered.
    • [squide] The following static navigation item has been registered to the "root" menu for a total of 2 static items.
  • Refer to a working example on GitHub.
  • Refer to the troubleshooting page.