Micro-frontends

Pick the approach by the boundary you need, not by how the code is split. The question is: how much should these two apps trust each other?

Choosing an approach

ApproachUse it forSecurity boundaryIntegration
iframe (mf-frame + mf-bridge)A panel from another team or another trust level inside your page: an agent console in a back office.Separate origin and sandbox; talks only through a checked, typed channel; headers on both sides say who may frame whom.Its own layout box; height comes over the bridge; no shared styles.
Web Component (mf-element)A widget tied to the host's layout that the host trusts as its own code.None between the two: the element runs in the host's origin and sees what the page sees.Shadow DOM keeps CSS apart; props and events cross directly.
Multi-ZonesWhole pages split by path on one site: /docs from one app, /app from another.Same origin, so shared cookies; each zone sends its own CSP.Navigating to another zone is a full page load.
Module FederationNot recommended with the App Router.Remote code loaded at runtime into the host's origin, outside your build's integrity checks.Server Components, streaming and the App Router's bundling are not designed for it; the Next.js plugins target the Pages Router.
  • Different teams, different release cycles or different trust: iframe.
  • One team, one trust level, a piece that must sit inside the host's layout: Web Component.
  • Separate apps that each own whole pages of one product: Multi-Zones.
  • Never pass a token across any of these boundaries: keep the session in a same-site HttpOnly cookie, or put a BFF in front of the API (bffStream).

Multi-Zones on the same site

The main app serves the site and rewrites the paths another zone owns to it. The browser only ever sees one origin, so the session cookie, CORS-free API calls and the same-origin rules of api() keep working.

main app: next.config.ts
const DOCS = process.env.DOCS_ZONE_URL; // e.g. https://docs-zone.internalconst config: NextConfig = {  async rewrites() {    return [      { source: "/docs", destination: `${DOCS}/docs` },      { source: "/docs/:path+", destination: `${DOCS}/docs/:path+` },      { source: "/docs-static/:path+", destination: `${DOCS}/docs-static/:path+` },    ];  },};
docs zone: next.config.ts
const config: NextConfig = {  basePath: "/docs",  // Its own prefix, so its assets never collide with the main app's /_next.  assetPrefix: "/docs-static",  experimental: {    // Requests arrive through the main app's host: allow it for Server Actions.    serverActions: { allowedOrigins: ["www.example.com"] },  },};
  • Same-site deployment. Serve every zone through the main app's host. Keep the zones themselves off the public internet (or behind the same edge), so nobody reaches them around the main app's headers.
  • Cookie scope. One origin means one cookie jar: set the session cookie HttpOnly; Secure; SameSite=Lax with Path=/ when every zone needs it, or a narrower Path for a zone-only cookie. Never set Domain to a parent domain just to share it: that also shares it with every other subdomain.
  • CSP per zone. Each zone renders its own pages, so each one applies securityHeaders({ nonce }) in its own middleware with its own nonce. The main app's rewrite passes the zone's response headers through; do not let the main app overwrite them with a CSP whose nonce the zone never saw.
  • Navigation. A link into another zone is a full page load: use a plain <a> rather than next/link for those paths.
  • Idle and logout. Zones share the cookie, so signing out in one signs out everywhere; run useIdleTimeout in each zone.

Embeds on another origin

  • Host: hostAppHeaders({ nonce, frameOrigins }) and <MfFrame>; embedded app: embeddedAppHeaders({ nonce, hostOrigins }) and useReportHeight.
  • Keep theme, locale and session in step with mf-context; logout in the host ends the embedded session.
  • A cross-site iframe gets its cookies only with SameSite=None; Secure (and the browser may still block third-party cookies). Prefer putting the embedded app on a subdomain of the same site, or authenticate it through the host's BFF.