Browse pages
Frontend Rendering and Routes
A route answers three questions: which web address it serves, which data it needs, and which floorplan, the page component fixing the page layout, draws it. This page states how a route loads its data before rendering, how the address carries its parameters, how routes and languages load separately, and how each route state renders. Frontend developers and agents apply it for every address the product serves, so each page renders with its data in place and no route shows a blank region where a request is pending or failed.
Stack: any Layer: frontend-ui
Concepts#
The Route, Its Cache, and Its View#
A route is the entry for one address: it declares its parameters, loads each read it needs through one shared cache, and hands rendering to its view. The view reads the same cache entries the route filled, so the page renders with its data rather than showing a spinner after it appears. The cache owns freshness; neither the router nor the view keeps a second copy. The view renders inside one floorplan, the page component that fixes the page layout (Controlled UI Governance).
Addresses Carry Their Own Parameters#
A route declares its address parameters, including filters and page, in a validated schema. A filtered list is then a link somebody can share, bookmark, and reopen: the address holds the filter values, and opening the address restores the same view. A filter kept in component state reaches nobody and is lost on the first navigation away.
Route States#
A route can reach six states: loading, empty, error, forbidden, not-found, and ready. Defining each one up front gives the reader a designed answer wherever a request is pending or failed, instead of a blank region.
Standards#
Load Route Data Before Rendering#
ruleruleguidancelitespec/frontend/rendering#load-route-data-before-renderingA route MUST load each read it needs through one shared cache before its view renders.
Applies toartifact: route
Why
A view that renders before its reads complete shows a spinner after it appears, then swaps the spinner for content: two drawings for one navigation, with layout shifting between them. Loading each read through one shared cache before the view renders gives the page its data in place. The cache owns freshness, so the router keeps no second copy that could disagree.
Example
An entity route loads its record and every read the record's own sections need.
Checka reviewer answers
Reviewed forWhich routes render before their reads load through the one shared cache? Look in the route loaders and the cache definitions.
Marked guidance: a reviewer answers this question.
Read Route Data from the Route Cache#
ruleruleguidancelitespec/frontend/rendering#read-route-data-from-the-route-cacheA view MUST read route data through the same cache entry its route filled.
Applies toartifact: route
Why
A view that reads under another key issues a second request for data the route already loaded, and the two answers can disagree when the data changes between them. Reading through the same cache entry the route filled renders the data the route approved. A failed read reaches the route's error boundary, which draws the shared problem state instead of a half-rendered view.
Checka reviewer answers
Reviewed forWhich views read under another key than the cache entry their route filled, or handle a failed read outside the route error boundary? Look in the view data reads and the route loaders.
Marked guidance: a reviewer answers this question.
Keep Address Parameters Validated by a Schema#
ruleruleguidancelitespec/frontend/rendering#keep-address-parameters-validated-by-a-schemaA route MUST declare its address parameters in a validated schema, including its filters and its page.
Applies toartifact: route
Why
A validated schema makes the address the whole input: a filtered list is a link somebody can share, bookmark, and reopen, and opening it restores the same filters and page. Validation also refuses a malformed address at the boundary instead of rendering a page from nonsense values. A filter kept in component state reaches nobody and is lost on the first navigation away.
Example
The list schema declares its own text field and spreads the shared paging fields.
Checka reviewer answers
Reviewed forWhich routes leave address parameters, filters, or page outside a validated schema? Look in the route parameter schemas.
Marked guidance: a reviewer answers this question.
Load Each Route and Each Language Separately#
ruleruleguidancelitespec/frontend/rendering#load-each-route-and-each-language-separatelyA frontend MUST load each route and each language as its own download, with no icon set or language loaded whole.
Applies toartifact: route
Why
A reader opens one address and reads one language, so downloading every route and every language up front wastes the reader's time on code and copy outside what they read. Each route and each language ships as its own download: a reader in Dutch who stays on the dashboard downloads neither English nor the routes outside their path. No icon set or language loads whole for the same reason.
Example
A dictionary loader returns one language. Each route file or folder ships as its own download.
Checka reviewer answers
Reviewed forWhich routes or languages ship in a shared download, or load an icon set or language whole? Look in the route bundles and the dictionary loader.
Marked guidance: a reviewer answers this question.
Prefetch a Route on Intent#
ruleruleguidancelitespec/frontend/rendering#prefetch-a-route-on-intentA frontend MUST prefetch the route the reader signals intent toward, without treating that prefetch as a cache beyond the shared cache.
Applies toartifact: route
Why
When the reader signals intent toward a route, by hovering a link or focusing a menu item, prefetching loads that route's data into the shared cache before the navigation starts, so most navigations render from data already in place. The prefetch fills the shared cache only: a router that kept its own second cache would serve a stale answer beside the fresh one.
Checka reviewer answers
Reviewed forWhich route prefetches land outside the shared cache, or feed a second router cache? Look in the router prefetch wiring.
Marked guidance: a reviewer answers this question.
Represent Route States#
ruleruleguidancelitespec/frontend/rendering#represent-route-statesA data-driven route MUST define its loading, empty, error, forbidden, not-found, and ready behavior.
Applies toartifact: route
Why
A blank region while a request is pending or failed gives the reader no signal: they read no difference between loading and broken. Defining loading, empty, error, forbidden, not-found, and ready behavior gives each state a designed drawing, and the root not-found handling draws the shared outcome page for an absent address.
These six are the states a route has. A control adds disabled and pending under litespec/frontend/components#render-control-states, because both describe a control rather than a route. A route adds not-found, which a control does not, because a missing target resolves at the route.
Checka reviewer answers
Reviewed forWhich data-driven routes miss a loading, empty, error, forbidden, not-found, or ready behavior, or leave an absent address outside the shared outcome page? Look in the route state definitions.
Marked guidance: a reviewer answers this question.
Keep Authenticated Caching Explicit#
ruleruleguidancelitespec/frontend/rendering#keep-authenticated-caching-explicitActor-specific data MUST declare its cache key, partition, invalidation owner, and security review before caching, beside the read definition setting the key.
Applies toartifact: component, route
Why
A cache entry that ignores whose data it holds serves one actor's answer to another reader: the classic leak behind a shared cache. Declaring the cache key, the partition, the invalidation owner, and the security review beside the read definition forces each cached actor-specific read to name its boundary before it caches. An uncached read is the safe default, and a cache partitioned per request is the safe server shape.
Checka reviewer answers
Reviewed forWhich cached actor-specific reads lack a declared cache key, partition, invalidation owner, or security review beside the read definition? Look in the read definitions setting cache keys.
Marked guidance: a reviewer answers this question.
Keep Proxy Behavior at the Edge#
ruleruleguidancelitespec/frontend/rendering#keep-proxy-behavior-at-the-edgeA development or edge proxy rule MUST route only, and never decide who the actor is or what the actor may read.
Applies toartifact: any
Why
A development or edge proxy runs before the request reaches the API, with no view of the record or the permissions an authorization decision depends on. A proxy rule that decided who the actor is or what the actor may read would enforce a different boundary than the API, and the two would disagree on the first edge case. The proxy routes and nothing else; the API owns identity and authorization.
Example
A development proxy forwards /api and /auth to the API and changes nothing else.
Checka reviewer answers
Reviewed forWhich proxy rules decide identity or authorization instead of routing only? Look in the proxy rules.
Marked guidance: a reviewer answers this question.
Build the Server Data Cache per Request#
ruleruleguidancelitespec/frontend/rendering#build-the-server-data-cache-per-requestA server-rendered frontend MUST construct its data cache inside each request.
Applies toartifact: any
Why
A server renders for many readers at once. A data cache shared across requests serves the next reader the previous reader's answer, leaking one actor's data to another with no error to report it. Constructing the cache inside each request gives every reader a fresh cache that dies with the response.
Checka reviewer answers
Reviewed forWhich server rendering reuses a data cache across requests instead of constructing it inside each request? Look in the server request setup.
Marked guidance: a reviewer answers this question.
Conventions#
Use a Shared Layout for a Shell#
conventiondefaultguidancelitespec/frontend/rendering#use-a-shared-layout-for-a-shellGive a shell a layout holding the frame every child route shares.
ReplacementA consumer can replace this default with an explicit local convention.
Applies toartifact: route
Why
A shell is the frame every child route shares: navigation, header, and providers. A shared layout holds it without adding an address segment, so the shell stays out of links and every child route renders inside the same frame.
Checka reviewer answers
Reviewed forWhich shells sit outside a shared layout, or add an address segment? Look in the layout definitions.
Marked guidance: a reviewer answers this question.
Keep Layouts Stable#
conventiondefaultguidancelitespec/frontend/rendering#keep-layouts-stableKeep a layout to the frame and the providers every child route needs.
ReplacementA consumer can replace this default with an explicit local convention.
Applies toartifact: route
Why
A layout wraps every route beneath it. A feature-specific provider placed in a shared layout forces unrelated routes to carry its download, its state, and its failure modes. Keeping a layout to the frame and the providers every child route needs keeps each route's cost to what it uses.
Checka reviewer answers
Reviewed forWhich layouts carry a provider that some child route never needs? Look in the layout definitions.
Marked guidance: a reviewer answers this question.
Keep Server-Only Code Identifiable#
conventiondefaultguidancelitespec/frontend/rendering#keep-server-only-code-identifiableKeep a module reading a request header, a cookie, or a server secret in a file whose name and place show the server ownership.
ReplacementA consumer can replace this default with an explicit local convention.
Applies toartifact: any
Why
A module that reads a request header, a cookie, or a server secret breaks when it runs in the browser, and worse, it can drag the secret into the client download. A file whose name and place show server ownership turns an accidental browser import into a build error, and carries the same fact to a reader browsing the tree.
Checka reviewer answers
Reviewed forWhich modules reading request headers, cookies, or server secrets sit in files unnamed or unplaced for the server? Look in the server file names and places.
Marked guidance: a reviewer answers this question.