Today’s goal
Understand how front-end architecture changes when products, packages, teams, and deployments grow.
We will connect:
- reusable components and design systems;
- tokens, themes, accessibility, documentation, and versioning;
- package APIs, ownership, workspaces, and monorepos;
- task graphs, affected builds, and caching;
- platform teams and golden paths;
- micro-frontend composition and runtime independence;
- Module Federation, contracts, failure containment, and observability;
- migration strategy and architecture decisions at scale.
By the end of today you can
- distinguish a component library from a design system;
- define raw and semantic design tokens;
- design stable package APIs and release policies;
- decide when a monorepo or separate repositories help;
- model dependency direction and affected builds;
- explain why micro-frontends are organizational and deployment architecture;
- choose server, client, build-time, or runtime composition;
- design contracts, failure boundaries, and observability;
- evaluate Module Federation trade-offs;
- recognize when a modular monolith is the better answer.
Scale changes the nature of front-end problems
At small scale, a change may affect one application.
At larger scale, the same change may affect:
- several products;
- multiple teams;
- package consumers;
- release trains;
- shared tokens and accessibility;
- deployment and runtime contracts.
The architecture must make change impact visible.
Technical scale and organizational scale differ
technical scale → code, builds, bundles, runtime complexity
organizational scale → teams, ownership, coordination, release authorityA micro-frontend does not solve a team-ownership problem automatically.
A monorepo does not solve a dependency-design problem automatically.
Prefer stable shared concepts
Good shared concepts often include:
Button
Dialog
Field
Tabs
tokens and themesBe careful sharing a component whose behavior is actually product-specific:
ApprovalWorkflowPanel
RegionalTaxEditor
CataloguePricingCardShare the stable concept, not the current visual coincidence.
Shared packages should represent responsibility
shared/ui reusable interaction and visual primitives
shared/tokens semantic design vocabulary
shared/config agreed tooling policy
domain/catalogue product-specific vocabularyDo not make a shared package the default home for anything that might be reused.
Why micro-frontends are considered
They may help when:
- teams need independent deployment;
- domains have different release cadence;
- a platform must integrate separately owned products;
- migration from a legacy application must be incremental;
- organizational boundaries are stable and meaningful.
They introduce coordination costs of their own.
Independent frameworks are not automatically better
Different teams may choose different frameworks.
That can support local autonomy but creates:
- duplicate runtimes;
- inconsistent accessibility;
- design drift;
- larger bundles;
- harder shared behavior.
Use multiple frameworks only when the boundary and trade-off are justified.
Signs micro-frontends are probably unnecessary
Warning signs:
- the only reason is “the app is large”;
- teams need to share mutable state constantly;
- one team owns the whole product;
- independent deployment is not actually required;
- integration testing is weak;
- the same design system and framework are already tightly coupled.
Start with a modular monolith and re-evaluate.
Avoid architecture by organization chart alone
Team boundaries are evidence, not the entire design.
Also examine:
- business capability boundaries;
- data ownership;
- user journeys;
- release frequency;
- failure containment;
- security and performance requirements.
Architecture should reflect durable responsibilities, not temporary reporting lines.
Practical stages 1–6: foundations and contracts
- Identify repeated foundations, primitives, and domain components.
- Define token ownership and semantic naming.
- Create a small package boundary and public API.
- Document compatibility, versioning, and affected consumers.
- Map team ownership.
- Add an accessibility contract.
Keep domain-specific behavior with the product team.
Practical stages 7–12: package and repository architecture
- Simulate a breaking change.
- Create workspace packages.
- Enforce package public APIs.
- Draw the package dependency graph.
- Add ownership.
- Add shared tooling.
Verification: the shared package has a small stable surface and does not become a hidden global dependency.
Practical stages 17–22: micro-frontend contracts
- Model route-level app separation.
- Build a micro-frontend decision record.
- Build a small federation demo.
- Add remote failure handling.
- Explore shared dependencies.
- Add an integration contract.
Make runtime loading, version compatibility, fallback, and observability explicit.
Practical stages 23–29: boundary and final architecture
- Avoid shared in-memory domain state.
- Add a custom event.
- Explore CSS collision.
- Use the design system across host and remote.
- Draw the runtime architecture.
- Compare three architectures.
- Create the final scaling ADR.
Compare a modular monolith, route-level separation, and runtime federation.
Troubleshooting guide (Part 1)
| Symptom | Likely cause |
|---|---|
| Shared package accepts every prop | The concept is not stable or API is too generic |
| Design system contains domain workflows | Product behavior was promoted too early |
| Every package rebuilds for one change | Dependency graph or package boundary is too broad |
| Teams still coordinate every release | Runtime independence is mostly nominal |
| Remote failure breaks the whole shell | Failure containment was not designed |
Troubleshooting guide (Part 2)
| Symptom | Likely cause |
|---|---|
| Different remotes look inconsistent | Token, component, or version governance is weak |
| Micro-frontends share a giant store | Durable contracts were replaced by hidden coupling |
| Monorepo feels slow and opaque | Task graph, affected builds, or ownership is unclear |
| Security assumption follows team ownership | Team boundary is not a runtime isolation boundary |
Completion checklist
- shared concepts are stable and intentionally owned;
- tokens distinguish raw values from semantic meaning;
- public package APIs are small and documented;
- accessibility is part of the shared component contract;
- versioning and deprecation have migration paths;
- package dependency direction is enforceable;
- monorepo tasks and affected builds are observable;
- platform defaults are supported but not needlessly mandatory;
- micro-frontends have durable contracts and failure fallbacks;
- scaling decisions are measured against user and team outcomes.
Misconceptions to leave behind (Part 1)
| Misconception | Better mental model |
|---|---|
| A design system is a component library | It is a product of foundations, behavior, docs, and governance |
| Tokens are just CSS variables | Tokens are semantic cross-platform decisions |
| More abstraction means more reuse | Shared abstractions create coordination cost |
| A monorepo means one application | It is a repository and package organization choice |
| Workspaces and monorepos are identical | Workspaces coordinate packages; architecture needs boundaries |
| Micro-frontends are tiny components | They are independently owned application capabilities |
| Micro-frontends are always more scalable | They trade local autonomy for integration complexity |
Misconceptions to leave behind (Part 2)
| Misconception | Better mental model |
|---|---|
| Independent deployment means no coordination | Contracts, versions, and runtime failures still coordinate |
| Module Federation prevents remotes from breaking hosts | Runtime loading requires compatibility and fallback |
| Shared dependencies are always better | They reduce duplication but increase coupling |
| Different teams require different frameworks | Team boundaries do not automatically justify runtime diversity |
| Micro-frontends provide security isolation | Same-origin code often shares trust |
| Full-page navigation is outdated | It can provide valuable isolation and recovery |