Spokes.wiki Search About

Synthesis — Frontend Architecture

The evolving thesis. This spoke was spun out on 2026-08-12 at the curator's approval, from three sources that sat in the hub's holding pen over six weeks under the tag frontend-architecture: flutter-large-app-structure (parked 2026-06-30), micro-frontends-migration (2026-07-14) and open-saas (2026-08-10). Each had been declined by every existing spoke, and the declines are the charter — see CLAUDE.md → Scope boundary.

Current thesis

One question, three answers, and the question is not technical. The founding sources all address who decides an application's structure, from three positions:

Read together they say the decision does not vanish when it is delegated. Adopting a boilerplate is a structural choice, made by someone the adopting team will never meet.

Boundaries beat patterns

The two architecture sources agree on a claim neither one demonstrates. flutter-large-app-structure: "Large applications rarely fail because they lack patterns. They fail because ownership boundaries become unclear." micro-frontends-migration: micro-frontends optimize for independence, because "when you optimize for reusability, you create coupling." One is talking about folders and the other about deployables, and they arrive at the same sentence.

They also agree on a specific corollary — global state is the enemy, and features or units should own their own. Both name roughly the same exceptions (authentication, theme, localization). Two sources at different scales, in different ecosystems, converging on one rule is the strongest signal this small corpus currently holds.

Enforcement is what separates the two scales

A micro-frontend boundary is enforced by deployment: crossing it requires a network call or a hard navigation. A feature-first-structure boundary is enforced by discipline: nothing stops an import except review, or a tool of the kind micro-frontends-migration names (ts-arch blocking unwanted imports, a bundle-size fitness function). The same thesis with two very different amounts of teeth, and no source here compares how well each holds.

The most useful number in the corpus is not about modularity

One team went from 3 deployments a month to 25 a day per team after a micro-frontend migration — and micro-frontends-migration attributes it to the "safe net" of edge-compute canaries and rollback by configuration change, not to the architecture. Read carefully, the spoke's headline figure is evidence about reversibility. That is a caution against the reading everyone will want to make of it.

Duplication has a price, and one source pays it

"Duplication is far cheaper than the wrong abstraction" is a position, not a truism. The evidence offered is a shared header changed once in three years, against a team that spent four months shipping nothing to refactor global state. Thin, but it is arithmetic rather than taste, which is more than the rest of the domain manages.

The corpus's own weak spot

This is a domain that argues rather than measures, and the founding corpus shows it plainly. Of three sources: one is a practitioner reporting migrations he ran, with figures and named failures (T2); one is a first-party repository stating what it ships (T1, and promotional by construction); and one cites nothing at all — no study, no case, no measurement, no codebase named (T3, and its own page says so).

So the pattern to watch for is not disagreement between sources but confidence without evidence. A structure diagram is not a finding. CLAUDE.md carries this as an edge rule: record what a source rests on, every time.

Open questions

"The framework decides" is two claims, not one (added 2026-08-15)

The spine has treated who decides the structure as a single axis running from the team to the framework, with wasp at the framework end: a compiler generates front-end, back-end and deployment from main.wasp.ts, so the structure "is not the author's to arrange." nextjs, the category's most-adopted member, does not sit anywhere on that line. It sits on both ends at once.

Routing structure: decided, absolutely. Folders are URL segments, page is what makes a route public, layout nesting follows the folder tree, and the reserved filenames (layout, template, error, loading, not-found, route) are simultaneously the API and the file layout. You cannot opt out and keep the framework.

Code organization: refused, explicitly. The docs call Next.js "unopinionated" about how project files are organized and colocated, then list three strategies without ranking them — code outside app/, code in top-level folders inside app/, or code split into the route segments that use it — and tell the reader to pick one and be consistent.

That third option is feature-first-structure, demoted from an argument to a menu item.

The consequence for this spoke is uncomfortable and worth keeping: the two sources that argue hardest about structure are arguing about the half the dominant framework deliberately leaves open. flutter-large-app-structure and micro-frontends-migration both concern where feature code lives, who owns state, and which unit ships — and none of that is what Next.js decides. It explains why the argument has no resolution better than either source does: there is no framework verdict to appeal to, because the framework declined to give one.

One vocabulary collision to keep straight. Route groups (marketing), (shop) organize routes "by site section, intent, or team" — team-shaped folders inside one deployable. micro-frontends means a team that deploys independently. Same word, opposite deployment story, and the distinction is the one micro-frontends-migration spends its first section drawing against components.

