Skip to main content

Page metadata

Every content file may carry a meta: block:

content/about/_index.yml
meta:
title: "About us"
description: "Who we are and what we build."

meta is reserved at the root of a content file whether or not autoMetadata is on, so turning the flag on later cannot silently start consuming a field you wrote.

The one-line version

app/about/page.tsx
export { generateMetadata } from 'copy-ink/server'

That is as automatic as Next allows — a page must export the function itself, so there is no way for a library to install it for you.

It returns title, description, and an openGraph block mirroring both.

Composing with your own metadata

app/about/page.tsx
import { getMetadata } from 'copy-ink/server'
import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
const meta = await getMetadata()

return {
...meta,
alternates: { canonical: 'https://example.com/about' },
openGraph: {
...meta.openGraph,
images: ['/og/about.png'],
},
}
}

getMetadata takes the same scope and locale options as getCopy, so a route can read another page's metadata when it needs to.

Collections

Item metadata comes from the item's own file. Read it with getItem:

app/blog/[slug]/page.tsx
import { getItem } from 'copy-ink/server'

export async function generateMetadata({ params }) {
const { slug } = await params
const post = await getItem('posts', slug)

return {
title: post?.data.title as string,
description: post?.data.excerpt as string,
}
}

autoMetadata

autoMetadata: true

The flag marks the project as metadata-driven. It does not — and cannot — export generateMetadata on your behalf; a page must still export it itself, as above.

caution

With the flag on, copy-ink check reports meta-conflict for any content file carrying a root meta: key, on the grounds that meta is then owned by copy-ink rather than by you. In practice that flags the very files you meant to write, so leave autoMetadata off and use export { generateMetadata } until that check is settled.