On-Demand Rendering

Purpose and Scope

On-demand rendering is Astro’s mode for producing HTML at request time instead of writing every page, route, and endpoint as static output during the build. In the public documentation this is also described as server-side rendering, or SSR. The reader-facing model is simple: static prerendering is the default, but an Astro project can choose to render some or all routes on a server when each request arrives. That makes it possible to personalize HTML for a signed-in user, read fresh backend data, or handle routes that cannot be fully known during a site build.

This page explains that model from the repository evidence available for this slice of the codebase. The provided source paths do not include the main route renderer, but they do show important build-time constraints that matter when a project mixes prerendered output with server output. The Cloudflare changeset records a failure mode where prerender errors inside workerd were previously hidden, while the build configuration files show how packages are compiled into distributable artifacts. The font URL and file ID utilities show how generated output keeps stable asset references, base paths, asset prefixes, search parameters, and content security policy resources coherent during builds.

Sources: .changeset/sharp-bags-build.md, configs/tsconfig.build.json, packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts, packages/astro/src/assets/fonts/infra/build-url-resolver.ts

Relevant Source Files

  • .changeset/sharp-bags-build.md — Records a Cloudflare adapter patch for prerender error handling in workerd, including buffering the response body so rendering errors surface as build failures rather than producing truncated HTML.
  • configs/tsconfig.build.json — Defines the shared TypeScript build layout for packages, including source input, distributable output, and a hidden tsbuildinfo cache under dist.
  • packages/astro-prism/tsconfig.build.json — Extends the shared build config for the Astro Prism package and includes its source plus virtual type declarations.
  • packages/astro-rss/tsconfig.build.json — Extends the shared build config for the Astro RSS package, showing the same package build convention used across Astro packages.
  • packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts — Implements build-time font file IDs by hashing resolved font content and appending the font type extension.
  • packages/astro/src/assets/fonts/infra/build-url-resolver.ts — Implements build-time URL resolution for font assets, applying base paths, asset prefixes, adapter-provided search parameters, and collecting CSP resources and generated URLs.

Rendering Model

Astro’s rendering decision is route-oriented. A route that can be generated at build time becomes static HTML or an endpoint artifact. A route rendered on demand instead requires a server runtime and an adapter that knows how to package Astro for that runtime, such as Node.js, Netlify, Vercel, or Cloudflare. The distinction matters operationally: a build can still generate static files, but the deployed output must also include server code for routes that execute later. In hosting environments that split client assets from server functions, deployment settings may also distinguish the public asset directory from the server bundle.

The Cloudflare changeset is a useful reliability signal because it documents how build-time rendering and server-runtime behavior can overlap. It describes a bug where pages throwing during rendering inside workerd caused astro build to exit successfully while emitting truncated HTML. The fix buffers the response body inside workerd before sending it back to the build process, so streaming errors are caught and reported as build failures. That is specifically about prerendering, but it illustrates an important rule for on-demand systems: render work may happen in a runtime-like environment, and errors must be propagated across that boundary clearly.

Sources: .changeset/sharp-bags-build.md

System-to-Code Mapping

ConcernRepository evidenceWhat it tells you
Runtime-backed prerender reliability.changeset/sharp-bags-build.mdAdapter/runtime rendering must not hide stream failures; build processes should fail loudly when generated HTML is incomplete.
Package build outputconfigs/tsconfig.build.jsonAstro packages compile from src to dist and place TypeScript build cache data under dist/._cache/ts_build.
Package-specific compilationpackages/astro-prism/tsconfig.build.json and packages/astro-rss/tsconfig.build.jsonIndividual packages inherit shared build behavior and add only package-specific include rules when needed.
Stable build asset IDspackages/astro/src/assets/fonts/infra/build-font-file-id-generator.tsFont files get deterministic IDs from the resolved file content and font type, supporting cacheable generated output.
Asset URLs in generated HTMLpackages/astro/src/assets/fonts/infra/build-url-resolver.tsBuild output can include base paths, asset prefixes, query parameters, and CSP resource tracking for font URLs.