The framework's decisions have a schedule (added 2026-08-20)

nextjs-16-3 complicates the section above enough to sit apart from it. Reading the docs gave a clean split — routing decided, code organization refused. Reading a release gives a third category: things the framework has not decided for you yet.

cacheComponents is the case. It puts cache boundaries on components, which is a question about where computation happens and what is shared between routes — structural by any reading. Today it is a flag a team opts into. The release says it becomes the default in a future major version. So the honest description of the axis is not the framework decides versus the team decides, but who decides, and when. wasp decides everything before the first line is written and is legible about it. Next.js decides some things later, into a codebase already built on other assumptions.

Two smaller items from the same release sharpen it:

And the evidence problem here is the mirror of the corpus's usual one. The spoke's standing complaint is that this domain argues without measuring. This source measures constantly — 90% less dev memory, 21.5 GB to 2 GB, 5.5× repeat builds, 22% more requests — and every one of those numbers belongs to vercel, which makes the framework and sells the hosting. The only independent readings are one early adopter relayed by The Register (~4 GB to 1.5 GB) and a Reddit thread. Meanwhile the best-evidenced part of the page is the list of things that break, which came from the project's own feedback discussion. Confident numbers from an interested party are not the opposite of confidence without evidence; they are the same gap wearing better clothes.

Enforcement has a third mechanism, and it is the weakest (added 2026-08-22)

The section Enforcement is what separates the two scales sets out two ways a boundary is held: deployment (crossing a micro-frontend boundary requires a network call or a hard navigation) and discipline (nothing stops an import into a feature-first-structure except review or a lint rule). module-federation — the mechanism micro-frontends-migration names four times without describing — belongs to neither.

Its boundary is enforced at runtime, by version negotiation in a share scope. Both sides must agree on a shareKey or the negotiation silently does not happen and each ships its own copy; singleton: true loads the higher version and warns whoever asked for the lower one; a requiredVersion mismatch resolves to "the smallest version available" with a warning. So the violation of this boundary is not a rejected import and not a review comment. It is two copies of React on one page, or a framework silently upgraded under a team that did not ask — found in a browser, in production, by whoever is looking.

That ranks the three honestly. Deployment enforcement fails loudly and early: the call does not compile or the network request 404s. Review enforcement fails quietly but locally: a bad import sits in one repository where a tool can find it. Runtime negotiation fails quietly and remotely, in someone else's application, at a moment nobody chose. And the corpus already holds the field evidence: micro-frontends-migration reports React Router against Module Federation needing a manual downgrade — this negotiation, resolved by hand.

The uncomfortable part is what shared is for. Micro-frontends are chosen for independence, on the argument that "when you optimize for reusability, you create coupling." A share scope is reusability, deliberately reintroduced, because shipping four copies of React is not tolerable. So the tool the pattern is most often built on exists to soften the property the pattern is chosen for, and nothing held here measures what that costs.

One smaller thing, on the spoke's own axis. Module Federation defines itself as "an architectural pattern for the decentralization of JavaScript applications (similar to microservices on the server-side)" — the analogy the open questions ask about, stated by the tooling as its definition rather than as a comparison. But the unit it federates is a module, so the same plugin serves a genuine team-owned deployable and an ordinary shared component library. Adopting it decides nothing about who owns what. Where wasp decides the structure and nextjs decides half and refuses the other half, this one decides nothing at all while describing itself as an architecture.

Enforcement has a fourth mechanism: capability grants at the plugin boundary (added 2026-10-05)

The three mechanisms held so far all police a boundary between the application's own parts: deployment (a network call), discipline (review and lint) and runtime version negotiation (module-federation). emdash-1-0 adds a boundary between the application and code its owner did not write, and holds it differently. A plugin runs in its own isolate (a Dynamic Worker, or a workerd service on Node.js), starts with private storage and nothing else, and every further reach (content, media, users, secrets, network) is a permission the plugin declares and an admin approves.

That makes it the first boundary in the corpus that fails closed. A violation is a refused call, not two copies of React on a page. It also moves the decision, again: the framework does not choose the structure of the plugin, but it chooses the edges of every plugin, and the person approving a grant decides how wide the edge is. The decider is now a fourth party, the site admin, who is neither the team, the organization nor the framework author.

The registry half is the same idea one level up. Publishers keep their signed records in their own AT Protocol accounts and the catalog can only hide a listing, so no central party can rewrite a release. That is ownership by construction, the property micro-frontends gets from separate deployment, applied to distribution.

