Project archive

Publishing the files on your platform

These notes document publishing the original file suite. When maintaining an existing setup, check the response body, status and content type against the format and the intended consumer's requirements.

Check what you are actually serving

The original specification required llms.txt to be served as text/plain; charset=utf-8, reachable without authentication, returning 200 over HTTPS. This GET request shows the headers and body so you can inspect what the URL actually serves:

verify
curl -sS -D - https://example.com/llms.txt

A 200 status alone does not tell you whether the body contains the expected file. Check for an HTML error page, login screen or other unexpected content, and follow redirects to inspect the destination. A different content type can affect how a consumer handles the response; it does not make the bytes universally unreadable.

Lighthouse checks this too

Chrome DevTools' Lighthouse includes an llms.txt audit under its Agentic browsing category, so you can verify from the browser as well as the command line. Note how it grades: a 404 is reported as Not Applicable, because publishing the file is optional at present — but a server error when fetching it is flagged. A passing audit therefore means the file was retrievable, not that its contents are right.

The soft-404 trap

A server can return a “page not found” HTML page with a 200 status. That status reports a successful request even though the expected file is missing. Check both the status and body; neither alone establishes that a file is valid for its intended consumer.

Archived platform examples

The original suite used root-level URLs such as https://example.com/llms.txt. These examples document that setup; check your host's current configuration before reusing them. The current llms.txt proposal also supports files under a relevant path, such as /docs/llms.txt.

Cloudflare Pages

Archived · Static host

Put the files in your output directory (or in public/ if your framework copies it through).

llm.txt redirect

text
# _redirects
/llm.txt   /llms.txt   301

Content-Type

text
# _headers
/*.txt
  Content-Type: text/plain; charset=utf-8

/*.json
  Content-Type: application/json; charset=utf-8

Netlify

Archived · Static host

Anything in publish/ (or public/ pre-build) is served from the site root.

llm.txt redirect

text
# _redirects
/llm.txt   /llms.txt   301!

Content-Type

text
# _headers
/llms.txt
  Content-Type: text/plain; charset=utf-8

/ai.json
  Content-Type: application/json; charset=utf-8

The trailing ! forces the redirect even when a file exists at the source path — useful if you previously published a literal llm.txt and want to retire it cleanly.

Vercel

Archived · Static host

public/ at the project root.

llm.txt redirect

json
// vercel.json
{
  "redirects": [
    { "source": "/llm.txt", "destination": "/llms.txt", "permanent": true }
  ]
}

Content-Type

json
// vercel.json
{
  "headers": [
    {
      "source": "/(.*).txt",
      "headers": [
        { "key": "Content-Type", "value": "text/plain; charset=utf-8" }
      ]
    }
  ]
}

nginx

Archived · Web server

Your document root, alongside robots.txt.

llm.txt redirect

nginx
location = /llm.txt {
    return 301 /llms.txt;
}

Content-Type

nginx
location ~ \.txt$ {
    default_type text/plain;
    charset utf-8;
}

location ~ \.json$ {
    default_type application/json;
    charset utf-8;
}

Apache

Archived · Web server

Your document root, alongside robots.txt.

llm.txt redirect

apache
# .htaccess
Redirect 301 /llm.txt /llms.txt

Content-Type

apache
# .htaccess
AddType "text/plain; charset=utf-8" .txt
AddType "application/json; charset=utf-8" .json

Astro

Archived · Framework

public/ — files there are copied to the site root verbatim and are never processed by the build.

llm.txt redirect

js
// astro.config.mjs
export default defineConfig({
  redirects: {
    '/llm.txt': { status: 301, destination: '/llms.txt' },
  },
});

For a static build the redirect is emitted only if your adapter supports it. On Cloudflare Pages or Netlify, use that host’s _redirects file instead — it is more reliable.

Next.js

Archived · Framework

public/ at the project root. Do not create app/llms.txt/route.ts unless you need the content to be dynamic.

llm.txt redirect

js
// next.config.js
module.exports = {
  async redirects() {
    return [
      { source: '/llm.txt', destination: '/llms.txt', permanent: true },
    ];
  },
};

Content-Type

js
// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:file*.txt',
        headers: [
          { key: 'Content-Type', value: 'text/plain; charset=utf-8' },
        ],
      },
    ];
  },
};

Shopify

Archived · Hosted platform

The earlier setup assumed root-level files, which can require platform-specific routing on a hosted store.

For optional llms.txt work, check current Shopify capabilities and the intended tool’s URL requirements. The upstream proposal also supports subpaths. A link in robots.txt does not establish that a tool will find a file on another host.

WordPress

Archived · Hosted platform

Upload to the web root via SFTP or your host’s file manager.

llm.txt redirect

apache
# .htaccess, above the WordPress rewrite block
Redirect 301 /llm.txt /llms.txt

Upload the files to the web root over SFTP, or use any plugin that lets you serve arbitrary static files from the root. Avoid plugins that render the files as WordPress pages — a consumer fetching /llms.txt needs the raw file, not a themed page.

When your host cannot redirect at all

The original specification called for /llm.txt to redirect to /llms.txt, with a byte-identical copy as a fallback. That was a rule of the proposal, not an established AI discovery requirement. The preserved llm.txt template is an explanatory pointer and does not implement that rule.

If an existing implementation keeps an identical copy, this check detects differences between the two local files:

ci
cmp -s public/llms.txt public/llm.txt || { echo "llm.txt has drifted from llms.txt"; exit 1; }

These are archived configuration examples. For an existing deployment, curl -I inspects response headers using a HEAD request; a GET request lets you inspect the body too. Check the published content and the intended tool's behavior separately. A successful response does not establish indexing or use in an AI answer.

Something here out of date or wrong for your host? Email info@discoveryfiles.ai.