Why this matters
An assistant answering a question has a fixed amount it can read before it stops. Every kilobyte of navigation markup is a kilobyte it does not spend on your argument, your data, or your product. Serving a twin does three things:- Your content is read in full, rather than truncated halfway through the page
- Quotes come out clean, because there is no markup to strip and misread
- Nothing is guessed, since headings, lists and tables arrive already structured
Setting it up on WordPress
The SnowSEO plugin publishes twins for every public post and page. There is nothing to write.1
Install and connect the plugin
Install SnowSEO from the WordPress plugin directory and connect it to your brand under SnowSEO → Settings.Already publishing to this site from SnowSEO? Then this is done.
2
Switch twins on
Go to Settings → Reading in the WordPress admin and tick “Publish a markdown copy of every public post and page”, then save.
This is off until you turn it on. Enabling it publishes new addresses on your site, so the plugin does not do it for you.
3
Check it worked
Open any published post and add You should see plain text, starting with a short block of title and date information, then the article. If you get your normal page or a 404, see Troubleshooting below.
.md to the end of its address:What gets a twin
Every post and page that is:- Published, and not password protected
- Publicly viewable
- Not marked noindex by Yoast, Rank Math, SEOPress, The SEO Framework or All in One SEO
Setting it up on other platforms
For Next.js, Astro, Nuxt, SvelteKit, Express, Cloudflare Workers or a custom stack, the SnowSEO SDK does the same job.1
Install
2
Point it at your content
If your pages come from Markdown files already, point at the folder:If they don’t - a React or Vue app, a CMS, anything rendered rather than stored as Markdown - convert the rendered page instead:
beacon.ts
beacon.ts
No account or key is needed for Markdown twins.
siteUrl is used to build the links between a page and its twin, so it must match the address your site is actually served on.3
Wire it into your routing
proxy.ts
beaconMiddleware serves the twin when one is asked for. beaconAdvertise adds the header that tells an assistant the twin exists.4
Decide which paths get twins
Twins make sense for public pages and not for your app. Skip anything behind auth - a twin of a signed-out dashboard shell tells an assistant nothing and advertises a URL that never has content.If your site has a staging password or similar gate, run that gate first: a twin serves the same content as the page, so handling it earlier would let anyone read protected content by adding
.md.How assistants find your twins
Three routes, so an assistant does not have to know your URL convention in advance.
You also get
/llms.txt, a single index of every twin on the site, on both WordPress and the SDK. That is the emerging convention for telling AI tools which pages matter, and it is pointed to from your robots.txt so it can be found without guessing.
Twins and Google
Markdown twins are deliberately kept out of search results. Each twin is served withX-Robots-Tag: noindex, follow. Without it, a search engine could index the raw Markdown file and show it in results, and a visitor clicking through would land on a page of unstyled text instead of your real page.
For the same reason, twins are not listed in the sitemap your site submits to search engines. Submitting pages you have marked noindex produces “Submitted URL marked noindex” errors in Google Search Console, once per page.
The SDK behaves the same way, so twins are held out of search whichever platform you are on.If you would rather have them indexed, set
X-Robots-Tag yourself and pair it with a Link: rel="canonical" back to the HTML page, so the two do not compete. Send one or the other, never both: a canonical asks for the twin to be consolidated onto your page, while noindex asks for it to be dropped, and the two directives contradict.Checking your setup
Run a GEO Audit on your site and open the Machine Readable section. SnowSEO checks the twin end to end:
You can also check by hand from a terminal:
200 with Content-Type: text/markdown; charset=utf-8.
Troubleshooting
The .md address returns a 404
The .md address returns a 404
Twins are off, or that particular page is not eligible.Check Settings → Reading first. If twins are on, confirm the post is published rather than a draft, is not password protected, and has not been marked noindex by your SEO plugin. A page marked noindex never gets a twin.
The .md address returns my normal page
The .md address returns my normal page
Something in front of WordPress is serving a cached HTML copy.Most page caches store one response per address and do not know that
Accept: text/markdown should produce a different one. SnowSEO marks Markdown responses as uncacheable, but a CDN configured to ignore those instructions can still override it. Clear the cache and try again; if it persists, exclude .md addresses from your cache rules.Changes to a post are not showing in its twin
Changes to a post are not showing in its twin
Twins are generated from the current content of the post, so a stale twin is almost always a cache.Clear your page cache, then request the
.md address again. If your CDN caches aggressively, purge that address specifically.I want to exclude one page
I want to exclude one page
Mark it noindex in your SEO plugin. SnowSEO skips it, and the page stays out of both search results and Markdown twins.