What it rests on: a vendor announcement and design argument. No audit, escape report or incident history is cited, and only free plugins exist, so the strong claim ("secure") is untested where it would matter, in a paid marketplace. The one operational figure (the Cloudflare Blog at 5,000 req/s) is Cloudflare describing its own site. Held at T3.

Growth edges

Ranked; each names the kind of source that would close it (see ../QUALITY.md → Growth edges).

  1. Any measured outcome of a structural choice. The spoke's thesis is currently unfalsifiable. — needs: a T1/T2 before-and-after on one codebase — defect rate, lead time, incident count or a validated cognitive-load instrument — not another architecture guide.
  2. The case against micro-frontends, from someone who tried them. Everything held is by an advocate. — needs: a published retrospective of a migration that was reversed or judged not worth it.
  3. Enforcement compared. (Now four mechanisms; the sandbox one has no failure data either.) — needs: an account of architecture-testing in practice (ts-arch, dependency-cruiser, ArchUnit-style tools) with what it caught, or a study of import-boundary violation rates.

Coverage edges — things this spoke's domain plainly includes and does not hold; an ordinary solid source closes any.

  1. React meta-frameworks. Next.js, Remix and Gatsby — one of three closed 2026-08-15: nextjs paged from its own project-structure docs (T1, v16.3.1). It did more than fill a hole, splitting the spine's axis in two (see above). — still needs: Remix and Gatsby, one page each from their own architecture documentation. Until then the spoke has one framework's answer and calls it the category's.
  2. Monorepo versus polyrepo. micro-frontends-migration says the choice moves architecture, organization and culture together, and no page covers it. — needs: Nx or Turborepo documentation plus one migration account.
  3. The modular monolith. The position that says don't distribute, which the corpus needs in order for micro-frontends to be a choice rather than a default. — needs: a write-up arguing it, ideally with a codebase behind it.
  4. Module Federation itself. Named repeatedly as the mechanism and never described. — CLOSED 2026-08-22 by module-federation, from the project's own docs and repository (T1, v2.8.2). A coverage edge closing cleanly on first contact, which is the third time that has happened here against zero clean closes for a question edge. It also did more than fill the hole: the shared scope is a third enforcement mechanism, and the spine section above ranks it below both of the two it already held.
  5. What runtime sharing costs. HALF-CLOSED 2026-08-25 (research pass) by module-federation-singleton-postfix-bug (module-federation/core #4078, T1): a semver prerelease suffix defeats singleton: true, every remote loads its own copy, and the consumer had asked for *. The reporter's own control — drop the suffix and it works — makes it a defect rather than a misconfiguration. It confirms the enforcement finding with a case and supplies a trigger nobody would guess, and the report was closed not_planned by an inactivity bot, so a team evaluating this architecture meets no artifact warning them first. Successor (edge 8a): still no accounting. That incident carries no measurement — no duplicated bytes, no time-to-detection, no downstream effect on the team that was upgraded under. — needs: a duplicate-bundle measurement across a federated application, or a post-mortem that states how long a two-instance state ran before anyone noticed. The vendor-consultancy write-ups that carry figures of this kind (11.9 MB bundles, a 7.5 → 10.5 MB regression) were found on 2026-08-25 and rejected at the bar — all T3 marketing for migration services, with no stated method.

Contradictions / tensions

No factual conflicts yet — three sources at three scales, largely non-overlapping. The live tension is about genre, and it was live before the spoke existed: two founding sources are architecture guides that argue a thesis; open-saas is a template that embodies one silently, and the hub's own park record noted that the same cluster had already excluded a build-along tutorial on exactly that distinction. The spin-out went ahead with the objection recorded rather than dissolved (boilerplate). Expect it to recur: this domain's artifacts are guides, repositories and talks, and they support very different kinds of claim.

Cross-spoke adjacency

Index — Frontend Architecture Wiki

Catalog of every page, grouped by schema.org @type. Spine: synthesis (thesis), log.md (history), this file (catalog). Spun out of the hub _inbox on 2026-08-12 from three sources parked over six weeks. This domain argues more than it measures — record what each source rests on (a migration the author ran, a codebase they shipped, or reasoning alone), and keep the tier honest.

DefinedTerm (concepts / patterns)

SoftwareApplication

NewsArticle (sources)

SoftwareSourceCode (sources)

PresentationDigitalDocument (sources)

Article (sources)

Person (entities)

EducationalOrganization (entities)

Synthesis