A static page is built before a request and can be cached widely. A server-rendered page assembles HTML for a request, possibly using a session and current record. A client-rendered page sends a shell and asks browser code to fetch the meaningful content later. These modes can coexist on one site. The right choice depends on whether the first response must contain useful text, how often data changes, whether the view is private, and how much browser work the interaction requires. Avoid making a tiny read-only page wait for a large client bundle without a reason.
Static, Server-Rendered, and Client-Rendered Pages
Working case
A public guide to inspection terms changes weekly and works well as static HTML. A private case page needs current permission checks and can be rendered on the server per request. A live status widget on that page may fetch updates after the initial HTML arrives. This combination keeps the record readable when enhancement fails while still supporting fresh status. Caching a private server-rendered page as though it were public would leak data; rendering every public guide from a database on each visit wastes work without adding value.
Implementation
function escapeText(value) {
return String(value).replace(/[&<>"']/g, character => ({
"&": "&", "<": "<", ">": ">", '"': """, "'": "'"
})[character]);
}
function renderCasePage(caseRecord) {
return `<main><h1>${escapeText(caseRecord.title)}</h1>` +
`<p>Status: ${escapeText(caseRecord.status)}</p></main>`;
}Cost and boundaries
Static delivery can avoid per-request template and database work, but rebuilding many pages after one edit has a cost. Server rendering adds request-time CPU and data lookup; browser rendering adds script transfer, parsing, execution, and a later data request before text appears. Compare real first-load and interaction traces, not framework slogans. The example below represents the server boundary: escape record text before inserting it into HTML, then send a complete page that does not require client code to reveal its title.
Common Mistakes
- Do not put private data in a shared public cache.
- Do not make essential text depend solely on a delayed client fetch.
- Do not force one rendering mode onto every route.
Connected lessons
Frontend Application Architecture; Component Boundaries and State Ownership; Browser Routing and History State; Locale and Time-Zone Boundaries; DOM events: enhance a working control without losing its baseline; HTML Tutorial; CSS Tutorial.
Failure trace
The team moves a public guide into a blank client shell because the same component renders private cases. On a slow phone, the guide title appears after the bundle and data request; with scripts disabled it never appears. Meanwhile, one cache rule accidentally stores a private case response at a public edge. Split delivery by route: public guide HTML can be cached, while the private response needs request-time authorization and a private cache policy.
Verification
- Fetch the initial guide document without executing scripts and inspect whether its main content is present.
- Request one private case as two users and confirm each response is authorized independently.
- Inspect cache headers on public and private routes separately, including a refresh after a write.
Decision note
Mixed rendering is often simpler than an all-or-nothing framework rule. Decide from the data and permission boundary first, then measure first useful content and interaction cost on the target device.
Apply and check
Build Project: paginated inspection feed with safe writes; then check the boundary with Web Development: offline and delivery contracts quiz.
Further connections
Server Rendering and Client Data Flow; Hydration and Deterministic First Render.
