docs / Runtime
SEO
Titles and descriptions via defineMetadata, structured data via the JsonLd component and schema generators, plus vesk seo to audit your app.
Vesk provides structured data (JSON-LD) components for search engine optimization. All auto-imported from `@vesk/runtime`.
Titles and descriptions
Declare a route's head as data with `export const metadata = defineMetadata({...})` from `@vesk/runtime`. It is evaluated at build time in a sealed sandbox, so the title cannot come out empty the way an interpolated `<Head>` expression can, and `vesk seo` understands it:
import { defineMetadata } from '@vesk/runtime'
export const metadata = defineMetadata({
title: 'Pricing',
description: 'What it costs, and what it does not.',
openGraph: { title: 'Pricing', image: '/og.png' },
alternates: { canonical: '/pricing' },
})
component Page() {
<h1>Pricing</h1>
}
For a title that depends on the route (a docs site with one page per slug, say), use `<Head>` — it is the reactive path — and the two merge, static first. See the Metadata page for why interpolated `<Head>` titles are worth avoiding where you can, and how `vesk seo` treats both.
JsonLd component
component BlogPost(props: { title: string, date: string, author: string }) {
<div>
<h1>{props.title}</h1>
<JsonLd schema={ArticleSchema({
headline: props.title,
datePublished: props.date,
author: { name: props.author },
})} />
</div>
}
- Renders a `<script type="application/ld+json">` tag with the structured data.
- Schema generators return Record<string, unknown> objects with @type set: ArticleSchema, ProductSchema, FAQPageSchema, BreadcrumbListSchema, OrganizationSchema, LocalBusinessSchema, VideoSchema.
`vesk seo` runs the SEO audit against app/ (RouteOutput checks); pass `--strict` to make audit errors fail the build or exit non-zero.