> ## Documentation Index
> Fetch the complete documentation index at: https://knitkit.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Local Dev Overrides for Federated Remotes

> Use @knitkit/overrides to point a remote at localhost during development while the rest of your federation stays on the deployed versions.

Developing one remote in isolation is easy — you run its dev server and iterate. The hard
part starts when you want to test that remote against the real host and all the other remotes
that surround it. Rebuilding and redeploying every time is slow, and running all remotes
locally at once is noisy. `@knitkit/overrides` solves this by letting you redirect a
single remote to your local dev server while everything else continues to load from the
deployed CDN — changes are isolated to your browser, never affect teammates, and never touch
production.

## Install

```bash theme={null}
npm i -D @knitkit/overrides
```

***

## How it works

Overrides are stored in `localStorage` under the key `knitkit:overrides` as a JSON object
that maps a remote name to a manifest URL (typically a `localhost` address). When
`applyOverrides` runs, it checks this store and rewrites the manifest URL for any remote
whose name has an entry — all other remotes pass through untouched. Because the rewrite
happens before `registerRemotes` is called, the host never knows the difference: it just sees
a different manifest URL for that one remote.

The floating widget provides a browser UI so you can set, update, and clear overrides without
touching your code or the URL bar. Overrides are **per-browser** and scoped to the origin
they are set on, so they are invisible to your teammates, CI, and production deployments.

***

## Setup

<Steps>
  <Step title="Wrap registerRemotes with applyOverrides">
    Import `applyOverrides` and pass your remotes array through it before handing the result
    to `registerRemotes`. `applyOverrides` returns the same array type `T[]` it receives, so
    there is no TypeScript friction.

    ```ts theme={null}
    import { registerRemotes } from "@knitkit/runtime";
    import { applyOverrides } from "@knitkit/overrides";

    await registerRemotes(applyOverrides([
      { name: "checkout", manifest: "https://cdn.example.com/checkout/knit.manifest.json" },
      { name: "profile",  manifest: "https://cdn.example.com/profile/knit.manifest.json" },
    ]));
    ```

    With no overrides set in `localStorage`, `applyOverrides` is a zero-cost pass-through.
  </Step>

  <Step title="Mount the overrides widget in dev mode">
    Call `mountOverridesWidget` after `registerRemotes` to render the floating panel. Pass the
    names of the remotes you want the widget to list. Guard it behind your build tool's `DEV`
    flag so it is never included in production bundles.

    ```ts theme={null}
    import { mountOverridesWidget } from "@knitkit/overrides";

    if (import.meta.env?.DEV) {
      mountOverridesWidget({ remotes: ["checkout", "profile"] });
    }
    ```

    `mountOverridesWidget` returns an unmount function you can call if you need to tear the
    widget down programmatically.
  </Step>

  <Step title="Use the panel to point a remote at localhost">
    Open your host app in the browser. Click the **⚙ knitkit overrides** button that appears
    in the bottom-right corner. Each remote listed in `options.remotes` gets its own row with a
    URL input.

    1. Find the remote you are developing locally (e.g. `checkout`).
    2. Paste the URL of its local manifest: `http://localhost:5174/knit.manifest.json`.
    3. Click **Use local**.
    4. The page reloads automatically.

    After the reload, `checkout` loads from your local Vite dev server while `profile` and
    every other remote continues to load from the CDN.
  </Step>

  <Step title="Clear the override when you're done">
    Click **Clear** next to the remote in the panel (or **Clear all & reload** to reset
    everything) when you are finished developing. The page reloads and the production manifest
    URL is restored.
  </Step>
</Steps>

***

## `applyOverrides(remotes)`

```ts theme={null}
import { applyOverrides } from "@knitkit/overrides";
import type { RemoteInput } from "@knitkit/overrides";

function applyOverrides<T extends RemoteInput>(remotes: T[]): T[]
```

Reads `localStorage["knitkit:overrides"]` and returns a new array where each remote whose
`name` has a stored override has its `manifest` property replaced with the stored URL. Remotes
with no stored override are returned unchanged. If `localStorage` is unavailable (e.g. a
sandboxed iframe or a server-side import), `applyOverrides` returns the original array
unmodified.

***

## `mountOverridesWidget(options?)`

```ts theme={null}
import { mountOverridesWidget } from "@knitkit/overrides";
import type { OverridesWidgetOptions } from "@knitkit/overrides";

function mountOverridesWidget(options?: OverridesWidgetOptions): () => void
```

Injects a small floating panel into `document.body`. If the widget is already present,
the existing one is removed first (so calling it a second time re-mounts with updated
options). Returns an unmount function.

<ParamField path="remotes" type="string[]">
  Remote names to display in the panel in addition to any names that already have an override
  set. Remotes that already have overrides always appear.
</ParamField>

<ParamField path="placeholder" type="string">
  Placeholder shown in each URL input. Defaults to
  `"http://localhost:5174/knit.manifest.json"`.
</ParamField>

***

## Storage API

The storage functions let you manage overrides programmatically — useful in test helpers,
bookmarklets, or custom dev tooling.

```ts theme={null}
import {
  getOverrides,
  setOverride,
  removeOverride,
  clearOverrides,
} from "@knitkit/overrides";
```

<ParamField path="getOverrides()" type="() => Record<string, string>">
  Returns all currently stored overrides as a plain object mapping remote name → manifest URL.
  Returns an empty object if `localStorage` is unavailable or contains no valid overrides.
</ParamField>

<ParamField path="setOverride(name, manifestUrl)" type="(name: string, manifestUrl: string) => void">
  Stores an override for `name`, replacing any existing value. Does nothing if `localStorage`
  is unavailable.
</ParamField>

<ParamField path="removeOverride(name)" type="(name: string) => void">
  Deletes the override for `name`. Other overrides are not affected.
</ParamField>

<ParamField path="clearOverrides()" type="() => void">
  Removes the entire `knitkit:overrides` entry from `localStorage`, resetting all overrides at
  once.
</ParamField>

***

<Note>
  Overrides are stored in the browser's `localStorage` under the key `knitkit:overrides` and
  are scoped to the page origin. They are invisible to other browsers, other users, and
  production servers. It is safe to ship the `mountOverridesWidget` call in your development
  builds — the widget is never rendered in environments where `document` is undefined (e.g.
  Node SSR), and it carries no risk of leaking to production as long as you guard it behind
  `import.meta.env?.DEV`.
</Note>
