{"id":50828820,"url":"https://github.com/minipekka25/knitkit","last_synced_at":"2026-06-13T21:01:30.947Z","repository":{"id":364602112,"uuid":"1268302868","full_name":"minipekka25/knitkit","owner":"minipekka25","description":"Module federation, minus the bundler — runtime-first, on native ES modules + import maps. Browser, Node SSR, and edge.","archived":false,"fork":false,"pushed_at":"2026-06-13T17:55:40.000Z","size":272,"stargazers_count":1,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T18:31:11.234Z","etag":null,"topics":["edge","esm","esmodules","import-maps","micro-frontends","micro-frontends-solution","micro-frontends-starter","microfrontends","module-federation","modulefederation","react","ssr","typescript","vite"],"latest_commit_sha":null,"homepage":"https://knitkit.mintlify.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/minipekka25.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T11:23:19.000Z","updated_at":"2026-06-13T18:24:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/minipekka25/knitkit","commit_stats":null,"previous_names":["minipekka25/knitkit"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/minipekka25/knitkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minipekka25%2Fknitkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minipekka25%2Fknitkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minipekka25%2Fknitkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minipekka25%2Fknitkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minipekka25","download_url":"https://codeload.github.com/minipekka25/knitkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minipekka25%2Fknitkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34300116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["edge","esm","esmodules","import-maps","micro-frontends","micro-frontends-solution","micro-frontends-starter","microfrontends","module-federation","modulefederation","react","ssr","typescript","vite"],"created_at":"2026-06-13T21:01:09.780Z","updated_at":"2026-06-13T21:01:30.923Z","avatar_url":"https://github.com/minipekka25.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# knitkit\n\n[![CI](https://github.com/minipekka25/knitkit/actions/workflows/ci.yml/badge.svg)](https://github.com/minipekka25/knitkit/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@knitkit/runtime.svg)](https://www.npmjs.com/package/@knitkit/runtime)\n[![runtime size](https://img.shields.io/badge/runtime-3.75%20KB%20brotli-brightgreen.svg)](./benchmarks)\n[![docs](https://img.shields.io/badge/docs-knitkit.mintlify.app-blue.svg)](https://knitkit.mintlify.app)\n[![license](https://img.shields.io/npm/l/@knitkit/runtime.svg)](./LICENSE)\n\n\u003e **Module federation, minus the bundler.**\n\u003e A tiny (\u003c 5 KB), zero-dependency, runtime-first module federation system built on native ES modules + import maps — identical in the browser, Node SSR, and the edge.\n\n\u003e ⚠️ **Pre-1.0.** Published under the `@knitkit/*` npm scope; APIs may change before 1.0.\n\n---\n\n## The problem\n\nModule federation today means buying into a bundler plugin (`ModuleFederationPlugin`, `vite-plugin-federation`) and its config surface, its singleton-versioning footguns (“Invalid hook call… more than one copy of React”), and its plugin-treadmill bug backlog. SSR is labeled experimental even by its own authors.\n\nThe web platform grew the primitives to do this natively: **import maps** (Chrome 89+, Firefox 108+, Safari 16.4+), the **`integrity` key** for module SRI, and **`module.register`** hooks in Node. `knitkit` is the runtime that uses them — and nothing else.\n\n## How it works in 10 lines\n\n```html\n\u003c!-- The import map is injected before the first module import. Zero bundler plugins. --\u003e\n\u003cscript type=\"importmap\"\u003e\n  { \"imports\": { \"@knitkit/runtime\": \"/runtime/index.js\", \"react\": \"https://esm.sh/react@18.3.1\" } }\n\u003c/script\u003e\n\u003cscript type=\"module\"\u003e\n  import { registerRemotes, loadRemote } from \"@knitkit/runtime\";\n  await registerRemotes([{ name: \"checkout\", manifest: \"/federation/knit.manifest.json\" }]);\n  const mount = await loadRemote(\"checkout/CartWidget\"); // resolved via the negotiated import map\n  mount(document.getElementById(\"slot\"));                // a Vue widget, mounted inside a React host\n\u003c/script\u003e\n```\n\nThat's the whole contract: declare remotes by manifest URL, `loadRemote` an exposed module, and shared dependencies resolve to **one instance** through the browser's module cache.\n\n## Try it in one command\n\n```bash\nnpm create @knitkit my-app \u0026\u0026 cd my-app \u0026\u0026 npm run dev\n```\n\nScaffolds a runnable host + remote (shared singleton, no build step) and serves it at\n`localhost:8080`. See [`@knitkit/create`](./packages/create).\n\n## Live demo\n\n[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/minipekka25/knitkit/tree/main/examples/stackblitz)\n\nOne click runs a zero-build, in-browser demo: it loads the **published `@knitkit/runtime` from a CDN**, `loadRemote`s a remote behind its own manifest, and proves the shared-singleton across the boundary. Open DevTools → Network to watch the import map resolve.\n\nRunnable examples in the repo:\n\n- [`examples/stackblitz`](./examples/stackblitz) — the live demo above: `loadRemote` + a shared singleton, framework-agnostic, no build step.\n- [`examples/react-host-vue-remote`](./examples/react-host-vue-remote) — a **React host mounting a Vue 3 remote**, one shared state object proven identical across the framework boundary.\n- [`examples/react-host-react-remote`](./examples/react-host-react-remote) — a **React host rendering a React remote via `\u003cRemoteComponent\u003e`**, sharing one React instance so the remote's hooks work across the boundary.\n- [`examples/nextjs-host`](./examples/nextjs-host) — a **Next.js App Router** host embedding a remote with `\u003cRemoteFragment\u003e` and **zero `next.config` changes** (uses the published `@knitkit/react`).\n- [`examples/node-ssr`](./examples/node-ssr) — **Node SSR** of a federated React component via `@knitkit/node` loader hooks (SRI-verified), with the import map serialized for hydration parity.\n- [`examples/edge-composition`](./examples/edge-composition) — **Tier-2 edge composition**: independent apps (a React fragment + a framework-less fragment) stitched into one streamed page by `@knitkit/edge`.\n\nRun any of them locally:\n\n```bash\nnpm ci\nnpm run --workspace=@knitkit/runtime build\nnpm --prefix examples/react-host-vue-remote test   # Playwright boots both servers and asserts the singleton proof\n```\n\n## Why the singleton just works\n\nOne import map entry per shared package → one URL → one module instance in the browser cache, shared by the host and every remote. There is no “share scope” to negotiate at runtime and no way to accidentally load React twice. **The shared surface is explicit and inspectable**: open the import map in DevTools and you can see who won and why. We call this *debuggability by construction* — and it kills the ecosystem's #1 bug class by design, not by configuration.\n\n## vs Module Federation 2.0\n\n| | **knitkit** | **Module Federation 2.0** |\n| --- | --- | --- |\n| **Bundler coupling** | None — runtime + manifest + tiny CLI. [Externalize shared deps (1 line)](https://knitkit.mintlify.app/bundler-recipes). | Ergonomic path is `ModuleFederationPlugin`; ESM output still maturing. |\n| **Shared singletons** | One import map entry → one instance, by construction. | `singleton: true` + `requiredVersion` — powerful, but the canonical footgun. |\n| **Substrate** | Native import maps + ESM. | Bundler runtime + share scopes. |\n| **SSR** | Same manifest drives Node via `module.register` *(Phase 2)*. | Supported, but labeled experimental/hard by its own creator. |\n| **Next.js App Router** | Embed an isolated remote with **zero `next.config` changes** (`\u003cRemoteFragment\u003e`, [demo](./examples/nextjs-host)); shared-React `\u003cRemoteComponent\u003e` needs extra config (Next bundles its own React). | `nextjs-mf` is EOL/maintenance. |\n| **Edge** | Same manifest, native import maps on Deno/Workers *(Phase 3)*. | Not a first-class target. |\n| **Types** | `.d.ts` published next to the manifest, synced to the host *(Phase 2)*. | Strong — TS hints are a praised MF feature. |\n| **Core size** | \u003c 5 KB min+gzip, zero deps. | Larger; bundler-embedded. |\n\nMF 2.0 is genuinely capable (decoupled runtime, manifest, TS hints, devtools). `knitkit` makes a different bet: **radical simplicity on platform primitives**, not feature breadth.\n\n## Roadmap (honest)\n\n- **Week 1 — Minimal Lovable MVP** *(done):* `@knitkit/runtime` (negotiation, import-map injection, `loadRemote`), the manifest spec v0.1, `@knitkit/cli` (emits shared ESM assets + manifest + SRI hashes from your `node_modules`), and the React-host / Vue-remote demo with a passing singleton smoke test.\n- **Weeks 2–4 — Production-credible v1:** `@knitkit/node` SSR via `module.register` with SRI enforcement, module cache, and hydration-parity import maps *(done)*; robust negotiation (x-ranges, `scopes` fallbacks, coded errors) *(done)*; `@knitkit/react` `\u003cRemoteComponent\u003e` *(done)*; `knitkit types generate` + `knitkit types sync` so `loadRemote()` is fully typed *(done)*; an SSR example rendering a federated React component *(done)*; `@knitkit/overrides` local-override dev widget *(done)*; a docs site *(done — [knitkit.mintlify.app](https://knitkit.mintlify.app))*; and a Next.js App Router demo *(done — zero-config via `\u003cRemoteFragment\u003e`)*.\n- **Months 2–3 — Traction \u0026 edge:** `@knitkit/edge` (ESI-style fragment composition for Workers/Deno/Vercel Edge), Tier-2 RSC fragment composition, a cold-load + bytes benchmark vs MF, and partnerships.\n\n## When **not** to use this\n\n`knitkit` is deliberately scoped. It is the wrong tool if you need:\n\n- **Cross-remote HMR** — requires bundler coupling, which we refuse. Each remote uses its own dev server's HMR; point a remote at `localhost` via the local-override widget instead.\n- **Automatic transitive sharing** — the shared surface is explicit by design. You declare what's shared; nothing is shared silently. (This is exactly where MF's worst bugs live.)\n- **Module-level RSC / Flight federation** — no standard exists for cross-app Flight module references yet. We are RSC-*compatible*, not RSC-*federated* (we're watching `react-server-dom-esm`).\n- **React Native** — out of scope.\n\nIf you want a bundler plugin that does everything, use Module Federation. If you want a small, standards-native primitive you can read in an afternoon, that's this.\n\n## Packages\n\n| Package | Status | Purpose |\n| --- | --- | --- |\n| [`@knitkit/runtime`](./packages/runtime) | ✅ MVP | Browser core: `registerRemotes`, `loadRemote`, negotiation, import-map injection. \u003c 5 KB, zero deps. |\n| [`@knitkit/cli`](./packages/cli) | ✅ MVP | Emits shared ESM assets from `node_modules` (esbuild), generates the manifest, computes SRI hashes. |\n| [`@knitkit/node`](./packages/node) | ✅ MVP | `module.register` SSR loader hooks, SRI verification, module cache, hydration-parity import-map serialization. |\n| [`@knitkit/react`](./packages/react) | ✅ MVP | Thin `\"use client\"` `\u003cRemoteComponent\u003e` wrapper (lazy + Suspense + error boundary) over `loadRemote`. |\n| [`@knitkit/overrides`](./packages/overrides) | ✅ MVP | Local-override dev tool: point a remote at `localhost` against deployed others (localStorage + UI widget). |\n| [`@knitkit/edge`](./packages/edge) | ✅ MVP | ESI-style HTML fragment stream-stitching + import-map injection for Workers / Deno / Vercel Edge. |\n| [`@knitkit/create`](./packages/create) | ✅ MVP | `npm create @knitkit my-app` — scaffolds a runnable host + remote starter. |\n\nThe **manifest spec** lives in [`/spec`](./spec/manifest-0.1.md) and is versioned from day one.\n\n## Documentation\n\n📖 **[knitkit.mintlify.app](https://knitkit.mintlify.app)** — guides, comparisons, and reference.\n\nHighlights: [getting started](https://knitkit.mintlify.app/getting-started) · [use with your bundler](https://knitkit.mintlify.app/bundler-recipes) · [security (SRI/CSP/CORS)](https://knitkit.mintlify.app/security) · [dev experience \u0026 HMR](https://knitkit.mintlify.app/hmr-and-dev) · [vs Module Federation](https://knitkit.mintlify.app/vs-module-federation) · [vs Native Federation](https://knitkit.mintlify.app/vs-native-federation) · [roadmap](https://knitkit.mintlify.app/roadmap). (Source in [`/docs`](./docs).)\n\nReproducible [benchmarks](./benchmarks/README.md) measure knitkit's federation overhead at **~3.5 KB brotli — ~7–8× smaller than Module Federation** (delta method, measured against a real MF 2.0 build).\n\n## Contributing\n\nEarly days — issues and discussion welcome. The negotiation function ([`packages/runtime/src/negotiate.ts`](./packages/runtime/src/negotiate.ts)) is the most-tested code in the repo; changes there need tests first. Core stays **\u003c 5 KB and zero-dependency** — that constraint is non-negotiable and CI-enforced.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminipekka25%2Fknitkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminipekka25%2Fknitkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminipekka25%2Fknitkit/lists"}