Server-Side Rendering and Adapters

Purpose and Scope

Server-side rendering, often abbreviated SSR, is Astro’s request-time rendering mode: a route is converted to HTML when a visitor asks for it instead of only during the static build. In Astro’s public documentation this same capability is also described as on-demand rendering. The key operational requirement is an adapter, which is an integration that teaches Astro how to emit a server entrypoint for a target runtime such as Node.js, Netlify, Vercel, or Cloudflare. This page explains the core rendering surface that adapters rely on, how component rendering participates in SSR, and what repository automation signals exist around deployable examples and sandbox infrastructure.

Sources: packages/astro/src/core/render/index.ts, packages/astro/src/runtime/server/render/index.ts

Astro keeps the adapter boundary conceptually separate from the component and page renderer. An adapter decides where the rendered application runs, while the runtime modules decide how Astro components, framework components, slots, scripts, styles, and streaming output become an HTTP response body. This separation is important for contributors: most behavior that affects what HTML is produced belongs in the runtime render modules, while deployment-specific packaging belongs in adapter integrations. The source paths for this page show the core render exports and component renderer hooks that make the request-time pipeline reusable across deployment targets.

Sources: packages/astro/src/runtime/server/render/component.ts, packages/astro/src/runtime/server/render/astro/index.ts

Relevant Source Files

  • packages/astro/src/runtime/server/render/component.ts — Implements component rendering decisions for Astro components, HTML components, framework components, hydration directives, slots, head content, and server-island instructions.
  • packages/astro/src/core/render/index.ts — Re-exports core rendering primitives such as Pipeline, renderer loading, params and props helpers, and Slots for the higher-level server pipeline.
  • packages/astro/src/runtime/server/render/astro/index.ts — Exposes Astro-component rendering primitives including component factories, component instances, template rendering, and render-to-string or readable-stream helpers.
  • packages/astro/src/runtime/server/render/index.ts — Collects the public server-render runtime surface used internally by the SSR pipeline, including page rendering, components, scripts, slots, streaming, tags, and utilities.
  • .github/workflows/build-sandbox-image.yml — Builds and publishes the repository sandbox image to GitHub Container Registry when sandbox inputs change or the workflow is run manually.
  • .github/workflows/examples-deploy.yml — Redeploys preview.astro.new through a Netlify build hook when example projects change on main.

System-to-Code Mapping

At the top of the server rendering stack, packages/astro/src/core/render/index.ts acts as a compact export hub. It exposes Pipeline from the base pipeline, getParams and getProps for route data preparation, loadRenderer for framework renderer discovery, and Slots for component children management. These are not adapter implementations themselves; they are the reusable building blocks that an SSR request flow needs before it can produce a response. An adapter can arrange deployment and runtime hosting, but the route still has to resolve params, load the proper renderer, prepare props, and pass slot state through Astro’s server-side renderer.

Sources: packages/astro/src/core/render/index.ts

The runtime server render index is the broader map of what Astro can emit during SSR. packages/astro/src/runtime/server/render/index.ts exports renderPage for page-level output, renderComponent and renderComponentToString for component output, renderStreaming for streaming responses, renderScript and renderScriptElement for script output, renderUniqueStylesheet for stylesheet tags, renderSlot and renderSlotToString for slot content, and utilities such as addAttribute, defineScriptVars, voidElementNames, chunkToString, and chunkToByteArray. The presence of these exports shows that SSR is not a single function call; it is a coordinated set of render steps that preserve Astro syntax, component composition, and asset-related tags.

Sources: packages/astro/src/runtime/server/render/index.ts

The Astro-specific render submodule narrows that surface to Astro component internals. packages/astro/src/runtime/server/render/astro/index.ts exports AstroComponentFactory and AstroComponentInstance types, factory and instance checks, createAstroComponentInstance, createHeadAndContent, renderTemplate, renderToString, and renderToReadableStream. In practice, this is the layer that understands Astro component factories and template results, while the outer render index coordinates them with pages, slots, scripts, styles, and framework renderers. For SSR work, this distinction helps keep Astro component execution separate from deployment concerns and from framework-component rendering concerns.

Sources: packages/astro/src/runtime/server/render/astro/index.ts

Execution Flow

A request-time render begins with route information and renderer availability, then moves through page and component rendering until a string, stream, or response-ready chunk sequence is produced. The exported Pipeline, getParams, getProps, and loadRenderer symbols identify the preparation phase: Astro must know which route matched, which parameters and props apply, and which renderers are available for non-Astro components. After that, runtime exports such as renderPage, renderComponent, renderTemplate, and renderStreaming perform the actual HTML generation. This structure is why adapter-driven deployment can be target-specific without rewriting Astro’s component semantics for every host.

Sources: packages/astro/src/core/render/index.ts, packages/astro/src/runtime/server/render/index.ts

Component rendering is where SSR meets islands. packages/astro/src/runtime/server/render/component.ts imports extractDirectives and generateHydrateScript, which means component props are inspected for client directives before rendering. It also imports serializeProps, createRenderInstruction, containsServerDirective, and ServerIslandComponent, connecting ordinary component output to server-island behavior. In the official docs model, a component marked with server:defer is rendered later through an adapter-backed request so the rest of the page can be cached or displayed sooner. The source confirms that server directives are recognized inside the component renderer, not as a deployment-only concern.

