Updated 2026-10-20
Add SEO meta tags to a Vite site at build time
A fresh Vite project ships with <title>Vite App</title> and nothing else in the head: no description, no link preview tags, no structured data, and images without alt text. That's what Google and every link previewer see until someone writes it by hand.
Headlark runs after vite build, reads each HTML file in dist, and writes the metadata into the files before your host uploads them.
1. Install and add it to your build
npm i -D headlark
// package.json
"scripts": {
"build": "vite build && headlark dist --site-url https://example.com"
}
--site-url is your production address. Page URLs and canonicals are built from it: dist/index.html becomes https://example.com/ and dist/about.html becomes https://example.com/about.
2. Add your key to the build environment
Create the site in the dashboard and set HEADLARK_KEY to its secret key where your build runs: Vercel (Project → Settings → Environment Variables), Netlify (Site configuration → Environment variables, or use the Netlify plugin), or a GitHub Actions secret.
3. Build
Each page is logged as (generated) or (cached). Pages whose content hasn't changed come from cache on every later build, at no cost. Every CLI option is in the build step docs.
To see what your deployed site is missing today, run the free site checker on it. It lists duplicate titles, missing descriptions and broken link previews across up to 50 pages.
A real before and after
This is the Vite fixture from our test suite, a Swedish bakery page, before and after the build step. The output below is produced by the same code the CLI runs.
<!-- before: dist/index.html -->
<title>Vite App</title>
<img src="/assets/hero-brod.jpg">
<!-- after (excerpt) -->
<title>Surdegsbageriet på Svartbäcken | Bageri i Uppsala</title>
<meta name="description" content="Handbakat surdegsbröd, kardemummabullar och kanelknutar i Uppsala. Se veckans bröd, öppettider och förbeställ till helgen.">
<meta property="og:title" content="Surdegsbageriet på Svartbäcken – handbakat i Uppsala">
<meta property="og:image" content="https://surdegsbageriet.example/assets/hero-brod.jpg">
<meta name="twitter:card" content="summary_large_image">
<link rel="canonical" href="https://surdegsbageriet.example/">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Bakery","telephone":"018-12 34 56","address":{…},"openingHoursSpecification":[…]}</script>
<img src="/assets/hero-brod.jpg" alt="Nybakade surdegsbröd från bageriet i Uppsala">
The page was in Swedish, so the output is too. The phone number, address and opening hours in the JSON-LD are all on the page; Headlark checks numbers and emails against the page before it writes them.
Good to know
- Single-page apps: a plain Vite SPA builds one
index.htmlfor every route, so there is one page to describe. To get per-route metadata, prerender each route to its own HTML file at build time first. - Your own tags: Headlark writes the title and description. A canonical, robots directive or JSON-LD type you already have is kept.
- Running it twice on the same output changes nothing.
- A page that fails is left untouched and the build continues. Add
--strictto fail the build instead.
Try it
The free plan covers one site and 25 pages. Add your site, copy its secret key, and your next build ships with SEO.