How to add llms.txt, JSON-LD, and AI crawler controls to Nuxt
Nuxt sites need the same machine-readable surface as any other modern website: llms.txt, structured data, markdown mirrors, crawler rules, and validation. The key is hooking into the build at the moment Nuxt has actually written your prerendered HTML to disk, so those artifacts reflect the final output.
Where the Nuxt adapter runs
@agentmarkup/nuxt is a Nuxt module that runs after Nitro finishes prerendering. It hooks Nitro's prerender:done event and processes the emitted .output/public directory: the same final-output-first model the other agentmarkup adapters use.
That means it is strongest on the nuxt generate path and on any route you prerender with routeRules or prerender: true. Those are the routes that produce build-time HTML files for the module to read and augment.
What the Nuxt adapter gives you
llms.txtgeneration from your config, with the homepage discovery link injected automatically- Optional
llms-full.txtwith inlined same-site markdown context when mirrors exist - JSON-LD injection into emitted HTML plus validation of existing schema blocks
- Optional markdown mirrors for thin or noisy prerendered pages that need a cleaner fetch target for agents
robots.txtpatching for AI crawler directives like GPTBot, ClaudeBot, and Google-Extended- Header support for Content-Signal and markdown canonicals through the static
_headersoutput - Build-time validation for schema mistakes, crawler conflicts, thin HTML, and markdown drift
Basic setup
Install the module:
pnpm add -D @agentmarkup/nuxtThen register it and pass the shared config under the agentmarkup key:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@agentmarkup/nuxt'],
agentmarkup: {
site: 'https://example.com',
name: 'Example Docs',
description: 'Technical docs and product pages.',
globalSchemas: [
{ preset: 'webSite', name: 'Example Docs', url: 'https://example.com' },
{ preset: 'organization', name: 'Example Inc.', url: 'https://example.com' },
],
llmsTxt: {
sections: [
{
title: 'Documentation',
entries: [
{
title: 'Getting Started',
url: '/docs/getting-started',
description: 'Setup guide and first steps',
},
],
},
],
},
llmsFullTxt: {
enabled: true,
},
markdownPages: {
enabled: true,
},
contentSignalHeaders: {
enabled: true,
},
aiCrawlers: {
GPTBot: 'allow',
ClaudeBot: 'allow',
PerplexityBot: 'allow',
'Google-Extended': 'allow',
CCBot: 'disallow',
},
},
})The config shape is the same AgentMarkupConfig used by the Vite, Astro, and Next.js adapters. Only the integration point changes: Nuxt reads it from the agentmarkup key.
Where it works best
Run a prerendered build and you get the full output flow written into .output/public:
.output/public/
llms.txt
llms-full.txt
robots.txt
_headers
docs/getting-started/index.html
docs/getting-started.mdBecause the module reads the directory Nitro actually wrote, the artifacts reflect your real final HTML rather than an earlier build step.
The one caveat that matters
Fully dynamic SSR routes are the boundary. If a route is rendered on demand by the Nitro server and never emits a build-time HTML file, there is no final file for the module to patch afterward.
That does not make the package useless for Nuxt apps. It just means you should be precise about ownership:
- Use
@agentmarkup/nuxtfor prerendered routes,nuxt generateoutput, generated root artifacts, and header output - Use the re-exported
@agentmarkup/corehelpers inside app code (for example a server route or Nitro handler) for truly dynamic routes that have no build-time HTML file
Should you enable markdown mirrors?
Only when they add signal. If your prerendered HTML is already substantial, keep HTML as the primary fetch target. If the built page is thin, noisy, or heavily shell-like, generated markdown mirrors can give fetch-based agents a cleaner path.
agentmarkup keeps that feature disciplined by generating mirrors from final HTML, keeping them directly fetchable, and adding canonical headers back to the HTML route so search engines keep the page itself as the preferred URL.
The bottom line
If your Nuxt app prerenders its pages, @agentmarkup/nuxt is the natural module. It gives you build-time machine-readable output on the same config surface as the other adapters, without stitching the pieces together by hand.
Start with the module for the routes Nuxt prerenders, keep markdown mirrors optional, and use @agentmarkup/core directly only where fully dynamic SSR makes that necessary.
If you need the underlying pieces in more detail, read the llms.txt guide, the JSON-LD guide, and the AI crawlers guide.