EverProduct
Frontend

Stage 04 · The Application

The Other End of the Wire: Data, Routes and Where Code Runs

Two questions decide the shape of a real application: how a person moves between screens, and at what moment the HTML gets built. Frameworks come and go; those two questions don't.

Up to now you've had components and state. An application adds two things: several screens with addresses, and a server on the other end of the wire.

That produces two decisions, and they shape everything else. How does a person move between screens? And — the one people skip, then pay for — at what moment, and on whose machine, does the HTML get built?

Routing: the URL is part of your interface

In a traditional site every link is a full page load: the browser throws away the page, asks the server, and renders a new document. In an application the router intercepts that, changes the address without a reload, and swaps the part of the screen that differs.

The pieces you'll meet are the same everywhere: routes mapping a URL pattern to a screen, parameters in the path, query strings for filters and searches, nested layouts so a shared shell survives navigation, and a 404 route for everything unmatched.

Three things are routinely got wrong, and all three are noticed by users:

Use real links. An anchor with an href can be middle-clicked, opened in a new tab, copied and read by a crawler. A div with a click handler that calls the router is a link that only works for people behaving exactly as you imagined — the same argument as the semantics article, now with the browser's whole navigation model at stake.

Restore scroll and manage focus. A real page load resets scroll and announces the new document. Client-side navigation does neither unless you make it: without focus management, a screen reader user follows a link and is told nothing at all, still sitting in the old position.

Treat the URL as state. From the previous article: filters, search terms, tabs and pagination belong there. It's what makes a view shareable and the back button honest.

Talking to a server

Most of the time you'll be calling an HTTP API and receiving JSON. The vocabulary is small: a resource identified by a path, a method describing the intent (get, create, update, delete), a status code describing the outcome, and a body.

Status codes are worth knowing as families rather than numbers: 2xx worked, 3xx go elsewhere, 4xx you got it wrong (401 not authenticated, 403 not allowed, 404 not there, 422 invalid data), 5xx the server got it wrong. That distinction drives your interface: a 4xx usually means show the user something specific and actionable; a 5xx means apologise and offer a retry.

You may also meet GraphQL, where the client asks for exactly the fields it wants in one request. It solves real problems — over-fetching and waterfalls of dependent requests — at the cost of a heavier client and more complex caching. Either way, the important habit is identical: the contract with the server is a thing to know precisely. What fields are optional, what an empty result looks like, what an error body contains. Most integration bugs are an assumption about that contract nobody wrote down.

Two things that will confuse you exactly once

CORS. You call an API from your page and the browser blocks it with a message about cross-origin. Read this once and save a day: the browser refuses to let a page read a response from a different origin unless that server explicitly permits it with a header. It's a protection for the user, and — this is the part people fight for hours — it can't be fixed in your front end. No fetch option, no header you add on the client. Either the server allows your origin, or you go through a proxy that does. Disabling browser security to make it go away isn't a fix; it's a way to make development stop resembling production.

Auth. Two common shapes. A token the client stores and sends on each request, or a cookie the browser attaches automatically. Tokens in local storage are readable by any script that gets injected into your page, which makes them an XSS payday; an httpOnly cookie can't be read by JavaScript at all, at the cost of needing CSRF protection. There are trade-offs and the Security sphere is where they belong.

But one rule is absolute, and it's the one frontend developers most often get wrong: the client never enforces permissions. Hiding an admin button is a courtesy, not a control. Anyone can call the endpoint directly. Every check that matters is repeated on the server, and if it isn't, the button was never the problem.

Where the HTML comes from

Here's the question this article exists for, and the one that most reliably separates people who choose a stack from people who inherit one.

Client-side rendering. The server sends a near-empty page and a bundle of JavaScript; the browser builds everything. Simple mental model, but the user sees nothing until the JavaScript loads and runs, and search engines see a blank page unless they execute it. Right for applications behind a login, where the first paint matters less than the interaction that follows.

Server-side rendering. The server builds the HTML for each request and sends a real page, which then gets wired up in the browser. Fast first paint, works for search, costs server time per request, and needs the data available at request time. Right when content is personalised and must also be fast.

