Deploy
How a Ginko site goes live. Vercel with ISR, a static build for sites from files, the environment variables, and what a static host cannot do.
Two kinds of site
How you deploy depends on where the content comes from:
- Files only. Every brick has
source: 'files'. The content is fixed at build time. You can build a static site withnuxt generateand put it on any static host, or deploy it to Vercel like any Nuxt site. - Platform. At least one brick comes from the platform. Owners change content after the deploy, so the site needs a server that fetches new content. Ginko is made and tested for Vercel.
Before the deploy, run ginko check in CI. It checks the configuration, the content files and the links, and exits with code 1 on an error. See Platform and CLI.
Vercel
Import the repository on Vercel. Vercel detects Nuxt and runs nuxt build; you change nothing in the build settings.
Set url in ginko.config.ts to the production address. Ginko marks every other host, such as Vercel's preview deployments, with noindex, so previews never reach a search engine (see SEO and agents).
The module sets these cache rules for you (Vercel ISR). Your own routeRules in nuxt.config.ts win: Ginko fills only what you leave unset. The exception is /__ginko/: there Ginko always sets the cache rule and the cache-control and x-robots-tag headers, so the preview is never cached or indexed.
- Every page is cached and rendered again at most every 60 seconds. Query parameters share one cache entry. The 60 seconds are a default, not a promise: with your own rule for
/**(for examplerouteRules: { '/**': { isr: 300 } }), Ginko keeps yours. A rule for a narrower path, such as/news/**, wins anyway. /api/**is not cached, because your own server routes may depend on the language of the visitor.- Ginko's own addresses under
/__ginko/are never indexed. The build output among them, the search index/__ginko/search/<language>.jsonand the content of file bricks under/__ginko/files/, stays cached until the next deploy. On a site with platform bricks the search index holds platform content too, so it is cached like a page instead. Everything else there, such as the preview, is never cached. Which addresses are stable and which are internal: Addresses and headers. - If the platform does not answer, the page answers with 503 and Vercel keeps the last good page.
- The cache keeps one version per address and ignores
Vary. So a page answers with the same HTML for everyone, and agents read its Markdown at its.mdaddress. An error such as a missing page also always answers with the error page as HTML, even whencurlor a monitor withoutAccept: text/htmlasks first. Only/api/, addresses ending in.jsonand/__ginko/keep Nuxt's choice between JSON and HTML.
Ginko also turns off experimental.payloadExtraction. With it, Nuxt fetches a _payload.json on client navigation, and the server renders the target page with the content of production for it. Pages read the content that is already in the browser instead. So the preview never shows production content, and a navigation costs no extra render.
Share cards
A site with share cards (nuxt-og-image, in every starter) that renders on a server needs NUXT_APP_SECRET: a random secret of at least 32 characters. nuxt-og-image signs the card addresses with it; without it, every card answers with an error, and the build warns. create-ginko writes one into .env for your computer; set one on Vercel too. A static build (nuxt generate) draws every card at build time and needs none.
A platform site
A site with platform bricks needs these environment variables on Vercel. Set both for Production and Preview: a variable that exists only for Preview leaves the production site without content. A production build on Vercel without a platform address stops with an error; a preview build only warns.
| Variable | Value |
|---|---|
NUXT_PUBLIC_GINKO_PLATFORM | The address of the platform. Not needed when ginko.config.ts sets platform; the variable overrides it. Without both, every page with platform content answers 503, and the server log says so once. |
NUXT_GINKO_REVALIDATE_TOKEN | The site token: create it in the Studio under Team, "Site token". Optional, see below. A build on Vercel without it prints a warning. |
Without NUXT_GINKO_REVALIDATE_TOKEN, a published change reaches the site within 60 seconds. Ginko gives the token to Vercel as bypassToken, unless your nuxt.config.ts sets nitro.vercel.config.bypassToken itself. With it, the platform renders the changed pages again right after a publish, and owners can use "Update website now". The site's server also sends it when it loads content, so visitors cannot use up the site's request limit. Create the token in the Studio (Team, "Site token", owners only): the platform stores it and shows it once. Replacing it ends the old one at once, so set the new value on Vercel and deploy again right after.
In CI, ginko release brings a new schema to production before the deploy. A superseded run is not an error: it ends with exit code 0 and prints "deploy":false. So deploy only when it prints "deploy":true. The page Platform and CLI has a CI snippet and the table of exit codes.
Search engines index a site only on the address in its url; any other address gets noindex. A demo, or a site that runs on a preview address such as name.vercel.app until its domain switch, sets NUXT_PUBLIC_GINKO_NOINDEX=true on that deployment: robots.txt then blocks everything and every response sends X-Robots-Tag: noindex. Remove the variable when the site moves to its own domain.
Static build (files only)
A site whose bricks all come from files can be built as plain files:
npx nuxt generateThe output in .output/public holds every page in every language, the Markdown version of each entry, /llms.txt, /llms-full.txt, /sitemap.xml, /robots.txt, the search index and, for a docs site, the RSS feeds. Upload the folder to any static host. A broken link or a page that fails to render stops the build.
A static host has no server. So these parts do not work there:
- Redirects with patterns. Exact paths, from
redirectFromand fromredirects, become part of the output. Rules with:nameor*need a server. - The docs MCP endpoint (
/__ginko/docs-mcp). noindexon preview hosts. The staticrobots.txtis written for the production address. Keep preview deployments out of search engines with your host's own setting.
Need any of these? Deploy the same site with nuxt build to Vercel instead.
Docs sites
A site with @lupinum/ginko-docs reads its pages from files, so both ways work: nuxt generate for a static host, or Vercel for the MCP endpoint and redirects with patterns.
Ginko's own docs also publish the shadcn-vue registry of the components under /r. Its build (pnpm --filter @lupinum/ginko-components registry) writes the item links from url in sites/docs/ginko.config.ts. GINKO_REGISTRY_URL overrides that address, for example http://localhost:3500/r for a local test.