The frontend boundary moved, the responsibility did not
Server-first components moved data access and rendering, but K81R still had to design navigation, loading, accessibility, errors, readiness, and browser cost.
By the end of 2023, much of K81R's source interface was React code that never ran in the browser.
It loaded authorized data on the server, rendered authored structure through Server Components, streamed optional regions, and passed small descriptors into client interactions. The client bundle became smaller. The database remained private. The route composed more naturally around source identity.
None of that reduced frontend responsibility.
The page still had to arrive in an understandable order, preserve focus, work under slow networks, communicate stale evidence, survive partial failure, and make consequential actions honest. The boundary moved across environments; the person still encountered one product.
Frontend stopped being a location
The old shorthand was simple: backend runs on the server; frontend runs in the browser.
K81R's source renderer ran on the server and owned:
- Information hierarchy and headings.
- Route and metadata composition.
- Loading and error boundaries.
- Disclosure-safe rendering.
- Responsive document structure.
- The props and markup interactive clients received.
Those were frontend decisions even when the JavaScript stayed off the device.
I began defining frontend as responsibility for the experienced system boundary, including how work divides between server, network, and browser.
Fetching close to a component reduced boilerplate and could produce waterfalls, duplicate queries, inconsistent revisions, and too many loading regions.
I designed a route data plan:
- Resolve disclosure-safe source identity and authorization.
- Load immutable source revision and current status coherently.
- Begin independent relationships and query context concurrently.
- Reveal source content first.
- Reveal optional regions only with compatible generation metadata.
The component tree expressed the plan. It did not let every leaf decide independently what the reader should wait for.
Frontend architecture included server query composition because query timing shaped the interface.
Suspense made pending boundaries easy to implement. It did not decide whether the page had one coherent task or six independent fragments.
K81R's source identity and body appeared together. Related decisions streamed later under a stable heading. Query context remained optional. Evidence generation used durable job state rather than a component spinner.
Fallbacks described the product region and appeared only after a perceptual delay. They preserved geometry and reading order. Empty and error states were designed alongside pending.
Server-first rendering changed where data waited. It did not make waiting self-explanatory.
Navigation was still temporal UI
Nested layouts could persist source identity while child routes changed. That persistence became dangerous if authorization or revision changed.
I tested direct loads, client navigations, Back and Forward, rapid source changes, loss of access, related-document traversal, and refresh during streaming. The route preserved stable layout only while its identity token remained valid.
Focus moved to the new main heading for full source navigation, stayed within the task for local filters, and returned predictably from evidence inspection. Scroll restoration followed document identity rather than arbitrary component survival.
Routing APIs did not supply these semantics automatically.
The server produced headings, landmarks, links, labels, and initial status. Client components later added selection state, dialogs, keyboard behavior, and live updates.
The combined accessibility tree needed to remain coherent before, during, and after hydration. I checked:
- Heading order in initial HTML.
- Link purpose without client code.
- Focus when an interaction island became ready.
- No duplicate labels from server and client wrappers.
- Polite announcements for completed claim blocks, not tokens.
- Reduced motion and stable content order during streaming.
- Error messages associated with the region they affected.
Accessibility was not owned by one execution environment.
Visible did not always mean interactive
A server-rendered button-like control could appear before its client handler loaded. The gap made fast clicks look lost.
Where ordinary forms or links could work, they provided the baseline. Client enhancement improved transitions and local feedback. Controls requiring client-only state remained honestly unavailable until ready, while surrounding content stayed readable.
I measured source-readable and selector-ready separately. The route could be successful for reading before all enhancements arrived.
The frontend contract included the interval between HTML visibility and browser capability.
Server Components reduced client JavaScript for source rendering and broad page-model data. I tracked:
- Client chunk bytes and dependency paths.
- Serialized props crossing client boundaries.
- Parse and hydration time.
- Browser memory after several document navigations.
- Main-thread work during source display.
- Interaction latency after readiness.
A new client feature had to justify the capability it added. Moving code server-side also had server CPU and latency cost, measured separately.
The goal was not a zero-JavaScript score. It was a browser budget aligned with actual interaction.
Errors needed truthful blast radii
If related decisions failed, the source remained authoritative and readable. If source authorization failed, no cached child region could remain visible. If the evidence selector failed to hydrate, reading and source links still worked.
Error boundaries followed these consequences. Copy named the unavailable product region and possible action, not the component environment.
Server logs, browser diagnostics, and durable workflow state shared navigation, source, release, and request identities. A full investigation could cross environments without presenting the topology to the reader.
Frontend owned the visible failure contract; operations preserved the deeper evidence.
Cache state became user-visible truth
Server caching could return an immutable source revision safely and a stale current-status label dangerously. Query context could lag the active corpus generation and remain useful when labelled.
I connected cache policy to data classification:
- Authority reads required current decision semantics.
- Immutable source snapshots cached by revision.
- Relationship projections exposed generation and lag.
- Request-scoped authorization never entered broad shared caches.
The page showed source revision and index freshness where they affected interpretation. It did not expose cache hits.
Frontend accuracy depended on backend freshness contracts becoming legible at the interface.
Metadata was part of the interface
Titles, descriptions, canonical links, social previews, and machine-readable document identity were generated on the server. They could leak restricted source names or disagree with the body.
The metadata path used disclosure-safe authorization and exact source revision. Missing and inaccessible shared a public absence. Optional projection failure did not change canonical identity.
Fixtures inspected initial HTML and head output, not only screenshots after hydration.
Server-owned interface includes content users encounter outside the visible page.
Client state still needed identity
The evidence selector tracked local draft selection across source inspection. Navigating to another source could preserve the tray and had to reset passage-local focus and filters.
I assigned state to entities:
- Evidence-set draft persisted across source navigation.
- Passage expansion belonged to source revision and reset on change.
- Query filters belonged to URL state.
- Copy feedback belonged to one control instance.
- Durable save state came from the server record.
Keys, reducers, routes, and command results expressed that ownership. Effects no longer tried to repair state after identity changed.
The Hooks mental-model audit remained relevant in a server-first application.
Evidence selection began as browser interaction and became an accepted server revision. The command included expected evidence-set revision, stable request identity, and passage identity.
Optimistic local state could show the draft immediately. It could not claim server acceptance. A conflict response preserved local operations and current authoritative set. Offline or lost responses remained recoverable by intent identity.
The rendering model did not convert network mutations into local function calls conceptually.
Frontend responsibility included showing where local intent ended and accepted state began.
Streaming AI output used document semantics
Raw token streaming created moving, uncited assertions. K81R buffered complete claim records, validated evidence IDs and rendering policy, then inserted claim and citations together.
The answer page showed evidence while generation worked. Screen readers received complete block announcements. Reconnection loaded durable claims rather than replaying token transport.
This was a frontend architecture decision spanning model adapter, server state, stream protocol, client rendering, and accessibility.
The experienced unit was a supported claim, not a token.
On wide screens, evidence selection and source metadata could sit beside the document. On narrow screens, DOM order remained source identity, content, selection state, relationships, and optional query context.
Streaming did not reveal lower-priority content above unresolved primary structure. Client portals and dialogs preserved accessible relationships and return focus. Large text and zoom did not move primary actions after optional regions arrived.
CSS placement changed across viewports; reading and focus order remained tied to the task.
Server rendering did not reduce responsive design to choosing a grid.
Design-system components declared capability
J05N had once grouped components by appearance. K81R's server-first migration added another useful dimension:
- Server-safe presentational primitives.
- Client interaction primitives.
- Compositions that accepted server-rendered children.
- Browser preference and external-store adapters.
The distinction avoided a client-only barrel turning typography and source blocks into browser dependencies. It also kept accessibility and visual tokens consistent across environments.
Reuse described behavior and execution cost without creating separate visual systems.
Unit tests alone could not show whether initial HTML, streamed regions, hydration, navigation, and durable commands formed one coherent experience.
Route scenarios captured:
- Initial response and document outline.
- Optional region pending and failure.
- Client readiness under delayed JavaScript.
- Keyboard selection and server acceptance.
- Navigation with a persisted evidence draft.
- Permission change and disclosure-safe rerender.
- Claim streaming and reconnection.
- Final answer provenance.
Visual, accessibility, performance, and state assertions shared deterministic fixtures.
Frontend verification became temporal and cross-environment.
Server spans and browser events used one navigation identity. Source authority, relationship projection, selector readiness, evidence save, and answer generation each exposed product milestones.
I could see that a page was readable while an optional projection was slow, or that server work was fast while a large client dependency delayed selection. Product-state measures prevented one environment's green dashboard from declaring the whole interface healthy.
The person did not need the trace. The system needed enough evidence to explain their wait.
The architecture could fail in either direction
Too much client ownership increased bundle, hydration, memory, exposure, and duplicated data logic. Too much server ownership could increase request work, make local interaction dependent on round trips, overcache sensitive data, or create waterfalls.
I evaluated each capability:
- Where is its authority?
- Does it require immediate local response?
- What data must cross the network?
- Can ordinary web semantics provide a baseline?
- What failure and recovery state does the person need?
- Which device or server resource does it consume?
Server-first was a useful default question, not a mandate that every interaction wait for the server.
The shift did not diminish browser expertise. It made that expertise more targeted. Focus, input, device constraints, offline behavior, layout, accessibility, and interaction still belonged in the client where needed.
It also required understanding server rendering, data authority, cache scope, stream protocols, security disclosure, deployment, and observability because they shaped the interface before the browser code began.
The discipline expanded across the product boundary while the browser payload contracted.
The year closed with a familiar principle
K81R's 2023 work had begun by separating retrieval from chat and ended by separating frontend responsibility from execution location.
Both corrections resisted a visible interface becoming the whole architecture. Search remained a product even without generation. Interface design remained a discipline even when components ran on the server.
The project grew more challenging not by accumulating fashionable surfaces but by making evidence and boundaries explicit beneath them.
Server Components moved where code and data could live. They did not decide what should be shown, when it became trustworthy, how a person could act, or what happened when part of the system failed.
The frontend boundary moved. The responsibility did not.
Privacy included what crossed the browser boundary
The client-prop audit became a practical data-minimization review. A field that never reached the browser could not be exposed through developer tools, client logs, extensions, or accidental analytics. That did not make server data harmless; it reduced one distribution surface.
I inventoried serialized props, HTML, metadata, client caches, browser storage, analytics events, and error reports. Evidence drafts stored stable source IDs and local operations, not unrestricted passages unless offline reading explicitly required a bounded snapshot.
Moving rendering server-side created an opportunity to send less data. Frontend responsibility included taking that opportunity deliberately.
The final 2023 source scenario began at search, opened an immutable document, inspected a citation, selected evidence, saved against an expected revision, generated validated claim blocks, navigated away, returned, and opened the immutable answer record. Slow relationships, denied sources, stale indexes, client delays, and model interruption each had a truthful state.
No individual framework feature supplied that coherence. It came from decisions across authority, server rendering, browser interaction, protocols, and interface design.
Offline behavior became explicit absence
The old broadly hydrated route could sometimes navigate cached client data after the server disappeared, without a clear freshness contract. The server-first source view required a server for new authorized documents.
I designed the offline state instead of pretending feature parity. An already opened immutable public source could remain readable from a controlled browser cache with its revision and last validation visible. Current authority, restricted sources, search, and evidence acceptance reported unavailable. Local evidence draft intent could remain pending without claiming acceptance.
Server ownership clarified which capabilities truly depended on a live authority.
Print and saved documents were first-class outputs
The source view's server-rendered structure produced a strong print baseline. I added styles that kept heading hierarchy, code, tables, citation URLs, source revision, and currentness visible while removing interactive controls that had no printed meaning.
Generated answers printed claim evidence and review state. A static copy never implied it would refresh with the corpus. Its header included answer and source revision identity.
Frontend responsibility extended beyond the interactive viewport to durable reading contexts.
Server-rendered content reduced reliance on modern client JavaScript for reading, but interactive selection, streaming transport, focus APIs, and CSS still needed compatibility checks.
I tested the project's supported browser range under full enhancement, delayed enhancement, and baseline navigation. Unsupported optional APIs had narrow fallbacks. The application did not send a blank shell because a client feature was unavailable.
Progressive enhancement turned browser diversity into graduated capability rather than one all-or-nothing support claim.
Analytics kept server and client observations distinct
A server render could complete without being seen because the connection closed. A client-ready event could occur after the reader had already found the source. Counting both as page views would duplicate and misinterpret behavior.
I used bounded events with stable navigation identity and clear purpose: response produced, source visible where observable, selector used, evidence save accepted. Synthetic verification carried detailed traces; ordinary personal usage retained minimal data.
The data model reflected what each environment could actually observe.
During rollout, an old route instance and new Server Component instance could answer adjacent navigations. Both used the same URL, source authority, evidence command contract, and design language.
Release identity travelled through diagnostics, not public copy. Client assets remained compatible across the overlap or used digest-pinned references. A stale client interaction could submit to the current server because the command contract was versioned and validated.
Deployment architecture did not excuse a visibly fractured navigation.
Design review used sequences and source maps
I reviewed the route as a filmstrip from initial HTML through optional streaming and client readiness, at narrow and wide widths, with keyboard and screen reader. Beside it, a responsibility map showed which environment owned each region, datum, action, cache, and error.
The visual sequence caught experience problems. The map caught architectural drift. A source block unexpectedly moving into the client graph or a server read acquiring browser state became visible before bundle numbers alone explained it.
The two artifacts connected design quality with execution responsibility.