Skip to main content
Veryfront pages can load data three ways: getServerData on every request, getStaticData during static generation and cacheable production requests, or fetch from a client component. Each one has its place. Examples below use the default app router. Set router: "pages" in veryfront.config.ts to switch to the pages router.

Prerequisites

  • A project with at least one page (see Pages and routing).
  • A data source you can call from server code, build-time scripts, or the browser (REST API, database, or in-memory data).

Server data

getServerData runs on every request. Use it when data depends on the request, such as authentication, query parameters, or cookie reads:
Run veryfront dev and open http://localhost:3000/dashboard?name=Grace. The page should render Welcome, Grace. getServerData, getStaticData, and getStaticPaths are reserved server data export names in browser project modules. Veryfront strips their bodies from browser bundles, and imports used exclusively by those stripped hooks are removed entirely, including their top-level side effects. Put client initialization in a separate client-referenced module or a bare side-effect import that is not only used by a server data hook. Declare server data hooks in the page module. Do not re-export a hook from another file:
A re-export has no local body for Veryfront to empty, so the browser build fails instead of shipping the loader and its transitive server graph. Import the server helper and call it from a local hook:
The props you return are passed to the page component. To read the same props data from a layout or nested component without prop-drilling, use usePageContext().data (see Pages and routing). Veryfront serializes that data into hydration markup and restores it after client-side navigation; do not rely on JavaScript object identity surviving serialization. The DataContext provides:

Set response headers and cookies

Return headers or cookies from getServerData to add metadata to the full document response:
Each cookie supports name, value, domain, path, expires, maxAge, httpOnly, secure, and sameSite. Use an RFC 7231 date string for expires. Veryfront URI-encodes cookie values and emits every cookie as a distinct Set-Cookie field. Veryfront owns CORS, cache, content, redirect, security, transport, and x-veryfront-* headers. Returning one of those headers throws an error. Use cookies instead of a Set-Cookie entry in headers. Layouts merge from outermost to innermost, then the page. The closest loader wins when custom header names conflict. Cookies append in that same order. Any response with a cookie uses no-cache, omits its ETag, and is not stored in the render cache. Response metadata applies to full document responses. getStaticData rejects it because static caches must not replay response cookies. Use an API route or middleware when a client-side navigation request must write response metadata.

Static data

getStaticData supplies cacheable data for static builds and production requests. Use it for content that does not depend on request headers, cookies, or request bodies:
For dynamic routes, pair getStaticData with getStaticPaths to tell the framework which pages to generate. getStaticData receives params and url. It does not receive request, request headers, cookies, a body, or a separate query property. Read query parameters from url.searchParams; the complete URL, including the query string, participates in static cache identity.

Revalidate static data

Set revalidate to a finite, non-negative number of seconds to refresh static data after it becomes stale:
Veryfront serves the cached result while one background refresh runs. A failed refresh keeps the live cached result. Omit revalidate or set it to false to disable background refreshes.

Redirects and 404s

Return redirect() or notFound() from getServerData or getStaticData:
redirect() accepts an optional second argument for permanent redirects:
When redirecting from getServerData, pass response metadata as the third argument to set a cookie or header on the redirect response:
Throwing works the same way. throw notFound() and throw redirect(...) behave exactly like returning them, which is useful inside a helper that has no clean way to return to the data function:
Only the objects notFound() and redirect() produce are read as control flow. Every other thrown value is an error, including an object that happens to carry a notFound property, such as a parsed error body from an upstream API. To restrict redirects to the current request origin and selected external origins, configure an allowlist:
The allowlist uses exact canonical origins, including the scheme and port when present. Do not include a path, query, fragment, credentials, or trailing slash. Root-relative, path-relative, query-only, fragment-only, and same-origin destinations remain allowed. Use an empty list to permit only same-origin redirects. Omit security.redirects to preserve unrestricted redirect behavior. The policy applies equally to returned and thrown redirect() results during full-page and client-side navigation.

Client-side fetching

For data that loads after the page renders, fetch in a client component:

Verify it worked

  • For getServerData, hit the page with curl http://localhost:3000/<path> and confirm the response contains the value you returned in props.
  • To verify response metadata, run curl -sD - -o /dev/null http://localhost:3000/<path> and inspect the custom header and separate Set-Cookie fields.
  • For getStaticData, run veryfront build and inspect the generated HTML for the page. The HTML should contain the static value rather than a client-side fetch loop.
  • For client-side fetching, open the browser dev tools network tab. The request should fire after the page paints and the rendered output should match the response.