GeoPromptTracker

How to add llms.txt to Next.js (static file or dynamic route)

Published August 17, 2026

Next.js is the easiest platform there is for llms.txt: drop a plain-text file in public/ and it's live at /llms.txt, or write a ~30-line route handler that generates the file from your actual content so it never goes stale. Here's both, with complete code — including the pattern this site uses for its own file.

Method 1: Static file in public/ (2 minutes)

Create the file with the llms.txt Generator (or by hand — it's just Markdown), save it as public/llms.txt, deploy. Next.js serves everything in public/ at the site root with correct content types:

your-app/
├── public/
│   └── llms.txt   ← served at yoursite.com/llms.txt
├── app/
└── ...

That's genuinely the whole method, and it's the right choice when your key pages are stable — a marketing site, a SaaS with a fixed set of core pages. The only cost is remembering to update the file when those pages change.

Method 2: Generate it with a route handler (stays in sync)

If your llms.txt should reflect living content — your latest guides, docs sections, product pages pulled from a CMS — generate it. In the App Router, create app/llms.txt/route.ts:

import { getAllPosts } from "@/lib/content"; // your content source

export const dynamic = "force-static"; // render at build time

export function GET() {
  const posts = getAllPosts();

  const lines = [
    "# Your Site",
    "",
    "> One line describing what your site is about.",
    "",
    "## Key pages",
    "- [Product](https://yoursite.com/product): What it does",
    "- [Pricing](https://yoursite.com/pricing): Plans and costs",
    "",
    "## Latest articles",
    ...posts
      .slice(0, 15)
      .map((p) => `- [${p.title}](https://yoursite.com/blog/${p.slug}): ${p.description}`),
  ];

  return new Response(lines.join("\n"), {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Key details:

  • force-static renders the file once at build time — it's a static asset in production, zero runtime cost, and it updates on every deploy.
  • Set the content type to text/plain explicitly; without it some setups negotiate something else.
  • Keep curation in the code. slice(0, 15) above matters — dumping every URL recreates a sitemap, and curation is the point. If you also want a full-content companion file, that's llms-full.txta different job.

A hybrid also works well: hand-write the curated sections, generate only the "latest articles" list. (That's roughly the pattern this site uses — static curated file, refreshed as part of the content workflow.)

Pages Router note

public/llms.txt works identically. For a generated file on the Pages Router, an API route can't sit at the root path directly, so add a rewrite in next.config.js:

async rewrites() {
  return [{ source: "/llms.txt", destination: "/api/llms-txt" }];
}

…and return text/plain from pages/api/llms-txt.ts. Honestly though: if you're choosing, the static file is less machinery for the same result.

Verify

  1. curl -s https://yoursite.com/llms.txt | head — plain Markdown, 200, no HTML.
  2. Run the URL through the llms.txt Validator — it checks H1/summary/link structure against the spec.
  3. Since you're in a Next.js codebase anyway: confirm your content is server-rendered where it matters — AI crawlers don't run JavaScript, and llms.txt pointing at client-rendered pages is a map to rooms crawlers can't enter. The AI-Readiness Audit checks both in one pass.

Bottom line

public/llms.txt for stable sites, a force-static route handler when the file should track your content. Either way it's minutes of work in Next.js — generate the content, ship it, validate it, and move on to the part that actually earns citations: the pages the file points to.

Frequently asked questions

How do I add llms.txt to a Next.js site?

Simplest: put a plain llms.txt file in the public/ directory — Next.js serves it at /llms.txt automatically. For a file that stays in sync with your content, create an app/llms.txt/route.ts route handler that generates the Markdown at build time.

Should llms.txt be static or generated in Next.js?

Static (public/llms.txt) if your key pages rarely change — it's zero code. Generate it via a route handler if the file should track your content (e.g., list your latest posts) so it can never drift out of date.

Does the llms.txt route need special headers?

Serve it as text/plain. A public/ file gets that automatically; in a route handler, set the content-type header on the Response. Add export const dynamic = 'force-static' so it's rendered at build time.

Does this work with the Pages Router?

Yes — public/llms.txt works identically in both routers. For a generated file on the Pages Router, use an API route (pages/api/llms.txt won't sit at the root path, so prefer a rewrite from /llms.txt to the API route, or just use the static file).

Related