The site-wide files
Three files, three lines each.
import { createGeoffyTextRoute } from "@geoffy/headless/next";export const GET = createGeoffyTextRoute({ siteKey: process.env.GEOFFY_SITE_KEY! }, "llms.txt");import { createGeoffyTextRoute } from "@geoffy/headless/next";export const GET = createGeoffyTextRoute({ siteKey: process.env.GEOFFY_SITE_KEY! }, "llms-full.txt");import { createGeoffyTextRoute } from "@geoffy/headless/next";export const GET = createGeoffyTextRoute({ siteKey: process.env.GEOFFY_SITE_KEY! }, "agents.md");Why route handlers and not a rewrite
Section titled “Why route handlers and not a rewrite”A rewrite in next.config.js works, but it must be in the beforeFiles array.
If your app has a catch-all segment such as app/[lang], a rewrite registered anywhere
else loses to it — and the catch-all answers /llms.txt with your home page and HTTP
200, which a crawler reads as a successful answer rather than a missing file.
Route handlers cannot lose that race. app/llms.txt/route.ts is a static route segment,
and static segments beat dynamic ones with no configuration.
Tuning the cache
Section titled “Tuning the cache”The fetch is cached for revalidateSeconds, one hour by default, under the
helper’s own cache tag:
createGeoffyTextRoute({ siteKey, revalidateSeconds: 300 }, "llms.txt");Mounting the revalidate route purges that tag on publish — see how updates arrive.
If Geoffy is unreachable
Section titled “If Geoffy is unreachable”The route answers 503 with a Retry-After header, never a fabricated 404. A crawler
retries a 503; a 404 tells it to drop the page from its index, which is a much more
expensive mistake to make on your behalf.