Micro-frontends skill for Codex

Split the frontend only when teams truly need it. Codex starts by questioning whether independent deploys are actually needed, and recommends a modular monorepo when they are not. When they are, it compares federation, import maps, web components, route splits and iframes, then implements the choice with singleton React and design-system sharing, typed exposed modules, namespaced events, CSS isolation, pinned remote versions and fallbacks so one failing remote never blanks the shell.

  • Frontend
  • $micro-frontends
  • 176 lines
  • 2 files
  • ~1,950 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- micro-frontends

Installs to ~/.agents/skills/micro-frontends/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $micro-frontends, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Decides whether and how to split a frontend across teams - build-time packages, Module Federation 2 (webpack, Rspack, Vite), import maps and Native Federation, web components, iframes or server-side composition - then implements the chosen integration with shared singletons, versioned contracts, routing ownership, CSS isolation and failure fallbacks. Use when several teams ship one web app, when evaluating Module Federation, when a remote breaks the host, or when duplicate React copies and style leaks appear.

Use it when

  • Several teams ship parts of one web app and block each other's releases
  • Evaluating or implementing Module Federation, import maps or web component composition
  • A remote breaks the host, loads duplicate dependencies or leaks styles

Use something else when

How to check the result

Each remote runs standalone and inside the shell, the network tab shows a single react-dom chunk, and blocking a remote's URL renders its fallback while the rest of the app keeps working.

The mistake it prevents

Declaring React as a singleton without requiredVersion, which hides version skew until hooks fail in production.

~/.agents/skills/micro-frontends/SKILL.md

--- name: micro-frontends description: Decides whether and how to split a frontend across teams - build-time packages, Module Federation 2 (webpack, Rspack, Vite), import maps and Native… license: MIT ---

Micro-frontends are an organisational tool, not a performance one. A good outcome lets teams deploy independently without coordinating releases, while users see one fast, consistent app. If teams do not need independent deploys, a well-structured monorepo is cheaper and should be the recommendation.

Step 1: challenge the premise

Ask (or find in docs and AGENTS.md) before designing anything:

  • How many teams own UI, and how often do they block each other’s releases today?
  • Do they share a framework and design system, or genuinely differ?
  • Is the pain build time, deploy coupling, or code ownership?
AnswerRecommendation
One or two teams, same release trainModular monorepo (pnpm workspaces + Nx/Turborepo), no runtime composition
Several teams, same framework, blocked on releasesModule Federation with a shared shell
Several teams, different frameworks or long-lived legacyRoute-level composition: separate apps per path behind a reverse proxy, or web components
Embedding a third-party or untrusted UIiframe with postMessage contract
Content sites, SEO critical, mostly staticServer-side or edge composition (fragments assembled per request)

Write the decision down as an ADR with the rejected options; the trade-offs are what future teams need.

Integration options compared

ApproachIndependent deployShared depsIsolationMain cost
Build-time npm packagesNo (host rebuild)Yes, dedupedLowRelease coordination
Module Federation 2YesRuntime negotiated singletonsLow (same JS realm)Version skew, build tooling coupling
Import maps / Native FederationYesVia import mapLowBrowser ESM only, smaller ecosystem
Web componentsYesUsually duplicated per appShadow DOM for stylesBundle duplication, framework interop
Route-level split (reverse proxy)YesNoneHighFull page loads between areas
iframesYesNoneVery highLayout, focus, a11y, performance

Module Federation 2 setup

Use @module-federation/enhanced (webpack/Rspack) or @module-federation/vite. Install needs network. Remote:

// checkout/rspack.config.js (webpack is the same shape)
const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack');
const deps = require('./package.json').dependencies;

module.exports = {
  output: { uniqueName: 'checkout', publicPath: 'auto' },
  plugins: [
    new ModuleFederationPlugin({
      name: 'checkout',
      filename: 'remoteEntry.js',
      exposes: { './CheckoutPage': './src/CheckoutPage.tsx' },
      shared: {
        react: { singleton: true, requiredVersion: deps.react },
        'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
        '@acme/design-system': { singleton: true, requiredVersion: deps['@acme/design-system'] },
      },
      dts: true,               // generate and consume federated types
    }),
  ],
};

Host:

