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:

app/pricing/page.vsk
									
										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

app/components/BlogPost.vsk
										
											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.