Skip to content

Astro Container API (experimental)

The Container API allows to render Astro components in isolation.

Added in: astro@4.9.0 Beta

Creates a new instance of the container.

import { experimental_AstroContainer } from "astro/container";
const container = await experimental_AstroContainer.create();

It accepts an object with the following options

export type AstroContainerOptions = {
streaming?: boolean;
renderers?: AstroRenderer[];
astroConfig?: AstroContainerUserConfig;
};

Enables rendering components using the streaming.

Type: boolean

A list of client renderers. Add a renderer if your Astro component renders some client components such as React, Preact, etc.

Type:: AstroRenderer[];

For example, if you’re rendering a Astro component that renders a React component, you’ll have to provide the following renderer:

const container = await experimental_AstroContainer.create({
renderers: [
{
name: "@astrojs/react",
client: "@astrojs/react/client.js",
server: "@astrojs/react/server.js"
}
]
})
const result = await container.renderToString(ReactWrapper);

A subset of the Astro user configuration.

Type: AstroContainerUserConfig

It renders a component, and it returns a string that represents the HTML/content rendered by the Astro component.

import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();
const result = await container.renderToString(Card);

Under the hood, this function calls renderToResponse and calls Response.text().

It accepts a number of options.

It renders a component, and it returns a Response object.

import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();
const result = await container.renderToResponse(Card);

It accepts a number of options.

Both renderToResponse and renderToString accept an object as their second argument:

export type ContainerRenderOptions = {
slots?: Record<string, any>;
request?: Request;
params?: Record<string, string | undefined>;
locals?: App.Locals;
routeType?: "page" | "endpoint";
};

Type: Record<string, any>;

Use this options if your component needs to render some slots.

If your components renders one slot, pass an object with default as key:

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
slots: { default: "Some value"}
});

If your component renders named slots, use the keys of the object to name the slots:

---
---
<div>
<slot name="header" />
<slot name="footer" />
</div>
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
slots: { "header": "Header content", "footer": "Footer" }
});

You can also render components in cascade:

---
---
<div>
<slot name="header" />
<slot name="footer" />
</div>
import Card from "../src/components/Card.astro";
import CardHeader from "../src/components/CardHeader.astro";
import CardFooter from "../src/components/CardFooter.astro";
const result = await container.renderToString(Card, {
slots: {
"header": await container.renderToString(CardHeader),
"footer": await container.renderToString(CardFooter),
}
});

Type: Request

The request is used to understand which path/URL the component is about to render.

Use this option in case your component needs to read information like Astro.url or Astro.request.

You can also inject possible headers or cookies.

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
request: new Request("https://example.com/blog", {
headers: {
"X-some-secret-header": "test-value"
}
})
});

Type: Record<string, string | undefined>;

Use this option in case your component needs to read Astro.params. As opposed to getStaticPaths, you must provide only one item of the params returned by that function.

---
const { locale, slug } = Astro.params;
---
<div></div>
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
params: {
locale: "en",
slug: "getting-started"
}
});

Type: App.Locals

Use this option to stub the Astro.locals object:

---
const { checkAuth } = Astro.locals;
const isAuthenticated = checkAuth();
---
{isAuthenticated ? <span>You're in</span> : <span>You're out</span> }
import Card from "../src/components/Card.astro";
test("User is in", async () => {
const result = await container.renderToString(Card, {
locals: {
checkAuth() { return true }
}
});
// assert result contains "You're in"
})
test("User is out", async () => {
const result = await container.renderToString(Card, {
locals: {
checkAuth() { return false }
}
});
// assert result contains "You're out"
})

Type: "page" | "endpoint"

Useful in case you’re rendering an endpoint. In this case, you want to use renderToResponse:

container.renderToString(Endpoint, { routeType: "endpoint" });
import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, {
routeType: "endpoint"
});
const json = await response.json();

If your endpoint needs to be tested on methods such as POST, PATCH, etc., you’ll have to use the request option to signal Astro to call the correct function:

export function GET() {}
// need to test this
export function POST() {}
import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, {
routeType: "endpoint",
request: new Request("https://example.com", {
method: "POST" //
})
});
const json = await response.json();