---
title: "How to make a website that AI assistants can read and cite"
description: "Publish every page twice, as HTML for people and as Markdown for machines, and generate both from one source so they cannot disagree. Add an llms.txt index, an Atom feed, Article structured data that points to the Markdown, and a robots.txt that names the AI crawlers. Then check each file by what the server actually sends, not by whether it answers."
date: 2026-10-11
lang: en
canonical: https://goingstellar.ro/methods/how-to-make-a-website-ai-assistants-can-read-and-cite/
author: Going Stellar
publisher: GOING STELLAR S.R.L.
topic: AI / Machine-readable sites
license: CC BY 4.0
alternate_ro: https://goingstellar.ro/ro/metode/cum-faci-un-site-pe-care-asistentii-ai-il-pot-citi-si-cita/
---

# How to make a website that AI assistants can read and cite

*Publish every page twice, as HTML for people and as Markdown for machines, and generate both from one source so they cannot disagree. Add an llms.txt index, an Atom feed, Article structured data that points to the Markdown, and a robots.txt that names the AI crawlers. Then check each file by what the server actually sends, not by whether it answers.*

> AI · Machine-readable sites · 2026-10-11 · https://goingstellar.ro/methods/how-to-make-a-website-ai-assistants-can-read-and-cite/

## Key points

- A website is citable by AI assistants when each page can be fetched as plain text with a stable address, title, date, author and licence.
- A plain-text mirror is only useful if it is generated from the same source as the page; a hand-maintained mirror drifts and gets quoted anyway.
- llms.txt is a cheap index, not a citation lever: Google's AI optimisation guide lists it among things a site does not need.
- Check machine-readable files by the content-type header the server sends, because a broken file can still answer 200 OK.
- Run the final check on the generated files, not on the source you just edited, or a corrected claim can survive in a meta description.

## What makes a website readable and citable by AI assistants?

A website is readable by AI assistants when its text can be fetched without running JavaScript, without guessing what is layout and what is content, and without guessing which number belongs to which claim. It is citable when each page has a stable address, a title, a date, an author and a licence that an assistant can repeat. The method below is the one behind goingstellar.ro: a plain-text twin for every article, indexes that list everything in one request, and a build that writes all of it from the same data.

By *AI assistants* we mean ChatGPT, Claude, Perplexity, Gemini and the AI answers in search engines. They reach a page either through their own crawlers or through a search index. Neither route rewards a page that hides its text behind scripts or scatters its facts.

## Generate every output from one source

**1. One source of truth.** All text and all figures live in one content file, in both languages. A build script writes the HTML pages, the Markdown twins, the indexes, the feed, the sitemap and robots.txt from that file. Nothing is edited by hand after the build.

We started this way because the previous version of the site was two hand-written HTML files of about 700 lines each, one per language, and they had already drifted apart: the number of apps listed for one marketplace was different in English and in Romanian. A mirror that can fall behind the page is worse than no mirror, because an assistant will quote the stale one with confidence. A generated mirror cannot fall behind.

The build also stops itself. Counts that appear in headings are tied by assertions to the length of the lists they describe, so a mismatch breaks the build instead of reaching a visitor.

## Give every page a Markdown twin

**2. A Markdown twin per article.** Every article is also written as a `.md` file at the same address with `.md` appended. The Markdown twin carries front matter (title, description, date, language, canonical address, licence, the address of the other language), the full text with its headings, a ready-made citation, a BibTeX entry and a CC BY 4.0 licence line. The citation block is there so that nobody, human or model, has to invent the format.

**3. Announce the twin.** The HTML page links to its Markdown twin with `&lt;link rel="alternate" type="text/markdown"&gt;` and shows a visible link to it. The conversion from HTML to Markdown is complete rather than approximate, because the source paragraphs may only contain bold, italic and code markup.

The reason for the twin is practical. An assistant that receives HTML has to strip the layout first, and the stripping loses exactly what matters: which line is a heading, which figure belongs to which claim, where the limitations are. The Markdown twin is the article without the layout.

## Publish llms.txt and llms-full.txt, without overselling them

**4. Two plain-text indexes at the root.** `llms.txt` is a short Markdown index: who we are, what we publish, every page with a one-line description, every article with the address of its Markdown twin. `llms-full.txt` holds everything: each application with its description, each published figure with the system it came from, and the full text of the methods and research. Both are regenerated on every build from the same data as the pages.

We do not claim llms.txt makes a site more likely to be cited. The search guidance we work from records that Google's own AI optimisation guide lists llms.txt among the things a site does not need, and that no major AI search provider has confirmed reading third-party llms.txt files. Coding assistants do read such files when loading documentation. For us the file costs nothing to generate and gives any reader a complete map in one request; that is the whole claim.

## Feed, structured data and robots.txt

**5. An Atom feed.** Each language has an Atom feed for the research articles and another for the methods, newest first. Every entry links both the HTML page and its Markdown twin, so a reader that follows the feed never has to parse the page.

**6. Article structured data.** Each article carries JSON-LD of type `Article` with headline, description, language, publication date, author, publisher, licence, word count and canonical address. It also carries an `encoding` object of type `MediaObject`, with `encodingFormat` set to `text/markdown` and `contentUrl` pointing to the twin. That tells any parser of structured data that a clean text version exists and where.

**7. A robots.txt that names the AI crawlers.** The general rule already allows every crawler. We still name 22 AI and search crawlers one by one, each with `Allow: /`, and point to the sitemap, which lists every page with its other-language pair. Naming them makes the permission a statement rather than an omission.

