Nimbus handles the metadata baseline automatically and gives you per-page and site-wide control where you need it.
Titles and descriptions
title and description frontmatter populate <title> and <meta name="description">, and feed the search snippet and llms.txt indexes. Site-wide fallbacks come from the Nimbus config:
const nimbusConfig = defineNimbusConfig({
site: "https://docs.example.com",
title: "Acme",
description: "Build with Acme.",
});Open Graph images
Set a site-wide fallback card and alt text, then override per page:
const nimbusConfig = defineNimbusConfig({
// …
socialImage: "/og.png",
socialImageAlt: "Acme documentation",
});---
title: Pricing
socialImage: /og/pricing.png
---Nimbus also ships an OG image route, so pages without an explicit image get a generated card: the site’s logo, the page’s section and its title. See Customize OG cards.
A docs page uses its frontmatter socialImage, or else its generated card, /og/<page>.png.
Other pages, such as the 404 page and hand-written routes, use the first that exists: config.socialImage, public/opengraph.png or public/logo.png, then the generated /og.png card.
Image paths are logical paths without Astro’s deployment base. For a site deployed at /docs, keep socialImage: "/og.png"; Nimbus produces /docs/og.png. Absolute and protocol-relative image URLs are preserved.
Image sizes
og:image:width and og:image:height are written only when the size is known, so a link preview is never cropped to the wrong shape:
- Generated cards (
/og.pngand/og/<page>.png) are 1200 × 630. config.socialImage, the auto-detectedpublic/opengraph.pngorpublic/logo.png, and every image underpublic/og/are measured at build time.- Any other image, such as a remote URL or a per-page file elsewhere in
public/, gets no size tags. Pass the size where you know it, associalImageSizeonNimbusHeador on the starter’sBaseLayout:
<NimbusHead title={title} socialImage="/diagrams/cover.png" socialImageSize={{ width: 1600, height: 900 }} />Sitemap and robots
When site is set, the sitemap integration and /robots.txt are wired automatically. Disable the sitemap with sitemap: false in the integration options.
The sitemap is written as sitemap-index.xml plus sitemap-0.xml, and /sitemap.xml is a copy of the index for tools that only try that name. A site that serves its own /sitemap.xml, as a file in public/, a sitemap.xml route, or a dynamic [name].xml route at the root, keeps it.
A docs page’s <lastmod> is its frontmatter lastUpdated, or else the date of the last commit to its file, matching its “Last updated” line. Pages with no content file, such as API pages, have none.
A serialize option in sitemap runs afterwards, so it can change or drop the value.
Git dates need the repository’s history. On a shallow clone, which most CI systems make by default, the build says so once and leaves out every git date: the sitemap’s lastmod and the “Last updated” line on pages. Fetch the full history to restore them, with fetch-depth: 0 in GitHub Actions or git fetch --unshallow.
Per-page and site-wide head
Add elements to <head> site-wide via config.head, or per page via frontmatter — the two are merged:
---
title: Analytics-tracked page
head:
- tag: meta
attrs: { name: "robots", content: "noindex" }
- tag: link
attrs: { rel: "canonical", href: "https://example.com/canonical" }
---Valid tags: meta, link, script, style, title, noscript, base. To exclude a page from crawlers without hand-writing the tag, use noindex: true.
Canonical URLs
On versioned sites, Nimbus emits <link rel="canonical"> pointing older versions at the current one, plus <link rel="alternate"> between siblings — driven by previousSlug.