Skip to main content
The Container API allows you to render Astro components in isolation, useful for testing, server-side rendering, and on-demand page generation.

Importing

import { experimental_AstroContainer as AstroContainer } from 'astro/container';

AstroContainer.create

Create a new container instance.
AstroContainer.create(options?: AstroContainerOptions): Promise<AstroContainer>
options
AstroContainerOptions
Container configuration options.
streaming
boolean
Enable streaming during rendering.Default: false
const container = await AstroContainer.create({
  streaming: true,
});
renderers
SSRLoadedRenderer[]
Array of renderers for UI framework components (React, Vue, etc.).Default: []
import reactRenderer from '@astrojs/react/server.js';
import vueRenderer from '@astrojs/vue/server.js';

const container = await AstroContainer.create({
  renderers: [reactRenderer, vueRenderer],
});
astroConfig
AstroContainerUserConfig
Subset of Astro configuration options.
const container = await AstroContainer.create({
  astroConfig: {
    trailingSlash: 'never',
    site: 'https://example.com',
  },
});

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';

const container = await AstroContainer.create();

renderToString

Render a component to an HTML string.
container.renderToString(
  component: AstroComponentFactory,
  options?: ContainerRenderOptions
): Promise<string>
component
AstroComponentFactory
required
The Astro component to render.
options
ContainerRenderOptions
Rendering options.
request
Request
Request object for the render. Used to populate Astro.request and Astro.url.
const html = await container.renderToString(Component, {
  request: new Request('https://example.com/page'),
});
params
Record<string, string | undefined>
Route parameters for dynamic routes.
// For src/pages/blog/[slug].astro
const html = await container.renderToString(Component, {
  params: { slug: 'my-post' },
});
props
Record<string, any>
Props to pass to the component via Astro.props.
const html = await container.renderToString(Component, {
  props: { title: 'Hello', count: 42 },
});
slots
Record<string, any>
Slot content to pass to the component.
const html = await container.renderToString(Component, {
  slots: {
    default: 'Main content',
    header: '<h1>Header</h1>',
  },
});
locals
App.Locals
Locals object accessible via Astro.locals.
const html = await container.renderToString(Component, {
  locals: { user: { id: '123', name: 'John' } },
});
routeType
'page' | 'endpoint'
Type of route being rendered.Default: 'page'
const html = await container.renderToString(Endpoint, {
  routeType: 'endpoint',
});
partial
boolean
When false, renders the component as a full page. When true, renders as a partial.Default: true
const html = await container.renderToString(Component, {
  partial: false, // Render complete page
});

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import Card from '../src/components/Card.astro';

const container = await AstroContainer.create();

const html = await container.renderToString(Card, {
  props: {
    title: 'My Card',
    description: 'Card description',
  },
});

console.log(html); // <div class="card">...</div>

renderToResponse

Render a component and return a Response object.
container.renderToResponse(
  component: AstroComponentFactory,
  options?: ContainerRenderOptions
): Promise<Response>
Accepts the same parameters as renderToString, but returns a Response object instead of a string.

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import Page from '../src/pages/index.astro';

const container = await AstroContainer.create();

const response = await container.renderToResponse(Page, {
  request: new Request('https://example.com/'),
});

console.log(response.status); // 200
const html = await response.text();

addServerRenderer

Manually add a server renderer to the container.
container.addServerRenderer(options: AddServerRenderer): void
options
AddServerRenderer
required
Renderer options.
renderer
NamedSSRLoadedRendererValue | SSRLoadedRendererValue
required
The server renderer exported by an integration.
name
string
Name of the renderer. Required if the renderer is not a named renderer.

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import reactRenderer from '@astrojs/react/server.js';
import vueRenderer from '@astrojs/vue/server.js';

const container = await AstroContainer.create();

// Named renderer (has .name property)
container.addServerRenderer({ renderer: reactRenderer });

// Non-named renderer
container.addServerRenderer({ 
  renderer: vueRenderer, 
  name: '@astrojs/vue' 
});

addClientRenderer

Manually add a client renderer to the container for components using client:* directives.
container.addClientRenderer(options: AddClientRenderer): void
options
AddClientRenderer
required
Client renderer options.
name
string
required
Name of the renderer. Must match the server renderer name.
entrypoint
string
required
Client-side entrypoint for the renderer.

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import reactRenderer from '@astrojs/react/server.js';

const container = await AstroContainer.create();

// Add server renderer first
container.addServerRenderer({ renderer: reactRenderer });

// Then add client renderer
container.addClientRenderer({
  name: '@astrojs/react',
  entrypoint: '@astrojs/react/client.js',
});

insertPageRoute

Register a page route in the container for use with Astro.rewrite().
container.insertPageRoute(
  route: string,
  component: AstroComponentFactory,
  params?: Record<string, string | undefined>
): void
route
string
required
The URL path that will render the component.
component
AstroComponentFactory
required
The component to render for this route.
params
Record<string, string | undefined>
Route parameters for dynamic routes.

Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import Home from '../src/pages/index.astro';
import About from '../src/pages/about.astro';
import Blog from '../src/pages/blog/[slug].astro';

const container = await AstroContainer.create();

container.insertPageRoute('/', Home);
container.insertPageRoute('/about', About);
container.insertPageRoute('/blog/[slug]', Blog, { slug: 'my-post' });

// Now these routes can be used with Astro.rewrite()

Testing Example

The Container API is particularly useful for testing:
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import { expect, test } from 'vitest';
import Card from '../src/components/Card.astro';

test('Card component renders correctly', async () => {
  const container = await AstroContainer.create();
  
  const html = await container.renderToString(Card, {
    props: {
      title: 'Test Card',
      description: 'This is a test',
    },
  });
  
  expect(html).toContain('Test Card');
  expect(html).toContain('This is a test');
});

test('Card with slots', async () => {
  const container = await AstroContainer.create();
  
  const html = await container.renderToString(Card, {
    slots: {
      default: '<p>Slot content</p>',
    },
  });
  
  expect(html).toContain('Slot content');
});

Framework Component Example

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import reactRenderer from '@astrojs/react/server.js';
import MyReactComponent from '../src/components/MyReactComponent.astro';

const container = await AstroContainer.create();

// Add React renderer
container.addServerRenderer({ renderer: reactRenderer });
container.addClientRenderer({
  name: '@astrojs/react',
  entrypoint: '@astrojs/react/client.js',
});

// Render component with React
const html = await container.renderToString(MyReactComponent, {
  props: { message: 'Hello from React' },
});

Build docs developers (and LLMs) love