Complete SEO Optimization Guide for Astro Applications
Master SEO best practices and optimization techniques for your Astro website.

Search engine optimisation is not a trick. It is the practice of making your content findable, fast, and trustworthy — and modern search engines are good enough that genuine quality tends to rank well. This guide covers the technical SEO that Astro makes easy, the on-page fundamentals, and the real-world checks that actually move rankings.
How Search Engines Work
Crawlers (Googlebot, Bingbot) follow links across the web, download pages, and index their content. The ranking algorithm weighs hundreds of signals, but three categories dominate:
- Relevance — does the page answer the query?
- Authority — do trusted sites link to it?
- Experience — is the page fast, stable, and accessible?
Technical SEO addresses category three and ensures categories one and two aren’t undermined by broken metadata, slow loads, or crawler-blocked pages.
Metadata with an Astro <head> Component
Astro renders every page to HTML on the server, so <title>, <meta>, and Open Graph tags are visible to crawlers without any JavaScript. The cleanest pattern is a reusable <SEO> component that accepts props and renders into the document head:
---
// src/components/SEO.astro
const {
title,
description = "The default description for pages that don't set one.",
image = "/og-default.webp",
type = "website",
} = Astro.props;
const siteName = "My Site";
const canonical = new URL(Astro.url.pathname, Astro.site);
const fullTitle = title ? `${title} | ${siteName}` : siteName;
---
<title>{fullTitle}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonical} />
<meta name="robots" content="index, follow" />
<!-- Open Graph -->
<meta property="og:type" content={type} />
<meta property="og:site_name" content={siteName} />
<meta property="og:title" content={fullTitle} />
<meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, Astro.site)} />
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@mysite" />
Set site in astro.config.mjs so Astro.site resolves absolute URLs. Then drop the component into your layout’s <head> and pass per-page values:
---
// src/pages/blog/[slug].astro
import SEO from "../../components/SEO.astro";
const post = await fetchPost(Astro.params.slug);
---
<head>
<SEO
title={post.title}
description={post.excerpt}
image={post.coverImage}
type="article"
/>
</head>
The canonical URL tells search engines which URL is authoritative when the same content appears at multiple paths (pagination, query params, etc.).
Sitemap
A sitemap tells crawlers which pages exist and how often they change. Astro’s official integration generates one for every route at build time — add it with one command:
npx astro add sitemap
// astro.config.mjs
import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://example.com", // required for sitemap URLs
integrations: [
sitemap({
changefreq: "weekly",
priority: 0.7,
filter: (page) => !page.includes("/draft/"),
}),
],
});
Build the site and it emits /sitemap-index.xml. Submit that in Google Search Console.
robots.txt
Control which pages crawlers can access. Drop a static file in public/ so it’s served verbatim at the site root:
# public/robots.txt
User-agent: *
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /draft/
Sitemap: https://example.com/sitemap-index.xml
Accessible at /robots.txt. Block API routes, admin panels, and draft content from indexing.
Structured Data (JSON-LD)
Structured data helps Google display rich results — star ratings, article metadata, FAQs, breadcrumbs — in the search results page itself.
---
// src/components/ArticleSchema.astro
const { post } = Astro.props;
const schema = {
"@context": "https://schema.org",
"@type": "Article",
headline: post.title,
description: post.excerpt,
image: post.coverImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
"@type": "Person",
name: post.author.name,
url: `https://example.com/authors/${post.author.slug}`,
},
publisher: {
"@type": "Organization",
name: "My Site",
logo: { "@type": "ImageObject", url: "https://example.com/logo.png" },
},
};
---
<script type="application/ld+json" set:html={JSON.stringify(schema)} />
Use Google’s Rich Results Test to validate your schema. Common types: Article, BreadcrumbList, FAQPage, Product, Organization, Person.
Core Web Vitals and SEO
Google uses Core Web Vitals as a ranking signal. LCP, INP, and CLS are the three metrics that matter (detailed coverage in the Performance Optimisation post):
- LCP < 2.5s — ensure the hero image uses
loading="eager"in Astro’s<Image>. - INP < 200ms — avoid long tasks on the main thread; defer heavy JS.
- CLS < 0.1 — set explicit
widthandheighton all images and embeds.
# Check real-user CWV for your domain in Google Search Console
# Or run from the CLI:
npx lighthouse https://example.com --only-categories=performance
Semantic HTML
Crawlers parse your HTML structure. Use semantic elements to communicate content hierarchy:
<!-- Good — clear structure -->
<article>
<header>
<h1>Article Title</h1>
<p>
By <a href="/authors/alice">Alice</a> ·
<time datetime="2026-01-15">Jan 15, 2026</time>
</p>
</header>
<main>
<p>Introduction…</p>
<h2>First Section</h2>
<p>Content…</p>
</main>
</article>
<!-- Avoid — meaningless divs everywhere -->
<div class="article-wrapper">
<div class="title">Article Title</div>
<div class="content">…</div>
</div>
One <h1> per page. Headings form a logical outline — don’t skip levels for styling purposes.
Internal Linking
Internal links pass authority between pages and help crawlers discover content. Every important page should be reachable within two or three clicks from the homepage.
<!-- Link with descriptive anchor text — not "click here" -->
<a href="/blog/react-hooks-deep-dive">React Hooks: A Deep Dive</a>
<!-- Breadcrumbs help both UX and structured data -->
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
<li aria-current="page">React Hooks Deep Dive</li>
</ol>
</nav>
Image SEO
Images appear in Google Images search and contribute to page relevance.
---
import { Image } from "astro:assets";
import reactHooks from "../assets/react-hooks.webp";
---
<Image
src={reactHooks}
alt="Diagram showing React component re-render flow with useCallback"
width={1200}
height={630}
/>
alttext describes the image for screen readers and crawlers. Describe the content, not “image of…”.- File names use hyphens:
react-hooks-flow-diagram.webp, notIMG_4923.webp. - Serve images from the same domain or a CDN with proper
Cache-Control.
Page Speed
Site speed is a direct ranking factor. The biggest wins (covered in depth in the Performance post):
# Measure before and after every change
npx lighthouse https://example.com --view
# Key targets for SEO
# Performance score > 90
# LCP < 2.5s
# CLS < 0.1
# TTFB < 800ms
For Astro specifically:
- Pre-render pages at build time so they serve straight from the CDN cache.
- Use
astro:assets<Image>for all images — automatic WebP/AVIF, lazy loading, size optimisation. - Minimise client-side JavaScript — most content pages need no
client:*directives at all.