The mapping shows that on-demand rendering is not only a route-level feature. It depends on the packaging and asset pipeline being deterministic enough for a deployed server and its static assets to agree. The shared TypeScript build config establishes the dist layout used by packages, while package-level configs such as Astro Prism and Astro RSS show how integration packages can inherit that convention. These files do not decide whether a route is prerendered, but they support the release and distribution model that adapters, integrations, and runtime helpers rely on.

Sources: configs/tsconfig.build.json, packages/astro-prism/tsconfig.build.json, packages/astro-rss/tsconfig.build.json

Execution Flow

A typical on-demand rendering workflow begins with project configuration. The developer chooses a deployment target, adds the matching adapter, and lets Astro build a project that may contain both prerendered and request-time routes. During the build, static output is emitted immediately, server bundles are prepared for the adapter runtime, and shared assets are resolved. If a prerendered route throws while running in an adapter-like environment, the build should fail instead of publishing broken HTML. The workerd fix documented for the Cloudflare adapter is a concrete example of this expectation being enforced.

For generated assets, the font build utilities show two parts of the build-time flow. The file ID generator accepts an original URL and a font type, resolves the font file content, hashes that content, and returns a filename-like ID ending with the type. The URL resolver then turns an ID into a URL by applying an optional assets prefix, the configured base path, and any provided search parameters. It also remembers the resulting URLs and CSP resource origins. Those details are especially relevant for deployments where server-rendered HTML references assets hosted under a CDN prefix or protected by adapter-level tracking parameters.

Sources: packages/astro/src/assets/fonts/infra/build-font-file-id-generator.ts, packages/astro/src/assets/fonts/infra/build-url-resolver.ts

Implementation Details

The shared build config uses a package-relative source root and output directory pattern. It extends the repository’s base TypeScript configuration, sets the source directory to src, writes compiled output to dist, and stores TypeScript incremental build metadata under dist/._cache/ts_build. The comment explains why that cache location is safe: dot-underscore cache content is ignored when publishing to the npm registry, so build artifacts needed for local compilation do not become part of the public package payload. This keeps package output focused on runtime and type artifacts that consumers actually need.

Astro Prism and Astro RSS demonstrate two variations on this shared build shape. The RSS package simply extends the shared build config, which is enough when its source tree matches the default convention. The Prism package also extends the shared config, but explicitly includes both its source directory and virtual.d.ts. That small difference is important for package authors because type-only or virtual module declarations can be part of the public build contract even when they are not ordinary runtime source files. On-demand rendering deployments depend on this kind of consistent package compilation because adapters and integrations are installed from built package artifacts.

The font URL resolver is also conservative about output bookkeeping. If an assets prefix is present, it resolves a prefix based on file extension and records that prefix as a CSP resource. Without a prefix, it records self and creates a slash-prefixed URL under the configured base. It then appends every provided search parameter before stringifying the placeholder URL. The source comment calls out adapter-level tracking such as skew protection, which is the kind of deployment concern that appears when server output and asset versions must remain aligned across rolling deploys.

Operational Guidance

When deciding whether a route should be rendered on demand, start from the user requirement. Use static prerendering when every visitor can receive the same HTML and the data changes only when you rebuild. Use on-demand rendering when the HTML depends on request-specific state, authentication, cookies, live data, or server-only secrets. After that decision, choose an adapter that matches the hosting runtime, confirm the host’s expected build command and publish directory, and test both successful rendering and failure paths before deploying.

For contributors working in this repository, the supplied files suggest two review questions for rendering-related changes. First, does the build fail when generated HTML cannot be completed, especially when an adapter runtime streams a response back to the build process? Second, do generated URLs remain stable and deployment-aware when base paths, asset prefixes, CSP requirements, or adapter search parameters are involved? These questions connect the user-visible SSR feature to the lower-level package and asset infrastructure that makes mixed static and server output reliable.

Next Steps

Read the adapter and deployment pages next if you need to choose a runtime target, then review the routing and server-side rendering pages to decide which routes should be prerendered and which should execute per request. If your work touches generated assets, inspect the image and font pipeline pages as well, because server-rendered HTML is only correct when its asset URLs, cache keys, and security policy resources line up with the deployed environment.