SPA
Single-page application: one HTML shell, with the client rendering routes and fetching data as JSON.
in practiceDashboards and apps behind login; slow first load and SEO limits on content pages.
From rendering strategies to org charts: SPA, MPA, SSR, SSG, islands and edge; micro-frontends and design systems; offline, CRDTs and real-time; state placement; code structure, migrations, ADRs and Conway's law.
How pages are rendered, how apps are composed, and how data moves and syncs.
Single-page application: one HTML shell, with the client rendering routes and fetching data as JSON.
in practiceDashboards and apps behind login; slow first load and SEO limits on content pages.
Multi-page application: each navigation loads a new server-rendered HTML document.
in practiceContent sites, e-commerce listings; cross-document View Transitions and Speculation Rules make it feel app-like.
Server-side rendering: producing HTML for a request on the server, then hydrating it on the client.
in practiceNext.js, Remix, Nuxt; faster first content and SEO at the cost of server work and hydration.
Static site generation renders pages at build time; incremental static regeneration rebuilds them in the background after a time or on demand.
in practiceDocs, marketing, blogs; product pages revalidated every 60 seconds.
A mostly static page with isolated interactive components hydrated independently.
in practiceAstro islands; a product page where only the cart button and gallery ship JS.
CSR, SSR, SSG, ISR, streaming and RSC chosen per route by how personal, fresh and interactive it is.
in practiceMarketing static, product pages ISR, checkout SSR, dashboard CSR, all in one app.
Splitting a frontend into independently built and deployed apps owned by different teams, composed at runtime or build time.
in practiceModule federation, route-level splits; the cost is consistency, duplication and version skew.
Running server code at CDN edge locations close to users, for low-latency personalisation and rendering.
in practiceEdge functions and middleware for geo, auth checks and A/B assignment; data still far away is the catch.
A server layer shaped for one client, aggregating backend services and holding credentials.
in practiceOne call per screen instead of seven from the browser; tokens kept off the client.
Designing so the app reads and writes locally first and syncs with the server when it can.
in practiceField-work apps, note apps, POS in patchy networks; IndexedDB, queues and conflict handling.
A conflict-free replicated data type: data structures whose replicas can be edited independently and always merge to the same result.
in practiceCollaborative editors (Yjs, Automerge), offline-capable lists and documents.
Keeping clients current with server state via push (WebSocket, SSE) with snapshots, deltas, sequence numbers and resync on gaps.
in practicePrice tickers, presence, chat, collaborative cursors.
How UI, state and code are organised, and how the organisation shapes them.
Tokens, components, patterns and guidance shipped as a versioned product that other teams build with.
in practiceMaterial, Polaris, Carbon; the internal UI package and its docs site.
A component that provides behaviour, state and accessibility but no styles, for teams to skin.
in practiceRadix, React Aria, Headless UI, Ark; the design system styles them.
A set of components that share implicit state through context (Tabs, Tabs.List, Tabs.Panel), giving flexible composition.
in practiceSelect, Tabs, Accordion APIs in design systems.
Where state lives and how it changes: local, lifted, context, a client store (Zustand, Redux) and a server-state cache.
in practicePutting server data in Redux as a common anti-pattern; URL state for filters.
Keeping shareable view state (filters, sort, page, tab) in the URL so links, back and refresh work.
in practiceSearch and dashboard filters; nuqs and router search params.
Storing entities once by id and referencing them, so an update shows everywhere it appears.
in practiceApollo and Relay caches, RTK entity adapters; the same user in a list and a header.
A unique key sent with a mutation so a retried request is applied once, not twice.
in practicePayments and transfers retried after timeouts; the Idempotency-Key header.
Organising code by feature or domain (checkout/, search/) rather than by type (components/, hooks/), with rules on what may import what.
in practiceOwnership via CODEOWNERS per folder; lint rules enforcing boundaries.
Replacing a legacy system piece by piece behind a routing layer until nothing of the old remains.
in practiceMoving routes from a legacy app to a new framework one at a time.
Architecture decision record: a short document of a decision, its context, options and consequences, kept with the code.
in practicedocs/adr/0012-use-tanstack-query.md; the history new staff engineers read first.
One codebase and deployment serving many customers or markets, with configuration and data isolation per tenant.
in practiceCountry config for currencies, KYC flows and features in a pan-African fintech.
Systems end up shaped like the communication structure of the organisation that builds them.
in practiceMicro-frontends mirroring team boundaries; the inverse Conway manoeuvre to shape the org for the architecture you want.