Back to Articles
Frontend Architecture, Micro-Frontends, and Monorepos: A Senior Field Guide

Architecture · Frontend

Frontend Architecture, Micro-Frontends, and Monorepos: A Senior Field Guide

September 2026 · 14 min read

Senior frontend work is less about shipping another screen and more about choosing how teams, codebases, and runtime boundaries scale together. After five years building production React and Next.js systems—insurance platforms, mini apps, RTL admin panels, and PWAs—I keep returning to three decisions that shape everything else: how we structure the frontend, when micro-frontends help (and hurt), and how a monorepo should earn its complexity.

Frontend architecture that survives real products

A healthy frontend architecture starts with clear ownership of domain boundaries, not folder fashion. Feature modules, shared UI kits, and data-access layers should map to how the product actually changes. In practice that means:

  • Colocate by capability (enrollment, claims, checkout) instead of dumping everything into components/ and hooks/.
  • Push contracts to the edges: Zod (or similar) at API boundaries, typed DTOs, and explicit error models so UI code stops guessing.
  • Separate “shell” concerns (auth, layout, i18n, telemetry) from feature logic so teams can move independently without rewriting navigation every sprint.
  • Design for RTL and performance early if your market needs them—retrofitting Emotion RTL, Persian dates, or image-heavy dashboards is expensive.

Framework choice matters less than these seams. Next.js App Router, React 19, and TanStack Query are tools; the architecture is the graph of dependencies you allow between features.

Micro-frontends: independence with a tax

Micro-frontends shine when multiple teams ship the same product surface on different cadences—think checkout vs. account vs. ops console—or when you must embed UI inside another host (messaging mini apps, partner portals). They are the wrong default for a single team building one coherent product.

If you adopt them, treat these as non-negotiable:

  • A real composition strategy: module federation, native federation, iframes, or edge composition—pick one and document failure modes.
  • Shared runtime contracts: auth tokens, theme tokens, routing basenames, and analytics events must be versioned like APIs.
  • Design system discipline: without a shared package for primitives, every MFE invents its own button and your brand collapses.
  • Observability per remote: bundle size budgets, error boundaries per island, and release ownership so one remote cannot take down the shell silently.

The senior call is often not to split. A well-modular monolith (or a modular Next.js app) with clear packages is cheaper until organizational scale forces independence.

Monorepos: one repo, many contracts

A monorepo is not “all code in one Git folder.” It is a workspace graph with explicit public APIs between packages. Done well (pnpm/npm workspaces, Turborepo or Nx, shared lint/test/build pipelines), it gives you:

  • Atomic cross-package refactors and shared types without publish-wait cycles.
  • A single source of truth for the design system and config (ESLint, TSConfig, CI).
  • Faster CI via task caching when package boundaries are honest.

Done poorly, it becomes a junk drawer: circular imports, “shared” packages that import everything, and builds that recompile the world. Guardrails I insist on:

  • Package boundaries enforced (dependency cruiser / Nx tags / ESLint restrictions).
  • Apps depend on libraries, not the reverse.
  • Versioned change management for anything shared across deployables.
  • CI that fails on boundary violations, not only on unit tests.

How the three fit together

Use a monorepo to share the design system and domain types. Keep a modular frontend as the default deployable. Introduce micro-frontends only where team or runtime isolation is a product requirement—then compose those remotes as packages in the same monorepo so contracts stay visible.

That combination—modular frontend, optional MFEs, disciplined monorepo—is what lets senior teams move fast without painting themselves into a distributed mess.

Practical checklist before you split or merge

  1. Do we have more than one team blocked on the same release train?
  2. Do we already have a shared UI package and typed API contracts?
  3. Can CI cache and test packages independently?
  4. Is the shell ready to own auth, routing, and failure isolation?
  5. If we stay modular in one app for six more months, what do we lose?

If you cannot answer those clearly, invest in modular architecture and monorepo hygiene first. Micro-frontends will not fix unclear ownership—they will amplify it.