Sources: packages/astro/src/runtime/server/render/component.ts

Framework components are handled through renderer selection. The component renderer imports SSRLoadedRenderer types and includes logic for renderer aliases, client-only framework names, and likely renderer guesses based on component file extensions such as Svelte, Vue, JSX, and TSX. It also checks hydration metadata and slot instructions before handing work to a renderer. This matters for SSR because an Astro page may contain Astro components, HTML components, and React, Preact, Solid, Vue, or Svelte islands in the same tree. Adapter output needs to host one application, but the render pipeline must still choose the right component renderer for each boundary.

Sources: packages/astro/src/runtime/server/render/component.ts

Server Islands and Adapter Requirements

Server islands are a special SSR use case because they split the page into an immediately delivered shell and separately fetched dynamic component output. The official docs describe server islands as normal server-rendered Astro components that delay rendering until their contents are available, with fallback content displayed first. The component renderer source backs this feature by importing server-island helpers and render instructions, while also relying on serializable props through serializeProps. That pairing explains the user-facing rule: server-island props must be transferred across a network boundary, so values such as functions or circular objects cannot be used even if they would work inside a purely local component tree.

Sources: packages/astro/src/runtime/server/render/component.ts

Adapters are required for server islands because the delayed island must have a server endpoint capable of rendering it when the browser asks for it. The adapter’s job is to make that endpoint executable in the chosen deployment runtime. The core renderer’s job is to preserve Astro’s component behavior, head buffering, slots, hydration metadata, and server-island instructions. This division is useful when debugging: if the island endpoint is not reachable, inspect adapter setup and deployment routing; if the island response renders the wrong component output, inspect component rendering, directives, props serialization, and renderer selection.

Sources: packages/astro/src/runtime/server/render/component.ts, packages/astro/src/runtime/server/render/index.ts

Deployment and CI/CD Signals

The repository includes automation that supports deployable examples and controlled execution environments. .github/workflows/examples-deploy.yml runs on pushes to main that affect examples/** and can also run through workflow_dispatch. Its deploy job is restricted to the withastro repository owner, checks out the repository, and sends a POST request to a Netlify build hook stored in secrets.NETLIFY_PREVIEWS_BUILD_HOOK. That workflow is not an Astro adapter, but it shows how the project keeps preview.astro.new aligned with example changes, including examples that demonstrate SSR, routing, integrations, and deployment-oriented patterns.

Sources: .github/workflows/examples-deploy.yml

The sandbox image workflow provides a separate infrastructure signal. .github/workflows/build-sandbox-image.yml publishes ghcr.io/${{ github.repository }}/flue-sandbox when selected sandbox files or the workflow itself change, and it can also be run manually. It lowercases the image name, logs into GitHub Container Registry with GITHUB_TOKEN, sets up Docker Buildx, and builds .flue/sandbox/Dockerfile with GitHub Actions cache. For SSR and adapter contributors, this workflow is relevant because reproducible sandbox environments help stabilize development and validation around runtime behavior, even when final deployment targets differ.

Sources: .github/workflows/build-sandbox-image.yml

Practical Workflow

To enable SSR in an Astro project, install an adapter that matches the deployment environment and configure Astro for on-demand rendering where needed. The official docs commonly show the one-step flow with astro add, for example installing the Netlify adapter with npx astro add netlify. Once an adapter is configured, routes can be rendered per request, and server islands can use server:defer for component-level delayed rendering. When evaluating behavior, separate three questions: whether the adapter deploys the server entrypoint, whether the route pipeline resolves params and props correctly, and whether the component renderer emits the expected HTML, scripts, styles, and island instructions.

npx astro add netlify

For source-level investigation, start broad and then narrow. Use packages/astro/src/core/render/index.ts to understand the core symbols that feed the render pipeline. Move to packages/astro/src/runtime/server/render/index.ts to see the complete runtime render surface and identify whether the issue concerns pages, components, scripts, slots, streaming, or tags. Then inspect packages/astro/src/runtime/server/render/component.ts for framework components, hydration directives, server-island behavior, slot rendering, and head handling. If the problem only appears after deployment, compare local renderer behavior with the adapter and hosting runtime, then check preview and sandbox automation signals for reproducibility expectations.

Sources: packages/astro/src/core/render/index.ts, packages/astro/src/runtime/server/render/index.ts, packages/astro/src/runtime/server/render/component.ts

Next Steps

Read the on-demand rendering and deployment overview material next if you are deciding when to add an adapter, then move to adapter-specific pages for Cloudflare, Netlify, Vercel, Node, or Deno deployment details. If your issue is component output rather than hosting, follow the API and modules references for render exports, directives, islands, scripts, and content that run inside the server pipeline. For contributors changing SSR behavior, pair runtime changes with examples that exercise the affected route or component shape, because the examples deployment workflow is the repository signal that public starter behavior remains visible after changes land.

Sources: .github/workflows/examples-deploy.yml, packages/astro/src/runtime/server/render/index.ts