Configuration

Configure the layer through nuxt.config.ts, app.config.ts, and environment variables.

The layer is configured in three places:

  • nuxt.config.ts — build-time options: site identity and the comarkDocs key.
  • 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:

nuxt.config.ts
export default defineNuxtConfig({
  extends: ['comark-docs'],
  site: {
    url: 'https://docs.example.com',
    name: 'My Project',
  },
})

comarkDocs options

nuxt.config.ts
export default defineNuxtConfig({
  extends: ['comark-docs'],
  comarkDocs: {
    isr: 300,
    contentDir: 'docs/content',
    codeExplorer: {
      allowRepos: ['my-org/examples'],
    },
  },
})
OptionDefaultPurpose
isr300ISR expiration in seconds for the generated route rules. Set to false to disable them entirely.
contentDirinferredContent 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.
A build that can't see .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:

nuxt.config.ts
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:

app.config.ts
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

KeyDefaultPurpose
seo.siteNamesite nameName used in title templates, OG tags, and JSON-LD.
header.titlesite nameTitle 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.searchtrueShow 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.ownersite nameCopyright 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.enabledfalseEnable 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.nameinferredRepository 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.
Nuxt merges 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.description is emitted as the blockquote summary of llms.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.organization is emitted as a top-level Organization JSON-LD node on the landing page. Give it a contactPoint (and optionally an address, a PostalAddress) so agents can verify the business behind the site.
app.config.ts
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

VariablePurpose
GITHUB_TOKENGitHub content reads and GraphQL history/RSS. Required in production.
GLOBAL_CONFIGConnection string for the optional contentSha production pin. Vercel creates it when you connect a Global Config store to the project.
WEBHOOK_SECRETHMAC secret for the GitHub push webhook (/api/revalidate).
VERCEL_BYPASS_TOKENISR purge on revalidation. Needed at build time too.
NUXT_OG_IMAGE_SECRETOG image signing.
NUXT_ASSISTANT_MODELOverride 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.