Host and Remote
A remote is any application or library that runsknitkit build. It produces a knit.manifest.json describing the modules it exposes and the shared dependencies it contributes, along with the built ESM artifacts for each. A remote is completely self-contained: serve its dist/ directory from any static host and it is ready to be consumed.
A host is any application that calls registerRemotes at boot time. The host fetches one or more remote manifests, negotiates shared dependency versions across all participants (including its own declared shared dependencies), injects a single import map, and then loads individual exposed modules on demand with loadRemote.
The host and remote do not need to know about each other at build time. The only coupling is the manifest URL, which is provided at runtime. This means you can deploy a new version of a remote and have the host pick it up on the next page load without any changes to the host’s build.
A single application can be both a host and a remote simultaneously — it can expose its own modules via a manifest while also loading modules from other remotes.
The Manifest
The manifest (knit.manifest.json) is the contract between a remote and its consumers. It is a versioned JSON document that the host fetches at boot to learn what the remote offers and what shared dependencies it expects.
Here is a representative manifest:
knit.manifest.json
All relative URLs in the manifest (
url, types) resolve against the manifest’s own URL. You can host a remote on any path or CDN origin and nothing breaks.
Shared Dependencies
Shared dependencies are packages that must resolve to a single instance across the host and all remotes. The canonical example is React: if a remote’s hooks run against a different React instance than the host’s renderer, React throws. The same constraint applies to any library that uses module-level singletons — stores, routers, context providers. knitkit solves this with a direct property of import maps: one import map entry maps to one URL, and one URL means one module instance in the browser cache. There is no share scope, no runtime reference counting, and no configuration flag that can accidentally create a second copy. Each participant in the federation — the host and every remote — declares its shared dependencies with three key fields:Import Map Negotiation
When you callregisterRemotes, the runtime runs the following sequence:
- Fetch manifests — each remote’s
knit.manifest.jsonis fetched in parallel. The response URL is used as the base for resolving relativeurlfields, so the manifest is portable. - Negotiate shared deps —
negotiateSharedmerges the shared declarations from the host and all remotes. For each package, it selects the highest version that satisfies every participant’srequiredVersion. If any participant declaressingleton: trueand no single version satisfies all ranges, the runtime throwsKNIT_ERR_SINGLETON_CONFLICTimmediately rather than silently loading a duplicate. - Inject the import map —
injectImportMapwrites a<script type="importmap">element into the document (or the equivalent structure in Node/edge environments) before any module import resolves through it. Everyimport "react"— from the host or from any remote — now resolves to the single winning URL. - Register remotes — the runtime stores each remote’s manifest and base URL so
loadRemotecan look up expose URLs later.
Expose Keys
Theexposes object in the manifest uses keys written with a leading ./, following the Node.js package exports convention:
loadRemote, they combine the remote’s name with the expose key, omitting the ./:
./ before looking it up in the manifest. If the key is not found, loadRemote throws KNIT_ERR_LOAD_FAILED and lists the available keys in the error’s suggestion field.
SRI Integrity
The manifest’sintegrity field on each shared dependency and expose declaration holds a Subresource Integrity hash computed by @knitkit/cli at build time:
integrity field is consumed in two ways:
- In the browser, the runtime places the hash in the import map’s
integritykey (available in Chrome 127+, Firefox 138+, Safari 18.4+). The browser enforces the hash on the module fetch, refusing to execute a tampered file. - In Node SSR,
@knitkit/node’s loader hooks verify the hash against the fetched bytes before the module is evaluated, providing the same protection server-side.
The
integrity field is optional in the manifest schema. Remotes built without @knitkit/cli can omit it, but SRI verification will not be possible for those modules. For production deployments, always run knitkit build to get computed hashes.