Configuration
The layer is configured in three places:
nuxt.config.ts— build-time options: site identity and thecomarkDocskey.app.config.ts— branding and navigation: header, footer, assistant, OG images.- Environment variables — secrets and runtime overrides.
nuxt.config.ts
Site identity
The site config drives canonical URLs, the sitemap, OG tags, and JSON-LD:
export default defineNuxtConfig({
extends: ['comark-docs'],
site: {
url: 'https://docs.example.com',
name: 'My Project',
},
})comarkDocs options
export default defineNuxtConfig({
extends: ['comark-docs'],
comarkDocs: {
isr: 300,
contentDir: 'docs/content',
codeExplorer: {
allowRepos: ['my-org/examples'],
},
},
})| Option | Default | Purpose |
|---|---|---|
isr | 300 | ISR expiration in seconds for the generated route rules. Set to false to disable them entirely. |
contentDir | inferred | Content directory relative to the repository root (an app in docs/ becomes docs/content). Inferred from the local git checkout. |
codeExplorer.allowRepos | [] | Extra owner/repo entries the CodeExplorer component may fetch from. The content repository is always allowed. |
.git (a shallow Docker build, an exported tarball) can't infer contentDir and assumes the app is the repository root. If your app lives in a subdirectory, set comarkDocs.contentDir (or NUXT_DOCS_CONTENT_DIR) explicitly — the build warns when it has to guess.agentDiscovery options
Markdown for agents is nuxt-agent-discovery, configured under agentDiscovery. The layer points it at the content instance, keeps versioned previews out of negotiation and seeds the MCP server card. Everything else is the module's defaults, and the option you are most likely to touch is the Agent Skills directory:
export default defineNuxtConfig({
extends: ['comark-docs'],
agentDiscovery: {
skills: {
dir: 'skills',
},
},
})Each subdirectory holding a SKILL.md with a description is published at /.well-known/skills/. Skills are scanned at build time from the app, not from GitHub-sourced content, so a skill change needs a redeploy.
app.config.ts
Branding and navigation live in app.config.ts. Everything is optional — this playground's own config is a good starting point:
export default defineAppConfig({
seo: {
siteName: 'My Project',
},
header: {
title: 'My Project',
// Main navigation tabs; omit to derive one tab per top-level section
nav: [
{ label: 'Documentation', sections: ['getting-started', 'writing'] },
{ label: 'API Reference', sections: ['reference'] },
],
links: [
{ icon: 'i-simple-icons-github', to: 'https://github.com/my-org/my-repo', target: '_blank' },
],
},
footer: {
icon: 'i-lucide-book',
owner: 'My Company',
links: [
{ icon: 'i-lucide-rss', to: '/rss.xml', target: '_blank', 'aria-label': 'RSS Feed' },
],
},
})All keys
| Key | Default | Purpose |
|---|---|---|
seo.siteName | site name | Name used in title templates, OG tags, and JSON-LD. |
header.title | site name | Title displayed next to the logo. |
header.to | '/' | Link target of the header logo. |
header.logo | — | { alt, mark, light, dark }. light/dark are image URLs per color mode; mark selects a wordmark shipped with the layer. |
header.ecosystem | [] | Sibling sites listed in the brand popover; empty hides the popover. |
header.search | true | Show the search button. |
header.nav | [] | Main navigation tabs; each group maps top-level content sections to a tab. Empty derives one tab per section — see Navigation. |
header.links | [] | Right-side icon links. |
footer.credits | '' | Full credits line; empty renders © ${year} ${owner}. |
footer.owner | site name | Copyright holder when it isn't the site itself. |
footer.icon | '' | Optional icon rendered before the credits. |
footer.links | [] | Footer icon links. |
toc.title | 'On this page' | Table of contents heading. |
assistant.enabled | false | Enable the "Ask AI" assistant. |
assistant.faqQuestions | [] | Suggested questions shown before the first message, grouped by category. |
github.branch | 'main' | Production content branch. |
github.owner / github.name | inferred | Repository owner and name (inferred from git when unset). |
docs.rss.title | '' | RSS feed title; empty renders ${siteName} Documentation. |
docs.ogImage | — | { accent, tagline, mark } for the generated OG images. |
docs.llms | — | { description, links } emitted in llms.txt. description becomes the blockquote summary under the heading (empty falls back to the site description). |
docs.schemaOrg | {} | schema.org SoftwareApplication identity, emitted as JSON-LD on the landing page. The organization sub-key is emitted as a separate Organization node — see below. |
docs.asideLinks | [] | Extra links appended to the docs page aside. |
app.config.ts across layers with defu, which concatenates arrays. Your list is appended to the layer's, not substituted for it — which is why every array default in the layer is empty.Agent metadata
Two optional keys help AI agents understand and verify your site:
docs.llms.descriptionis emitted as the blockquote summary ofllms.txt— the place the llms.txt spec reserves for key context. Use it to tell agents when to reach for your product: name the jobs it is right for and how an agent calls it — specific guidance, not marketing copy.docs.schemaOrg.organizationis emitted as a top-levelOrganizationJSON-LD node on the landing page. Give it acontactPoint(and optionally anaddress, a PostalAddress) so agents can verify the business behind the site.
export default defineAppConfig({
docs: {
llms: {
description:
'Use My Project to build documentation sites where Markdown is served at request time. ' +
'Fetch any page as raw markdown at `/raw/<path>.md`, or request any page URL with `Accept: text/markdown`.',
},
schemaOrg: {
applicationCategory: 'DeveloperApplication',
organization: {
contactPoint: { '@type': 'ContactPoint', contactType: 'customer support', email: 'support@example.com' },
sameAs: ['https://github.com/my-org'],
},
},
},
})Environment variables
| Variable | Purpose |
|---|---|
GITHUB_TOKEN | GitHub content reads and GraphQL history/RSS. Required in production. |
GLOBAL_CONFIG | Connection string for the optional contentSha production pin. Vercel creates it when you connect a Global Config store to the project. |
WEBHOOK_SECRET | HMAC secret for the GitHub push webhook (/api/revalidate). |
VERCEL_BYPASS_TOKEN | ISR purge on revalidation. Needed at build time too. |
NUXT_OG_IMAGE_SECRET | OG image signing. |
NUXT_ASSISTANT_MODEL | Override the AI Gateway model serving /api/assistant. |
The GitHub repository, branch, and content directory are inferred from the local git checkout and VERCEL_GIT_* variables. Override them at runtime with NUXT_DOCS_* variables: NUXT_DOCS_GITHUB_OWNER, NUXT_DOCS_GITHUB_REPO, NUXT_DOCS_GITHUB_BRANCH, and NUXT_DOCS_CONTENT_DIR.
See Deploy on Vercel for where each variable is set in production.