new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    // manifest URL enables runtime discovery, preloading and type hints
    checkout: 'checkout@https://cdn.example.com/checkout/mf-manifest.json',
  },
  shared: { react: { singleton: true, requiredVersion: deps.react }, 'react-dom': { singleton: true, requiredVersion: deps['react-dom'] } },
});

Consume with lazy loading and a boundary:

const CheckoutPage = lazy(() => import('checkout/CheckoutPage'));

<ErrorBoundary fallback={<CheckoutUnavailable />}>
  <Suspense fallback={<PageSkeleton />}>
    <CheckoutPage cartId={cartId} onComplete={goToConfirmation} />
  </Suspense>
</ErrorBoundary>

For per-environment remote URLs, register remotes at runtime from a config the shell fetches (the Module Federation runtime API), instead of rebuilding the host per environment.

Contracts between teams

  • Props or mount API: an exposed module exports a component or a mount(el, props) => unmount function. That signature is a public API: version it, type it (dts), and never break it without a deprecation window.
  • Events: cross-app communication through CustomEvent on window with namespaced names (checkout:completed) and a typed payload, or the URL. Never a shared mutable global store between independently deployed apps.
  • Routing: the shell owns top-level routes; each micro-frontend owns everything under its prefix (/checkout/*) and uses the shell’s history instance or basename.
  • Auth: the shell obtains the session; remotes receive a token getter, never read cookies or storage keys owned by another team.
  • Design system: one shared package as a singleton, versioned with semver; visual drift is the most visible micro-frontend failure.

CSS isolation

TechniqueUse when
CSS Modules or CSS-in-JS with unique prefixesDefault for federated React apps
Cascade layers (@layer shell, remote)Shell styles must win predictably
Prefixed utility classes (Tailwind prefix)Several apps use Tailwind with different configs
Shadow DOM (web components)Hard isolation is required

Global resets and body styles belong only to the shell. Grep remotes for :root, html, body and * selectors.

Failure handling

  • Every remote load has a timeout and a fallback UI; a down remote must not blank the shell.
  • Log remote load failures with the remote name and version to monitoring.
  • Pin remotes by version in production (versioned manifest URL or a deployment registry); “latest” remotes mean the host can break without any deploy of its own.
  • Keep a rollback path per remote: redeploying the previous remote version must be one step.

Performance

  • Shared singletons with incompatible requiredVersion load a second copy (or warn and break hooks). Check the network tab for duplicate react-dom chunks, and inspect the MF2 runtime’s __FEDERATION__ global (or the Module Federation Chrome devtools extension) to see which version of each shared package won.
  • Preload the remote entry for the likely next route; do not eagerly load every remote.
  • Budget each remote’s initial JS; one team’s heavy dependency taxes every page it appears on.

Testing

  • Each remote runs standalone with a dev shell for local work and its own tests.
  • Contract tests on the exposed API (types plus a render test with the documented props).
  • An end-to-end smoke suite in the integrated environment that loads every remote, run on every remote deploy, with the ability to block the deploy.

Gotchas

  • publicPath wrong on the remote: the entry loads but chunks 404 from the host’s origin.
  • singleton: true without requiredVersion hides version skew until hooks fail at runtime.
  • React context does not cross separately bundled React copies; a duplicated React means “Invalid hook call” or missing providers.
  • CORS and CSP must allow the remote origins for scripts and chunk loading.
  • SSR with federation multiplies complexity; validate the framework’s support (Next.js support is limited) before promising it.
  • Deploying the host and remotes in one pipeline step defeats the purpose; it is a distributed monolith.

Deliverable

## Micro-frontend decision
- Context: teams, release pain, frameworks
- Decision: <approach>, rejected: <options + reason>
- Contracts: exposed modules and signatures, events, route ownership
- Shared singletons and version policy
- Failure handling: timeouts, fallbacks, version pinning, rollback
- Rollout: first remote to extract, success metrics (deploy frequency, lead time)

Production rollouts of new remotes or changes to the shell’s remote registry affect all users: confirm with the user before deploying them.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Micro-frontends"
  short_description: "Split the frontend only when teams truly need it"
  default_prompt: "$micro-frontends Should we use Module Federation for our three frontend teams? Give me a recommendation"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem