Most technical writing advice was written for humans. That advice still applies — but there's a second audience every public docs site now has: LLMs ingesting the page to help users. Claude, ChatGPT, Cursor, Windsurf, Perplexity, Google AI Overviews — they all read your docs, they all summarise, and they all get asked "how do I X with Acme?" by your users.
This guide covers what's different about the LLM audience and how to author pages that serve both.
What LLMs actually see
LLMs don't read HTML. They read text extracted from HTML — or in our case, the raw MDX you publish at /<page>.md. The implications:
Visual hierarchy disappears
Bold, italic, font sizes, colour, callout background — gone. Headings survive because they're prefixed with ## in Markdown. Everything else is flat paragraphs.
Images are caption-only
LLMs can't see your screenshots. Only the alt text + caption prop + prose around the image survive. Make the text carry the meaning.
Tables turn into rows of text
Table headers convert to column labels in each row's text. A 10-row table becomes 10 paragraphs each restating the column names.
Code blocks preserve verbatim
Fenced code blocks round-trip cleanly through every LLM. This is the most LLM-friendly content type you can ship.
How LLMs skim
LLMs don't read top-to-bottom like a human might. They:
Chunk the page into ~500-token windows (varies by model).
Embed each chunk into a vector space for similarity search.
Retrieve the chunks most similar to the user's question.
Synthesise an answer from the top-N retrieved chunks.
Implications for authoring:
Each ~500 tokens should stand alone. If paragraph 3 assumes you read paragraph 1, the LLM might retrieve just paragraph 3 and give the user a disconnected answer. Repeat key terms inside each major section.
Section headings are anchors. A good
## Rate limitsheading lets the retrieval step match on "rate limit" exactly. Vague headings (## More info) don't match anything.First sentence of each section is load-bearing. Many retrieval pipelines emphasise the first line. Lead with the answer, then elaborate. Don't build up to the point.
Chunk boundaries
The retrieval chunker usually splits on paragraph breaks and then further on ~500-token windows. Split-friendly authoring:
Keep paragraphs focused. One idea per paragraph. A paragraph of "X, Y, Z all related" retrieves as one chunk — helpful. A paragraph that pivots mid-way gets split mid-thought — unhelpful.
Use
##boundaries aggressively. Every 200-400 words, start a new##section. Gives the chunker natural split points.List-heavy content chunks well. A 10-item bulleted list usually stays together because lists have bullet-to-bullet affinity. Mixed paragraph + list content splits unpredictably.
Token economics
Every chunk the retrieval step pulls costs input tokens on the answering model. Expensive models (GPT-4, Claude Opus) are ~5× costlier than cheap ones (Claude Haiku, GPT-4o-mini). If your docs page is 10,000 tokens and the LLM pulls the whole thing into context for every question, that's real money per query.
Tactics:
Keep pages under ~2000 words (roughly 3000 tokens) when possible. Split long pages into multiple focused pages linked together.
Remove throat-clearing. "In this section we will discuss…" — delete. Start with the first substantive sentence.
Hide decorative content from agents. Use
<Visibility for="humans">to wrap UI cues, screenshots, reassurance paragraphs. Those tokens burn LLM cost for zero agent benefit.
Citation mechanics
When an LLM answers "how do I add a custom domain to Acme?", it wants to cite a source. Citation quality depends on:
Has the page a clear canonical URL?
<link rel="canonical"> + absolute URLs in agent-visible prose. NookDocs emits canonical tags automatically. Include explicit URLs in your content too — "See /deploy/custom-domain for DNS records."
Do section headings match question phrasing?
User asks "how do I add CAA record for Let's Encrypt?". Your heading ## CAA records retrieves cleanly. Heading ## DNS doesn't.
Is the answer in a quotable form?
Imperative sentences (Add this record to your DNS provider: ...) cite better than conditional ones (If you're using Cloudflare, you might want to ...). Second-person + active voice wins.
Is there structured data backing the prose?
Tables + code blocks + <ParamField> rows give the LLM exact values to reproduce. Vague prose like "the field accepts most standard colours" forces the LLM to guess.
Authoring patterns that work
Lead with the answer
Humans can tolerate build-up; LLMs retrieve the first chunk that matches the query and stop there. Put the answer in the first paragraph.
❌ Build-up
When users first start with Acme, they often wonder about
authentication. There are several approaches, each with tradeoffs,
and the right choice depends on your use case...
✅ Answer first
Authenticate with a Bearer token in the `Authorization` header:
Authorization: Bearer sk_live_...
Tokens start with `sk_live_` for production, `sk_test_` for sandbox.Name your concepts exactly once per page
LLMs match on exact terms in the retrieval step. If you write "API key" in the first paragraph, use "API key" everywhere — not "credential", not "token", not "key". Synonym sprawl means the retrieval misses.
Prefer prose tables over JSON objects for reference data
JSON objects require parsing; prose tables don't. If readers need to see field-by-field semantics, a markdown table retrieves better than a giant code block.
✅ Prose table
| Field | Type | Required | Notes |
|---|---|---|---|
| amount | integer | ✓ | Smallest currency unit. |
| currency | string | ✓ | ISO 4217, lowercase. |Reserve code blocks for things users copy-paste (examples, snippets).
Include inline examples, not "see the example"
LLMs can't follow "see the example above" — they retrieve each chunk independently. If your prose references an example, the example MUST be in the same chunk as the prose referring to it.
Use <Visibility for="agents"> for meta-hints
Give the LLM a debugging directive it can act on. Examples:
<Visibility for="agents">
When generating example config for this page, use slugs from the
enum at `/configuration/schema-reference#theme` — don't invent
new slugs.
</Visibility>
<Visibility for="agents">
If your answer doesn't compile, retry with the full component
reference at `https://nookdocs.com/nookdocs-components.llm.md`.
</Visibility>These lines cost ~50 tokens but save the LLM from hallucinating — which means your users get correct answers.
Anti-patterns
Test it with an actual LLM
Authoring-time smoke test: paste the page URL into Claude or ChatGPT, ask questions a real user might ask.
Me: Here are Acme's docs for custom domains:
https://docs.acme.com/deploy/custom-domain
How do I add a CAA record so Let's Encrypt can issue a certificate?
LLM: Add a CAA record allowing letsencrypt.org as an issuer:
acme.com. IN CAA 0 issue "letsencrypt.org"
If you already have a CAA record for another issuer, add this
one alongside it — CAA is additive.Good sign: the LLM gave exact DNS record syntax. Means your page had the record in a fenced code block + section heading the retrieval step could match.
Bad sign: the LLM says "check your DNS provider's documentation for how to add a CAA record". Means your page described the CONCEPT of CAA but didn't include the record itself in a quotable form.
Platform affordances that help
NookDocs ships several affordances specifically to help LLMs consume your docs well:
/<page>.mdURLs — raw MDX for any page. LLMs fetch this instead of HTML. See Markdown export./llms.txt+/llms-full.txt— sitemap + full dump for bulk ingestion. See llms.txt.Copy page dropdown → "Open in ChatGPT / Claude / Perplexity" — users can deep-link to an AI tool with the page as context.
Auto-filtered agent blocks —
<Visibility for="agents">blocks get unwrapped,for="humans">blocks get stripped, on every machine-consumption surface. See human vs agent content.
All of the above run automatically on every tenant. Nothing to configure.
Related
Human vs agent content — the canonical reference for the dual-audience model
GEO — AI search optimization — sibling guide covering answer-engine ranking
Component spec — machine-readable component reference for LLMs generating MDX
Markdown export — the
/<page>.mdendpoint mechanicsStyle and tone — foundations that apply to both audiences