Skip to main content
Astro can be a server application or a static site. Choose the SEO serving mechanism from the deployment mode, not from the Astro logo:
  • output: "server" or on-demand SEO routes → mount one middleware
  • default/static output → write SEO assets into public/ before astro build
Both modes use the same head helpers and the same client-side AI registration.

1. Shared config and SEO instance

src/lib/commerce-seo.config.ts
src/lib/seo.ts

2. Render Astro-native head data

src/pages/product/[slug].astro
Your layout should render seoHead.title, seoHead.meta, seoHead.links, and seoHead.scripts. Do not also render generic product/page Open Graph tags when seoHead is present.

Add the breadcrumb separately

Use seo.productUrl() and seo.categoryUrl() for breadcrumbs. Hard-coded /product/ or /category/ concatenation breaks as soon as a CMS or route resolver changes the public URL.

3A. Server deployment: mount middleware

src/middleware.ts
The middleware handles Markdown mirrors, content negotiation, llms.txt, sitemap.md, robots, and XML sitemap routes. It delegates unrelated requests without adding unnecessary Vary: Accept cache keys. Use this only when those requests actually reach an Astro server in production.

3B. Static deployment: generate physical files

For Astro’s default static output, write the assets into public/ before the build: Use the same pure SEO config from step 1 rather than copying site identity or route bases into the build script. Run the prebuild as TypeScript and load local env files explicitly because this command runs before Astro starts:
scripts/generate-seo-assets.ts
package.json
Do not keep indexable: true in a shared build script. Leaving it unset preserves the package’s deployment detection, so preview CI builds stay non-indexable while a proven production deployment becomes indexable automatically. The generated files bypass Astro’s file-router priority entirely.
Do not implement static .md mirrors as a catch-all Astro route. A concrete /product/[slug] route can claim /product/shoe.md before the catch-all gets a chance to serve it.

4. Register agent tools with the client runtime

With View Transitions, the document changes without a normal full-page reload. Register on astro:page-load and clean up registrations across transitions.
src/lib/client-runtime.ts
If your app has no View Transitions, registering once from a client island/runtime bootstrap is sufficient.

Production checklist

  • Astro output mode matches the SEO serving mechanism
  • static deployments generate files into public/
  • server deployments mount createAstroSeoMiddleware
  • page layout yields generic social defaults whenever page-specific seoHead exists
  • breadcrumb URLs come from route resolvers
  • View Transition navigation does not accumulate duplicate WebMCP registrations
  • development diagnostics fire on every starter page load where registration is expected

Reference starter

Static Astro production pattern with page head data, prebuilt discovery assets, and WebMCP registration.