Skip to content

Next Steps

Mosaic proved the shape: a runtime-composed, multi-framework storefront where each slice deploys on its own. What it deliberately left out is everything that turns a proven shape into a production system. Each extension below names what it teaches and where it plugs into what you already built, so none of it is a rewrite — it’s a next commit.

What it teaches: how to render remotes on the server and stream their HTML into the first response, so the user sees content before any remoteEntry.js loads — the biggest gap in a client-composed shell.

Where it plugs in: the shell currently mounts remotes on the client after load (the path of a runtime remote shows the round trip). Introduce a server that composes remote HTML fragments — the content remote already lives partly on the server via Astro, so start there and generalize the pattern to the catalog and cart shells.

What it teaches: the @module-federation/runtime plugin API — hooks that intercept remote loading to add retries, swap remoteEntry URLs per environment, inject auth headers, or fall back to a cached version when a remote is down.

Where it plugs in: you already point the shell’s remotes at env-driven URLs in Independent Deployment →. A runtime plugin is the clean home for that logic and for the resilience fallbacks you wrote as error boundaries — move the load-time concerns down into the loader itself.

A real design-system build and release pipeline

Section titled “A real design-system build and release pipeline”

What it teaches: versioning and publishing the design system as its own package — semver, a changelog, and a release that consumers upgrade to deliberately, instead of everyone importing HEAD from the workspace.

Where it plugs in: @mosaic/design-system is a workspace package today (Tokens & Primitives →). Publish it to a registry, pin each remote to a version, and now a token change is a release the catalog and cart teams adopt on their own schedule — the same independence you gave the remotes, applied to the shared layer.

Contract testing between shell and remotes

Section titled “Contract testing between shell and remotes”

What it teaches: how to catch a broken seam before deploy — that a remote still exposes ./Catalog, that <cart-app> still accepts the attributes the shell passes, that a bus event still carries the fields consumers read.

Where it plugs in: the mount/interop points from Module Federation Core → and the events from Cross-MFE Communication → are your contracts. Write tests the remote runs in CI that assert its exposed surface, and tests the shell runs against a remote’s published contract — so bus.emit('cart:add', …) renaming a field fails a pipeline instead of a user’s cart.

What it teaches: tracing a single user action across independently-deployed slices — which remote version rendered, which BFF answered, where a “add to cart” that never arrived actually broke.

Where it plugs in: every slice has a natural instrumentation point — the Hono BFFs for backend spans, the event bus for cross-MFE traces, and the resilience layer for remote-load metrics. Stamp a correlation id at the shell and thread it through the bus and every BFF call.

What it teaches: a pipeline where changing one slice builds, tests, and deploys only that slice — the operational proof of the independence the architecture promises.

Where it plugs in: Independent Deployment → established that a slice ships on its own. Wire it up for real: path-filtered CI in the monorepo so a change under apps/cart/ deploys the cart’s UI and BFF and nothing else, publishing a new remoteEntry.js the shell loads on the next visit.

Import maps as an alternative to Module Federation

Section titled “Import maps as an alternative to Module Federation”

What it teaches: that runtime composition isn’t only Module Federation — native browser import maps can resolve bare specifiers to versioned remote URLs, giving you runtime swapping with far less tooling (and different trade-offs: no built-in sharing negotiation or dependency dedupe).

Where it plugs in: it’s a considered alternative to everything in Module Federation Core →. Try composing one remote via an import map instead of the MF host config and feel the difference — what you gain in simplicity, what you give up in shared-singleton management. Knowing both is what lets you choose Module Federation rather than default to it.


That’s Mosaic. You built a storefront that several teams could own independently, in three frameworks, composed at runtime — and you can defend every seam in it.

Revisit the whole shape any time in the Architecture overview →, and take the code further at the source: github.com/avetavos/realworld-mosaic.