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>
Container configuration options.Enable streaming during rendering.Default: falseconst container = await AstroContainer.create({
streaming: true,
});
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],
});
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.
Rendering options.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 to pass to the component via Astro.props.const html = await container.renderToString(Component, {
props: { title: 'Hello', count: 42 },
});
Slot content to pass to the component.const html = await container.renderToString(Component, {
slots: {
default: 'Main content',
header: '<h1>Header</h1>',
},
});
Locals object accessible via Astro.locals.const html = await container.renderToString(Component, {
locals: { user: { id: '123', name: 'John' } },
});
Type of route being rendered.Default: 'page'const html = await container.renderToString(Endpoint, {
routeType: 'endpoint',
});
When false, renders the component as a full page. When true, renders as a partial.Default: trueconst 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 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 of the renderer. Must match the server renderer name.
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',
});
Register a page route in the container for use with Astro.rewrite().
container.insertPageRoute(
route: string,
component: AstroComponentFactory,
params?: Record<string, string | undefined>
): void
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' },
});