A correct sitemap is the cheapest SEO improvement you can ship. A wrong one quietly leaks pages or pollutes Google with broken URLs.
Background
Astro’s official @astrojs/sitemap integration covers 90% of cases out of the box. The remaining 10% — exclusions, alternate language pairs, last-modified dates — is where most sites get it wrong. Getting these right at setup time saves rounds of indexing problems later.
How to tell
- Your site has more than 30 URLs you want indexed.
- You have multiple languages or regional variants.
- You ship draft, hidden, or auth-only pages that must stay out of search.
- You want to give Google fresh
lastmodsignals when content changes.
Quick verdict
Use @astrojs/sitemap as the foundation. Customize via the filter and serialize options to handle exclusions and hreflang.
Step by step
- Install the official integration:
npx astro add sitemap
- Configure
astro.config.mjs—site:must be set or the integration silently produces a useless file. For a bilingual content site, this is the shape that works:
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://yourdomain.com',
trailingSlash: 'always',
build: { format: 'directory' },
integrations: [
sitemap({
i18n: {
defaultLocale: 'en',
locales: { en: 'en', zh: 'zh-CN' },
},
filter: (page) =>
!page.includes('/drafts/')
&& !page.includes('/preview/')
&& !page.includes('/admin/')
&& !page.endsWith('/404/'),
serialize: (item) => {
// Tag homepage as daily, articles as weekly, everything else monthly
if (item.url.match(/\/articles\/[^/]+\/$/)) item.changefreq = 'weekly';
else if (item.url === 'https://yourdomain.com/') item.changefreq = 'daily';
else item.changefreq = 'monthly';
return item;
},
}),
],
});
- Run the build and confirm the sitemap files exist:
npm run build
ls -la dist/sitemap*.xml
# dist/sitemap-index.xml
# dist/sitemap-0.xml
head -20 dist/sitemap-0.xml
- The generated XML should look like this — each URL pair carries
xhtml:linkalternates for hreflang:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://yourdomain.com/en/articles/astro-sitemap-setup/</loc>
<xhtml:link rel="alternate" hreflang="en"
href="https://yourdomain.com/en/articles/astro-sitemap-setup/" />
<xhtml:link rel="alternate" hreflang="zh-CN"
href="https://yourdomain.com/zh/articles/astro-sitemap-setup/" />
<changefreq>weekly</changefreq>
</url>
</urlset>
- Add a
public/robots.txtthat points to the sitemap so crawlers find it without manual steps:
User-agent: *
Allow: /
Disallow: /drafts/
Disallow: /preview/
Disallow: /admin/
Sitemap: https://yourdomain.com/sitemap-index.xml
- After deploy, fetch the sitemap and count URLs — quick sanity check against your article count:
curl -s https://yourdomain.com/sitemap-index.xml | grep -c '<loc>'
curl -s https://yourdomain.com/sitemap-0.xml | grep -c '<loc>'
# should roughly equal (en articles + zh articles + hub pages)
- Submit
sitemap-index.xmlonce in Search Console → Sitemaps. After that, you never resubmit unless the URL changes — Google polls it on its own.
Common pitfalls
- Forgetting to set
site:in config — Astro silently produces a useless sitemap. - Listing pages that return 404 or redirect — every wrong URL chips at your crawl budget.
- Including draft or test URLs and watching them get indexed before you notice.
- Setting
lastmodto the build date for every page — Google ignores it as noise. - Submitting one sitemap per language separately when a sitemap index with hreflang would be cleaner.
Who this is for
Any Astro site that depends on organic search.
When to skip this
Private internal tools or single-page sites where a sitemap adds noise without benefit.
FAQ
- Does Astro generate a sitemap automatically?: Only if you add the
@astrojs/sitemapintegration. Stock Astro does not. - How big can a sitemap be?: A single sitemap file can hold up to 50,000 URLs or 50 MB. The Astro integration splits automatically with a sitemap index.
- Do I need to ping Google when the sitemap changes?: No, that endpoint was deprecated. Just keep the sitemap fresh and let Google recrawl on its own schedule.
- What if some pages should not be in the sitemap?: Exclude them via the
filteroption and also addnoindexto the page itself. Belt and suspenders.