Mobile Optimisation
Google indexes the mobile version of your site (mobile-first indexing). Check it:
# Test mobile usability
https://search.google.com/test/mobile-friendly
# Or in Chrome: DevTools → Toggle Device Toolbar → Lighthouse
Tailwind’s responsive prefixes make mobile-first design natural. Ensure tap targets are at least 44×44px, text is readable without zooming, and horizontal scroll is absent.
Google Search Console
Free, essential. Set it up on day one.
Key reports to check monthly:
- Coverage — which pages are indexed, which are excluded, and why.
- Core Web Vitals — field data from real users, segmented by device.
- Search Performance — queries driving clicks, impressions, and average position.
- Links — top linked pages and top linking sites.
<!-- Verify site ownership with a <meta> tag in your <head> -->
<meta name="google-site-verification" content="your-verification-code" />
Content Quality
Technical SEO is table stakes. Content quality is the differentiator. The signals Google rewards:
- E-E-A-T — Experience, Expertise, Authoritativeness, Trustworthiness. Author bios, citations, and fresh dates matter.
- Search intent match — a query like “how to reverse a string in JavaScript” expects code and explanation, not a product page.
- Depth over length — a 1,500-word post that thoroughly answers the question beats a 5,000-word padded one.
- Original data and examples — unique charts, code samples, and case studies attract backlinks naturally.
Closing Thoughts
SEO compounds. A well-structured site with fast pages, good metadata, and genuinely useful content builds authority slowly and then all at once. Focus on the technical foundations — metadata, sitemap, structured data, Core Web Vitals — then publish content that earns links by being the best answer to a specific question. That combination holds up across algorithm updates better than any hack.
About the author
The Plake Team
Writes long-form essays on craft, software, and the slow web. Curates the Sunday digest read by 88,000+ readers.
Read moreKeep reading
Related Articles








