Rendering architecture
Frontend architecture chosen for how your product is used
The right rendering model depends on who has to read the page first: a search engine, a returning user, or a device with a weak connection. We choose between client-side rendering, server-side rendering, static generation and hybrid frameworks like Next.js and Nuxt based on your content, your audience and how often your data changes.
SSR vs CSR vs static: which one fits?
| Approach | How it works | Good fit | Watch out for |
|---|---|---|---|
| Client-side rendering (SPA) | The browser downloads JavaScript and builds the page | Dashboards and tools behind a login | Crawlers see little content; first paint is slower on low-end phones |
| Server-side rendering (SSR) | The server sends ready HTML on each request, then the page becomes interactive | Stores, marketplaces, listings that change often and must be indexed | Server cost and hydration time |
| Static generation (SSG) | HTML is built once at deploy time | Documentation, marketing pages, blogs | A rebuild is needed when content changes |
| Incremental regeneration | Static pages are rebuilt in the background when data changes | Large catalogs with thousands of pages | Cache invalidation needs careful design |
| Hybrid (Next.js, Nuxt) | Each route picks its own model; server components stream HTML | A store with an account area, or a SaaS with public marketing pages | More moving parts, so the team needs clear conventions |
| Cross-platform (React Native, Capacitor, Tauri, Electron) | One codebase targets web, mobile and desktop | Products that need app-store presence or device hardware | Gaps between native and web APIs need planning |
A typical online store needs both. Product and category pages are server-rendered with structured data so search engines and AI assistants can read prices and availability. Cart, filters and checkout behave like a single-page app. Hybrid frameworks let one codebase do both.
A codebase that stays small and modular
Large frontends slow down when everything depends on everything else. We structure projects so that:
- UI components are presentational and get their data from outside.
- Business logic (pricing rules, validation, sync) lives in plain TypeScript modules that can be tested without rendering anything.
- Features are separate modules with enforced boundaries, so one team's change can't quietly break another team's screen.
- Each route loads only its own code, so adding a feature doesn't make every page heavier.
State and memory management
We separate the kinds of state that tend to get mixed together:
Server state
Data from your API lives in a query cache such as TanStack Query, with clear rules for refetching and staleness.
UI state
Open panels and selections stay local to components or in a small store like Zustand or Pinia.
URL state
Filters, tabs and pagination live in the URL, so views can be shared and bookmarked.
Persisted state
Drafts and offline queues go to IndexedDB.
POS terminals, kiosks and monitoring screens run for days without a reload. For those we test memory over long sessions and clean up subscriptions, timers and listeners, so the app doesn't slow down by the end of a shift.
Frontend security
We use what the browser offers to limit damage if something goes wrong:
- A Content Security Policy that blocks injected scripts, plus Trusted Types where supported.
- Subresource Integrity for third-party scripts.
- Session tokens in HttpOnly, Secure cookies instead of localStorage.
- Sanitizing any user-supplied HTML before rendering.
- Dependency auditing and locked versions in CI.
- Permissions Policy and sandboxed iframes for third-party widgets.
- No secrets in the client bundle, ever.
FAQ
Frequently asked questions
01Should we use Next.js?
If you have public pages that need search visibility and an app experience behind login, it's often a good fit. If your entire product sits behind a login, a client-side app with a fast static shell is usually simpler and cheaper to run.
02Can you migrate an old Create React App, AngularJS or Vue 2 project without stopping feature work?
Yes. We move it route by route behind a proxy, so the old and new app run side by side until the migration is done.
03Do you prefer a particular framework?
We prefer the one your team can maintain. The architecture decision record explains the choice so it can be revisited later.
Next step
Start with a review of what you have
Send us your repository or a staging link. We'll come back with the three changes that would make the biggest difference to your release speed, performance and reliability.
