Skip to content
KismetKismetDevelopers
Beta accessllms.txt

Markdown pages

View .md

Every page a Kismet site declares has a Markdown twin at the same URL plus .md — the version an AI agent reads instead of rendering HTML. /llms.txt links the twins, so a broken twin or a twin that links a page the site does not serve is a dead end for every agent that followed the index. This guide says which pages have twins, how the SDK builds them, how a site serves them, and how to check the links inside them.

The SDK’s page-type registry is the only list of page types, and every type in it carries a Markdown composition. The twin is per declared page: a page exists for an agent when the site declares it with definePage and serves it.

Page type HTML route Markdown twin
Homepage / /index.md
Results (collection) /properties/ /properties/index.md
Property /properties/{slug} /properties/{slug}.md
Property group /groups/{slug} /groups/{slug}.md
Group index /groups/ /groups/index.md
Reviews /properties/{slug}/reviews /properties/{slug}/reviews.md
Rates /properties/{slug}/rates /properties/{slug}/rates.md
Blog index /blog/ /blog/index.md
Blog post /blog/{slug} /blog/{slug}.md
FAQ, About, Contact, Owners /faq, /about, /contact, /owners same route + .md
Booking confirmation /booking-confirmation /booking-confirmation.md
Custom the site declares it the declared URL + .md

A page marked private never serves a twin — the twin endpoint returns 404, the same boundary the HTML page enforces elsewhere. Unlisted-but-public pages keep twins; only /llms.txt decides what is advertised.

markdownForPage(page) renders the twin body, in this order:

  1. Your renderMarkdown override, if definePage got one — it wins.
  2. The page type’s composition — the property twin carries the details, the long description, highlights and selling points, amenities, neighborhood and location, the pricing summary, the photos, and a Book section linking the property page and the rates twin; the group twin lists its members.
  3. The fallback: title, Canonical: line, description.

Every twin starts with a Canonical: line naming the HTML page it mirrors, and the HTML page carries <link rel="alternate" type="text/markdown"> pointing back at the twin.

The SDK builds the Markdown string; the site decides which URL serves it. Two supported shapes:

Next.js — rewrite .md to one twin route. Rewrite every declared page’s .md URL to a single route that calls the page adapter’s markdown handler, which resolves the page for the request URL and returns markdownForPage:

next.config.ts
const nextConfig: NextConfig = {
async rewrites() {
return [
{ source: "/properties/:slug", destination: "/property-page" },
{ source: "/properties/:slug.md", destination: "/markdown-twin" },
{ source: "/groups/:slug.md", destination: "/markdown-twin" },
];
},
};

The markdown handler is exact-host and same-origin: a twin URL that names no declared page returns 404, so a twin exists only where the HTML page does.

Static export — write the twins as files. After the build, write each twin next to its HTML (the homepage twin at /index.md). The checker probes <route>.md then <route>/index.md, and / twins at /index.md.

Either shape, the site also serves:

  • /llms.txt from Kismet.llmsTxt — it links every public twin. Pass { markdownTwins: false } only if the site serves no twins at all; then the site/markdown-twin rule does not require them.
  • Accept: text/markdown negotiation on the HTML routes, so an agent that asks for Markdown instead of HTML gets the twin body without the .md URL.

A twin links the pages its guest actions need, and every link must resolve on that site:

  • The Canonical: line points at the twin’s own HTML page.
  • A property twin links the rates twin (…/rates.md) and the property page.
  • Group and index twins link their members.
  • /llms.txt links every public twin.

The rule is absolute: a twin may only link URLs the site actually serves. The SDK builds links from the page type’s template; if the site does not serve that page, the link is broken for agents. That exact failure shipped on a live site — property twins linked /properties/<slug>/rates.md while the site rewrote only property and group twins, so every rates link returned 404 (KIS-21888). Serve the linked page, or remove the link, and re-run the link check before go-live.

  1. Twin exists and is Markdown. curl any declared page’s .md URL and expect 200 with a Canonical: line:

    Terminal window
    curl -fsSL https://example.com/properties/<slug>.md | head -5
  2. Every declared page has a twin. Run the conformance check in production mode — the site/markdown-twin rule fails for each declared page-type route without a reachable twin:

    Terminal window
    npx kismet check https://example.com --env production --json
  3. Every link inside every twin returns 200 on the live domain — the curl loop is go-live checklist N7. The checker’s site/internal-links rule grades twin links it can read from a built directory; twins served through a rewrite need the live curl check, because no static file holds their body.