Markdown rendering
The markdown route serves your page’s source verbatim by default. On a Markdown site that is exactly right. On an MDX site it means the thing an AI agent fetches is full of import statements and component tags rather than prose.
renderMarkdown
decides which of those the route serves.
What the modes produce
Section titled “What the modes produce”This page in your editor:
<Tabs syncKey="pkg"> <TabItem label="npm"> ```sh npm install starlight-llm-actions ``` </TabItem> <TabItem label="pnpm"> ```sh pnpm add starlight-llm-actions ``` </TabItem></Tabs>Under the default 'raw', that is byte-for-byte what the .md route returns —
component tags included. An agent has to guess what <Tabs> means.
Under 'simple', the same block arrives as ordinary Markdown:
* npm
```sh npm install starlight-llm-actions ```
* pnpm
```sh pnpm add starlight-llm-actions ```Nothing is left for the reader to interpret. Starlight’s <Tabs>,
<FileTree>, <Steps>, and Expressive Code blocks all flatten this way.
Choosing a mode
Section titled “Choosing a mode”| Mode | Use it when |
|---|---|
'raw' |
Your pages are plain Markdown, or you want the source — someone copying a page to file a docs PR needs the original, not a rendering of it. |
'simple' |
Your pages use MDX components and the audience is AI agents or readers, not editors. |
{ module } |
You need output neither mode produces — stripping sections, injecting frontmatter, rewriting links for an external index. |
If you are unsure, 'raw' is the safer default: it has no dependencies and
cannot fail.
Enabling 'simple'
Section titled “Enabling 'simple'”The flattening pipeline is heavy, so the plugin does not bundle it:
npm install @astrojs/mdx unified rehype-parse rehype-remark remark-gfm remark-stringify hast-util-select unist-util-removeThen set the mode:
starlightLlmActions({ renderMarkdown: 'simple',})Miss a dependency and the build stops at config time and prints the exact install command — it will not fail halfway through rendering your pages.
What can go wrong
Section titled “What can go wrong”Framework components throw. 'simple' renders through an Astro container
that registers the MDX renderer only, so a page using a React, Vue, Svelte, or
Solid component cannot render. The plugin catches that per page, warns with the
page name, and serves that page’s raw source instead. One such page will not
fail your build or affect any other page.
Chrome leaks into the output. Unknown custom elements are unwrapped and their text kept. When an element renders pure chrome you do not want in the Markdown, mark it and the whole subtree is dropped:
<div data-mdast="ignore">…</div>Turning off the route makes the mode moot. With
injectRoute: false
there is no route to render, so the setting changes nothing — though 'simple'
still expects its dependencies whenever it is set.
Advertising the Markdown
Section titled “Advertising the Markdown”Rendering good Markdown only helps if something can find it.
linkAlternate
adds a discovery tag to every page:
starlightLlmActions({ linkAlternate: true,})Each page then carries a tag pointing at its own Markdown:
<link rel="alternate" type="text/markdown" href="/guides/example.md" />Crawlers and agents can follow it without knowing your URL convention. Drafts and the 404 page are skipped, because the route produces no Markdown for them.
Verify it on this site
Section titled “Verify it on this site”These docs run renderMarkdown: 'simple' and linkAlternate: true, so you can
check both without installing anything. Open
the Markdown for the install page
and compare it against the <Tabs> source above — that is the flattening,
running live. View the source of any page here and you will find its
alternate tag in the <head>.