meta export
Declare per-page head metadata via a meta export.
The pattern
Every page module may export a meta constant (or an async function returning the same record) describing per-page metadata — title, description, and layout override. The build reads this export, parses it into a typed record (crates/), and resolves which layout module wraps the page. The renderer itself emits no <head> tags; the layout component owns <head> and decides what to render with the values it receives.
Example
export const meta = {
title: "Blog — My Site",
description: "Latest writing on web development.",
};
export default function BlogPage() {
return <article>{/* ... */}</article>;
}If you need data from a collection or an async source to compute meta — for example, a title derived from a CMS field — export meta as an async function. The renderer awaits it before rendering the page shell.
export async function meta() {
const post = getCollection("blog")[0];
return {
title: post.data.title,
description: post.data.description,
};
}Supported keys
PageMeta accepts exactly the following keys. Unknown keys are rejected at parse time (deny_unknown_fields) so that typos surface as build errors rather than being silently dropped.
title?: string— overrides the layout default for this page.description?: string— made available to the layout component, which decides whether to render a<meta name="description">tag. The bundled default layout currently does not emit one.layout?: string— module specifier (relative path or bare specifier) for the page layout component. When absent, the project default layout is used.
Note
Canonical URL, Open Graph, and Twitter Card tags are not part of PageMeta — there is no meta→<head> emission pipeline to extend (the layout owns <head>). To add these tags, inject them directly in your layout component, or use a build-time plugin to emit <head> content.