AI search readiness · Frameworks
Astro SEO and sitemap: @astrojs/sitemap, robots.txt and llms.txt
Astro prerenders pages to static HTML by default, which is the format AI crawlers read best. The official @astrojs/sitemap integration builds sitemap-index.xml once you set your site URL. robots.txt and llms.txt are not generated, but a static file in public/ or a small endpoint handles both.
- Edit robots.txt
- YesAdd public/robots.txt, or generate it with an endpoint at src/pages/robots.txt.ts.
- XML sitemap
- With a plugin or appOfficial @astrojs/sitemap integration (npx astro add sitemap). Requires the site option; writes sitemap-index.xml and sitemap-0.xml.
/sitemap-index.xml - llms.txt
- YesNo built-in feature. Use public/llms.txt or a static file endpoint at src/pages/llms.txt.ts.
- AI crawlers
- No AI-specific setting in Astro. Pages are prerendered to HTML by default, so crawlers that do not run JavaScript still get the content.
- Structured data
- Astro adds no structured data. Add JSON-LD with a script tag of type application/ld+json and set:html={JSON.stringify(data)}, usually in a layout.
Setting up @astrojs/sitemap
The official sitemap integration installs with one command:
npx astro add sitemap
It needs your production URL. Set site in astro.config.mjs, and per the docs it must start with http:// or https://:
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://www.example.com',
integrations: [sitemap()],
});
On build, the integration writes sitemap-index.xml and sitemap-0.xml; very large sites get extra numbered files. Submit /sitemap-index.xml, not /sitemap.xml, which Astro does not create. Use the filter option to drop pages: it receives each page's full URL, and returning false leaves the page out. That is the place to exclude thank-you pages, drafts and internal tools.
One limit to know: the integration covers dynamic routes generated by getStaticPaths(), but it cannot create entries for dynamic routes rendered on demand in SSR mode. If you serve those, generate a separate sitemap for them with an endpoint and reference both in robots.txt.
robots.txt and llms.txt
The sitemap integration does not write robots.txt. The Astro docs give two options: a static public/robots.txt, or an endpoint at src/pages/robots.txt.ts. A static version looks like this:
User-agent: *
Allow: /
Sitemap: https://www.example.com/sitemap-index.xml
Endpoints are the better fit for llms.txt. Astro's endpoint docs show that a file such as src/pages/builtwith.json.ts exporting a GET function produces /builtwith.json at build time. In the same way, src/pages/llms.txt.ts can read your content collections and return a Markdown Response listing your key pages, so the file updates on every build. Validate it with the llms.txt checker.
If you add AI crawler rules, be precise about which token does what. Blocking GPTBot opts out of OpenAI training; OAI-SearchBot is the one that decides whether ChatGPT search can show you.
JSON-LD in Astro
Astro has no structured data helper, but its set:html directive makes JSON-LD simple. The directives reference shows it on a script tag:
<script type="application/ld+json" set:html={JSON.stringify(schema)} />
Astro treats any script with an attribute other than src as is:inline, so the JSON is written into the HTML as-is rather than bundled. The docs also warn that set:html does not escape its value, so do not pass untrusted user input. Put Organization JSON-LD in your base layout and page-specific types in each page or content collection layout.
Rendering and AI crawlers
Astro's docs state that pages, routes and endpoints are prerendered at build time by default. You opt individual routes into on-demand rendering with export const prerender = false and a server adapter. Either way the HTML is produced on the server, and client-side islands only add interactivity on top. That matters because Vercel's December 2024 analysis found that the major AI crawlers it tested do not render JavaScript. The one thing to avoid is loading core text inside a client-only island (client:only), which leaves it out of the HTML. Check the live site with the robots.txt checker after deploying.
Check your Astro site
Paste your domain to see which AI crawlers your live robots.txt lets in.
robots.txt checker
Test your robots.txt against every AI crawler
robots.txt generator
# robots.txt generated with https://www.getpicked.app/tools/robots-txt-checker
# Preset: Allow AI search, block training
User-agent: *
Allow: /
# Model training crawlers
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: Google-Extended
User-agent: Applebot-Extended
User-agent: Meta-ExternalAgent
User-agent: Amazonbot
User-agent: CCBot
User-agent: Bytespider
Disallow: /
Questions
- Where is the Astro sitemap?
- @astrojs/sitemap writes sitemap-index.xml and sitemap-0.xml to the build output. Submit /sitemap-index.xml to search engines; it links to the numbered files, and large sites get more of them.
- Why is my Astro sitemap empty or missing pages?
- Check that site is set in astro.config.mjs with a full http:// or https:// URL; the integration requires it. Also note that it cannot list dynamic routes rendered on demand in SSR mode, only routes generated by getStaticPaths().
- Does @astrojs/sitemap create robots.txt?
- No. The docs show adding a Sitemap line to your own robots.txt, either as a static file in public/ or generated by an endpoint in src/pages/robots.txt.ts.
- Is Astro good for AI search?
- Its defaults help. Astro prerenders pages to static HTML at build time unless you opt a route into on-demand rendering, so AI crawlers that skip JavaScript still see the full text.
Other frameworks
Related
Sources
Checked against these pages on 2026-10-19. Operators change their crawlers; check the source before relying on a detail.