| name | modern-frontend-architecture |
| description | Use when starting, scaffolding, or reviewing the architecture of a web frontend, or making any frontend architecture decision — framework/stack choice, client-server data, state management, routing/URL state, styling and design systems, i18n/RTL, server-side logging/observability, or deploy target. Triggers on new web-app setup, "which library/framework should I use", data fetching and mutations, global vs local state, component and design-system design, internationalization, and Cloudflare/self-host/Vercel deploy questions. |
Modern Frontend Architecture
House standard for web frontends. Take the Use default; open the reference for how + why.
Guiding rule: establish the boundary on day 1, defer the implementation. Default to the collection seam — don't build Electric. Pick the realtime transport — don't build the system.
Current best, not eternal truth — last reviewed 2026-08-24. The boundaries (the decisions and seams) below are durable; the named tools and versions filling them are the current best as of that review. If today's date is well past it, treat specific tool/version picks as possibly superseded — keep the decision, re-verify what best fills it now. This is the guiding rule applied to the skill itself: the seam is the commitment, the tool is the implementation.
Defer, don't duplicate: platform HTML/CSS/JS → modern-web-guidance · composition → vercel-composition-patterns · React perf → vercel-react-best-practices · motion → web-animation-design. The two vercel-* are companion skills — install them alongside this one (see README); if a target project doesn't have them, fall back to modern-web-guidance + first principles, don't inline their depth here.
Reference implementation: ultimate-ts-starter (github.com/Amir-Abushanab/ultimate-ts-starter) — copy patterns from it.
Defaults
| Decision | Use | Not | Why (when non-obvious) |
|---|
| Package manager | pnpm + catalogs · existing Bun toolchain: keep Bun, mirror the gates (bunfig minimumReleaseAge = 604800) | npm / yarn · Bun without the cooldown configured | pnpm takes precedence on greenfield; Bun ≥ 1.3 has the same enforced install gate (seconds, not pnpm's minutes) |
| Web stack | TanStack Start (default; SSR+SSG) · Astro only if super-SEO-critical or content-only | Next.js · Astro/split by default | one Start app covers mixed sites; reach for Astro only when SEO is paramount; Next couples rendering to its model + Vercel |
| Deploy | Cloudflare · self-host (first-class) | Vercel | |
| Lint / format | oxc (oxlint + oxfmt), error-only | ESLint+Prettier · Biome | Rust-fast and skips the TS compiler API, so TS 7 works today |
| Types | TS 7 native tsc, strict + noUncheckedIndexedAccess | TS 6 · loose | |
| Wire types | oRPC + zod · simple Hono-server projects: Hono RPC (hc<AppType>) | tRPC · hand-typed | OpenAPI-compatible, edge-agnostic; Hono RPC = same seam, no extra layer — graduate to oRPC at OpenAPI / non-TS consumers |
| Server data | oRPC → TanStack Query → TanStack DB collection (useLiveQuery, optimistic) | raw Query for entity data · hand-rolled cache writes | collection gives optimistic+rollback and the sync seam free — deletes ~80 lines |
| Loading / error | Suspense + ErrorBoundary | isPending / isError plumbing | |
| Memoization | React Compiler via oxc — react({ compiler: true }) + oxc-transform-react | manual useMemo / useCallback · babel-plugin-react-compiler (fallback only) | one Rust pass (compiler + JSX + Fast Refresh), ~10× faster, toolchain stays Babel-free |
| Client state | collection → zustand / xstate-store → XState | Context/useEffect webs · a hand-rolled FSM that keeps growing |
References
| For… | Read |
|---|
| stack · deploy · toolchain · repo skeleton | references/stack-selection.md |
| data · URL state · realtime | references/data-and-typesafety.md |
| where state lives | references/state.md |
| components · design system | references/design-system.md |
| internationalization | references/i18n-rtl.md |
| CI gates · git hooks · supply-chain · enforcement · the factory | references/agent-first-factory.md |
| rule → enforcer map · ratchets | references/enforcement-map.md |
| runtime security · CSP · headers · secrets · CSRF · XSS | references/security.md |
| server-side logging · wide events · client telemetry · sampling | references/logging.md |
Brownfield & hard constraints
These are day-1 greenfield defaults. On an existing codebase, or when a real constraint (client mandate, an existing Next/Vercel app, the team's skill set) rules out the house choice:
- Adopt the seam, not necessarily the tool. The durable value is the boundaries — typed wire boundary, the collection/store seam, one realtime transport, token-only components. Most are portable onto another stack; take the seam even where the tool differs.
- Non-conformance isn't a reason to migrate. A rewrite is justified by a concrete cost the current choice imposes, not by "it's not the table." Match the default on new surfaces; migrate an existing one only when it's already being changed for another reason (strangler, not big-bang).
- The "Never"s are day-1 defaults, not migration mandates. Already on Next.js/Vercel and it works? Don't rip it out — adopt the portable seams now, reach for the house stack at the next greenfield boundary (new app, major rewrite). Migration specifics →
references/stack-selection.md.