## Serve the files correctly, and check what the server sends

**8. Teach the web server what Markdown is.** Our nginx did not know the `.md` extension, so it served the twins as `application/octet-stream` and browsers downloaded them instead of showing them. One location block for `.md` fixes it: `text/markdown` as the type, UTF-8, and open cross-origin access.

**9. Verify by content type, not by status.** A `200 OK` proved nothing here: the broken files also answered 200. The check that counts reads the response header, for example `curl -sI` on a Markdown address and a look at `content-type`. We now check the Markdown twin, llms.txt, the feed and robots.txt by header after every deploy.

## Write pages that can be quoted one paragraph at a time

**10. Structure.** Each article has one `h1`, one `h2` per section, the date in a `&lt;time&gt;` element, and its limitations in a section of their own rather than in a footnote. The first paragraph answers the title directly. Each section names its subject again instead of saying *it*, so that a paragraph quoted alone still makes sense. Newer articles end with short takeaways and a few questions answered in full.

**11. A numeric gate before publishing.** A text that is meant to be quoted must not contain a figure we cannot source. Every number in an article has to appear in a facts list next to the file it came from, and a script with no model in it rejects any digit outside that list. In the first round of articles, checking found 25 invented quantities, and we applied 117 corrections. Agents also look for quantities written in words, which the digit check cannot see.

The last gate reads the generated files, not the source. An earlier wrong claim about the number of countries we ship to (eight instead of seven) had been fixed on the page and survived in a meta description. A check that looked only at the text just edited would have missed it.

## Where we were wrong, and what the method does not prove

We assumed the nginx change also declared the character set. The header check showed the Markdown files served as `text/markdown` with no charset parameter, and llms.txt as `text/plain` with none either. The registration for `text/markdown` makes the charset parameter required, and a client that assumes another encoding will garble Romanian diacritics. The fix was to add the Markdown type, and the plain-text and feed types, to the server's list of types that receive a charset; we applied it the same day and checked the header again. We had verified the type and not the whole header.

The methods section has its own feed and its own Markdown index, built from the same data as the pages.

The main limit is measurement. We have not yet measured how many visits, if any, reach the site from AI assistants, and we have no evidence that any assistant has cited these pages. The method makes the site easy to read and easy to quote correctly. It does not make anyone ask about it, and it does not replace being indexed by search engines, which is how most AI answers find a page in the first place.

## Checklist

One content file; everything else generated. A Markdown twin per article, linked as an alternate and in the article's JSON-LD `encoding`. llms.txt and llms-full.txt from the same data, described honestly. An Atom feed with Markdown links. robots.txt naming the AI crawlers, and a sitemap with language pairs. The server sends `text/markdown` with a charset, checked by header. One `h1`, sections that stand alone, limitations in their own section. Every number in a facts list, checked by a script on the generated output.

## Questions and answers

### What is a Markdown twin of a web page?

A Markdown twin is a plain-text copy of a page at a predictable address, for example the page address with .md appended. It carries the same title, headings and figures without layout, plus front matter, a citation and a licence. The HTML page announces it with a link element of type text/markdown, so crawlers and assistants can fetch clean text instead of stripping HTML themselves.

### Does llms.txt help a website get cited by ChatGPT or Google AI Overviews?

There is no evidence that it does. Google's AI optimisation guide lists llms.txt among things a site does not need, and no major AI search provider has confirmed reading third-party llms.txt files. Coding assistants do use such files for documentation. Publish llms.txt as a free, complete index of the site, generated from the same data as the pages, but do not present it as a ranking or citation factor.

### Should robots.txt list AI crawlers by name if everything is already allowed?

Naming them is optional when the general rule allows all crawlers, but it turns permission into an explicit statement and makes later changes deliberate. On goingstellar.ro the robots.txt names 22 AI and search crawlers, each with Allow, and points to a sitemap that pairs every page with its other-language version.

### How do I check that my server serves Markdown files correctly?

Request the headers of a Markdown address, for example with curl -sI, and read the content-type line. It should say text/markdown with a UTF-8 charset. Do not rely on the status code: a server that does not know the .md extension still answers 200 and sends the file as a download, and a missing charset can garble non-English characters.

### What structured data helps AI assistants cite an article?

Article JSON-LD with headline, description, language, publication date, author, publisher, licence and canonical address gives an assistant what it needs to attribute a quote. Adding an encoding object of type MediaObject, with encodingFormat text/markdown and a contentUrl, points parsers to the clean text version of the same article.

## How to cite

**Cite this as:** Going Stellar (2026). *How to make a website that AI assistants can read and cite*. GOING STELLAR S.R.L.. https://goingstellar.ro/methods/how-to-make-a-website-ai-assistants-can-read-and-cite/

```bibtex
@misc{goingstellar2026how,
  title  = {How to make a website that AI assistants can read and cite},
  author = {{Going Stellar}},
  year   = {2026},
  url    = {https://goingstellar.ro/methods/how-to-make-a-website-ai-assistants-can-read-and-cite/},
  note   = {2026-10-11}
}
```

Licence. Free to quote with attribution.

## Also available

- This page as HTML: https://goingstellar.ro/methods/how-to-make-a-website-ai-assistants-can-read-and-cite/
- Same article in Romanian: https://goingstellar.ro/ro/metode/cum-faci-un-site-pe-care-asistentii-ai-il-pot-citi-si-cita/
