Manifest
A build that only writes images leaves the site to work out for itself what was
generated, where it lives and how big it is, which usually means globbing for
*-og.png to find the landscape variant, or hardcoding 1200 and 630 into the
meta tags. All of that is known while the images are being generated, so
pointing manifest at a file writes it down:
export default defineConfig({ placement: { strategy: "public-dir", dir: "public/og", urlBase: "/og" }, manifest: "data/colophon.json", // src/data/ for Astro, _data/ for Eleventy});{ "version": 1, "pages": { "blog/my-post": { "images": { "og": { "url": "/og/blog/my-post-og.png", "width": 1200, "height": 630 }, "square": { "url": "/og/blog/my-post-square.png", "width": 1200, "height": 1200 } }, "widest": "og", "alt": "My post" } }}Every generator in scope reads JSON as native data. Hugo picks it up from
data/, Astro imports it, Eleventy and Jekyll read _data/, and Zola has
load_data. That makes the meta tags a lookup rather than a convention:
const page = manifest.pages["blog/my-post"];const image = page.images[page.widest];// <meta property="og:image" content={image.url}>// <meta property="og:image:width" content={image.width}>metaTags will do that part for you.
What is in it
Section titled “What is in it”- Pages are keyed by slug, which is what the site addresses a page by, and
under
slugStrategy: "route"is the route itself. Two pages cannot share a key, and a build that would need them to fails saying so, because a lookup returning the wrong post’s image is worse than no manifest at all. widestnames the most landscape image by aspect ratio, ties going to the size configured first. It is what asummary_large_imagecard wants, and the check every site currently writes for itself. Note that og (1200x630) and square (1200x1200) are equally wide, so comparing widths would pick either.urlis absent where the placement knows none. See Placement. The dimensions are always there.altcomes from the props’ title, and is absent for a page without one.- Extra images are not pages, so they are not listed. A project that named the output path of one already knows where it is.
What it describes
Section titled “What it describes”The manifest describes what exists, not what a given run did. A rebuild that skips every image still writes the whole thing, so a build over an unchanged tree still produces a complete record of the site.
It is built from the planned work rather than the results, which is also why a duplicate slug fails before the tree is rendered rather than after.
Pages and sizes are sorted and the JSON is indented, so a manifest committed to a repository changes only when the build does.