Static generation. The HTML is built once at deploy time and served as files, usually from a CDN. Nothing is faster or cheaper, and nothing is more robust — but the content must be the same for everyone until the next build. Right for content sites, documentation, marketing, blogs.

Hybrids. Rebuilding static pages on a schedule or on demand, streaming parts of a server-rendered page as data arrives, or shipping mostly-static HTML with small interactive islands. These exist because most real sites are a mixture: a product page is static-ish, the cart is not.

Every rendering strategy answers one question: at what moment is the HTML built, and by whom — the build, the server, or the browser?

Learn that axis and the product names stop mattering. Meta-frameworks — Next, Nuxt, SvelteKit, Remix, Astro — exist precisely to give you routing, data loading and a choice of rendering strategy in one coherent package, and they compete on exactly this axis, not on anything mysterious.

The current direction of travel is worth knowing: rendering more on the server, sending less JavaScript, and marking only the genuinely interactive parts for the client. It's a swing back after a decade of moving everything into the browser, and it's driven by the thing that never changed — bytes cost time, and someone's phone is doing the work.

Choosing, in three sentences

A content site — marketing, docs, a blog: static, and don't overthink it. An application behind a login: client-rendered is fine, since search and first paint matter less than the twenty minutes that follow. Anything public, personalised and commercial: hybrid, and this is where thinking about it actually pays.

And a fourth: whatever you choose, know where each piece of data comes from and when. Most performance disasters are a page that can only start loading its data after everything else has finished.

Caching, one layer at a time

Data caching from the previous article isn't the only layer, and knowing the stack prevents a specific kind of madness. The browser caches files by their headers. A CDN caches responses near the user. Your data layer caches API results in memory. And a service worker, if you have one, can cache aggressively enough to serve a page offline — and aggressively enough to serve a version you deleted three weeks ago.

When users see stale content, the question isn't "why is it cached" but "which of the four". Naming the layer is the fix.

In practice

Draw the data flow for one screen. Which requests fire, in what order, what depends on what, and where it renders. Ten minutes on paper finds waterfalls that are invisible in code.

Open the Network panel and count the round trips before the screen is usable. The number is usually higher than you'd guess, and the sequential ones are the ones to attack.

Put your filters in the URL, then use the back button. Small change, immediate proof.

Read your API's documentation properly, once, rather than discovering the contract by trial and error over a month. This is the same distinction the How to Learn sphere draws between recognising and knowing: skimming until something works leaves you with a shape you can't reason about.

Explain your rendering strategy in one sentence: "the HTML is built at X by Y because Z." If you can't, you inherited it rather than chose it — which is fine, right up until it's the thing you need to change.

Check yourself

Close the article and answer in your own words:

  1. What does a client-side router replace, and what three things does it break unless you handle them?
  2. What do the 4xx and 5xx families mean for what you show the user?
  3. What is CORS, and why can't you fix it in the front end?
  4. Why is hiding a button not a permission check?
  5. Give one sentence each for client rendering, server rendering and static generation, with the case each suits.
  6. What single question do all rendering strategies answer?
  7. Name the four caching layers between your data and the user's screen.

In short

  • An application adds two decisions to components and state: how people move between screens, and when the HTML is built.
  • Routing means real links, restored scroll, managed focus, and a URL that carries filters, search and pagination.
  • Know your API contract precisely; status code families tell you whether to show something actionable or apologise and retry.
  • CORS is the server's decision and cannot be fixed from the client — and the client never enforces permissions, only displays them.
  • Client rendering suits applications behind a login, server rendering suits fast personalised content, static generation suits content sites, and real sites are usually hybrids.
  • Every strategy answers one question — at what moment and on whose machine the HTML is built — and meta-frameworks compete on exactly that axis.
  • The industry is moving back towards rendering on the server and shipping less JavaScript, because bytes cost time on someone else's phone.
  • Stale content is always one of four caching layers: browser, CDN, data layer, service worker.