Astro SEO: what the framework already does, the settings to add, and where an island can hide your text
Astro ships finished HTML by default; the title, canonical, sitemap and image work is yours, and two features can keep text out of the first response.
Published by AI Knows Us · Updated 21 October 2026
Astro SEO starts from a strong default: Astro pre-renders every page to plain HTML at build time and ships no JavaScript unless you ask for it, so search engines get your full text on the first request. What Astro does not do for you is the rest of the job. You set the site URL, write the title, description and canonical tag in a layout, add the official sitemap integration, use the built-in image component, and keep your important text out of client-only components. This page walks through each of those steps, using Astro's own documentation as read on 22 October 2026.
What Astro already gets right for search
Astro describes itself as a framework for content-driven websites such as blogs, marketing sites and online shops. Three of its defaults matter for SEO.
- Static HTML by default. Astro's docs say pages, routes and API endpoints are pre-rendered at build time as static pages unless you choose on-demand rendering. A crawler receives finished HTML, with no rendering step needed to see the words.
- Zero JavaScript by default. A React, Vue or Svelte component placed on an Astro page is rendered to HTML with no JavaScript, unless you add a
client:*directive. Only the parts you mark become interactive "islands". - A multi-page site. Each URL is its own HTML document. Astro contrasts this with the single-page app model, where one shell loads and JavaScript draws each view.
That is a good base. Google can render JavaScript, but a page whose text is in the HTML from the start removes a whole class of problems. Our guide to how Google renders JavaScript sites explains why that matters on frameworks that do not work this way.
Step 1: set the site URL first
The site option in astro.config.mjs is your final, deployed URL. Astro's configuration reference says it uses this value to generate your sitemap and canonical URLs, and strongly recommends setting it. The sitemap integration will not work without it, and the value must start with http:// or https://.
// astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap'; export default defineConfig({ site: 'https://www.example.com', integrations: [sitemap()],
});
Use the exact host you want indexed. If your live site is on www, put www here, so every generated URL matches the version you want Google to choose.
Step 2: write the head once, in a layout
Astro has no built-in SEO component. You write the <head> yourself, and the normal place is a layout component that every page uses. Astro's layout docs show a layout taking title and description as props and printing them as <title> and <meta name="description">.
The same layout is where the canonical tag goes. Astro's API reference shows the pattern: build the canonical from the current path and the site value.
---
// src/layouts/BaseLayout.astro
const { title, description } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>{title}</title> <meta name="description" content={description} /> <link rel="canonical" href={canonicalURL} /> </head> <body><slot /></body>
</html>
Make title and description required props, so a page cannot be built without them. If your posts live in a content collection, add both fields to the collection schema. Astro's content collections docs describe the schema as optional but highly recommended, and it validates every entry at build time, so a missing description becomes a build error rather than a gap you find months later. For more on choosing the right canonical, see how canonical tags work.
Step 3: add the sitemap, and know its one gap
The official @astrojs/sitemap integration (version 3.7.4 on its docs page today) is added with npx astro add sitemap. On build it writes sitemap-index.xml and sitemap-0.xml, and more numbered files on large sites. The default limit is 45,000 entries per file.
Points worth knowing from its documentation:
- Dynamic routes in SSR mode are not included. The docs say the integration cannot generate entries for dynamic routes rendered on demand. Static dynamic routes built with
getStaticPaths()are included. If you render pages on demand, usecustomPagesorcustomSitemapsto add them. - Use
filter()to drop pages that should not be indexed, such as thank-you pages. - Google ignores
changefreqandpriority. The integration's own docs say so.lastmodis the field worth setting, per page, throughserialize(). - The
i18noption adds hreflang links to each entry, which matters for multi-language sites (see step 6).
Point crawlers at it with a Sitemap: line in robots.txt. The docs show a src/pages/robots.txt.ts endpoint that reads the site value, so the URL never goes stale.
Step 4: use the Image component
Astro's <Image /> component from astro:assets processes images in src/. For a pre-rendered page the output is a WebP file with width, height, loading="lazy" and decoding="async" set. The docs say it infers dimensions to avoid Cumulative Layout Shift, one of the Core Web Vitals. The alt attribute is mandatory on the component, which is useful for both accessibility and image search.
One catch: files in public/ are copied as they are and are never optimised. Keep content images in src/. For the hero image at the top of a page, add the priority prop (added in Astro 5.10). The docs say it sets loading, decoding and fetchpriority to their best values for above-the-fold images, instead of the lazy default.
Step 5: keep important text out of client-only islands
This is the Astro-specific mistake. Two features move content out of the first HTML response:
| Feature | What the docs say happens | SEO effect |
|---|---|---|
client:only | Skips HTML server rendering and renders only on the client | The component's text is not in the HTML a crawler first receives |
server:defer (server islands) | The page shows fallback content, then the component's contents are fetched on the client | The deferred content arrives after the page loads |
client:load and similar | Rendered to HTML on the server, then made interactive | Text is in the HTML; safe for content |
Use client:only and server islands for things like a cart, an avatar or a live price. Keep product descriptions, article text, headings and FAQs in normal Astro components or in islands that render on the server.
Step 6: settings for multi-language and larger sites
- i18n routing. Astro's i18n config sets a
defaultLocaleandlocales. WithprefixDefaultLocaleoff (the default), your main language has no prefix and every other language does. Pair this with the sitemap'si18noption for hreflang. - Redirects. The
redirectsconfig maps old paths to new ones, including dynamic routes, as long as both sides are the same kind of route. Use it when you rename URLs. - Trailing slashes. The
trailingSlashoption controls matching in development and for on-demand pages. The docs note that for pre-rendered pages your hosting platform decides, so check your host's setting and keep internal links consistent with it. - A custom 404. A
404.astroor404.mdfile insrc/pagesbuilds to404.html, which most hosts serve for missing pages. - RSS. The
@astrojs/rsspackage builds a feed from an endpoint. It is not a ranking factor, but it helps readers and feed tools find new posts.
If you are still choosing a framework, our comparison of static content generators sets Astro beside Hugo, Eleventy and the rest.
Questions about Astro SEO
Is Astro good for SEO?
Yes, for content sites. Pages are pre-rendered to HTML and ship no JavaScript by default, so search engines read the full text immediately. You still need to add titles, descriptions, canonicals and a sitemap yourself.
Does Astro generate a sitemap automatically?
Not on its own. Add the official @astrojs/sitemap integration and set the site option. It then builds the sitemap on every build.
Is there an Astro SEO plugin?
Astro's official tools here are the sitemap and RSS integrations. Community packages exist for meta tags, but a small layout with your own head tags, as shown above, does the same job and is easy to audit.
Does server-side rendering in Astro hurt SEO?
No. On-demand rendered pages still return HTML. The two things to watch are that the sitemap integration skips dynamic SSR routes, and that you set caching so pages respond quickly.
Which Astro version is current?
The npm registry listed Astro 7.4.2 as the latest release on 22 October 2026. Check the docs for the version you run, since options are marked with the release that added them.
Fast HTML is also what an assistant reads
Astro's habit of sending complete HTML helps a second kind of reader. When someone asks ChatGPT or Perplexity which tool, agency or product to choose, the answer is often built from pages the assistant fetched in that moment, and a page whose text is in the first response is easy for it to quote. Being easy to read is not the same as being named, though. AI Knows Us checks whether the assistants actually name your business for the questions your buyers ask, which is a separate result from where your Astro pages rank.