Astro 5 Islands: SEO Landing Pages with View Transitions
Marketing sites with five to ten pages rarely need a full React bundle on every route. Yet a pure SPA tanks Core Web Vitals, and SSR adds latency you don’t always need. Astro 5 ships static HTML by default and hydrates Islands — isolated interactive components — only where JavaScript actually matters.
View Transitions, now first-class in Astro 5, add smooth page changes without turning your site into a single-page app. Crawlers still receive plain HTML with unique titles and canonical URLs. Users get animated navigation. Both sides win.
This guide covers a production service landing: multi-page structure, React islands for forms and animations, JSON-LD, and Vercel deployment.
Why Islands Beat SPA and SSR for Marketing Sites
Islands architecture is Astro’s core bet. The build outputs zero-JS HTML for static content. Components with a client:* directive hydrate independently. Everything else stays markup.
| Approach | First-load JS | Crawler HTML | Page transitions |
|---|---|---|---|
| SPA | Full framework | Needs SSR/prerender | Fast, heavy |
| SSR (Next.js) | Varies | Excellent | Client router |
| Astro Islands | Targeted only | Full static HTML | MPA + View Transitions |
Typical split for a service landing:
Static HTML (no JS): hero copy, benefits, testimonials, FAQ, footer, nav, Open Graph, JSON-LD.
Islands (with JS): booking forms, price calculators, framer-motion decorations, cookie banners.
Lighthouse scores often hit LCP under 1.5 seconds and near-zero TBT because the main content never waits for hydration.
Project Setup
Bootstrap with React for shadcn/ui compatibility:
npm create astro@latest landing -- --template basics
cd landing
npx astro add react tailwind
Suggested structure:
src/
├── layouts/BaseLayout.astro # head, ViewTransitions, JSON-LD
├── pages/index.astro
├── pages/pricing.astro
├── pages/contact.astro
├── components/Hero.astro
├── components/BookingForm.tsx
└── components/HeroAnimation.tsx
Enable View Transitions in your base layout:
---
import { ViewTransitions } from 'astro:transitions';
const { title, description } = Astro.props;
const canonical = new URL(Astro.url.pathname, Astro.site);
---
<html lang="en">
<head>
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonical} />
<ViewTransitions />
</head>
<body><slot /></body>
</html>
The injected script (~2 KB gzip) intercepts internal link clicks and animates DOM swaps. With JS disabled, the site behaves as a normal multi-page app — SEO intact.
Need something similar built for you? Message on Telegram.
View Transitions Without SEO Penalties
The browser’s View Transitions API morphs elements between pages when they share a transition:name. Astro wraps this with fallbacks for browsers that lack native support.
<!-- index.astro -->
<header transition:name="hero" transition:animate="fade">
<h1>Fast SEO Landing Pages</h1>
</header>
<!-- pricing.astro -->
<header transition:name="hero" transition:animate="fade">
<h1>Pricing</h1>
</header>
Matching transition:name links the two headers across routes. Each page keeps its own <h1> and <title> — Google indexes them separately.
Prefetch on hover loads HTML for linked pages without pulling island JavaScript early:
<a href="/pricing" data-astro-prefetch>Pricing</a>
Interactive Islands: Forms and Motion
Use client:visible for below-the-fold forms — JS loads when the block enters the viewport:
<BookingForm client:visible />
Use client:load for above-the-fold animations that must run immediately but stay isolated:
<HeroAnimation client:load />
SEO rule: keep headlines and body copy in .astro files. framer-motion handles decoration; crawlers read static HTML, not animated wrappers.
// HeroAnimation.tsx — decorative only
import { motion } from 'framer-motion';
export default function HeroAnimation() {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
/>
);
}
shadcn/ui works as a standard React island. Share one Tailwind config across Astro and React — no duplicate utility classes.
For FAQ and case studies, Astro 5 Content Layer generates static pages from Markdown at build time. No client-side fetch, full indexability.
SEO Checklist and Core Web Vitals
View Transitions improve UX; they don’t replace SEO fundamentals.
- Unique meta per page: pass
titleanddescriptionthrough your layout. Build canonical fromAstro.site+ pathname. - JSON-LD: embed schema as a static
<script type="application/ld+json">— visible to Googlebot without JS. - Test each URL separately in PageSpeed Insights (
/,/pricing,/contact). First visits are scored as standard MPAs. - Search Console URL Inspection: confirm rendered HTML includes titles, canonical tags, and FAQ text.
| Metric | Target | Astro advantage |
|---|---|---|
| LCP | < 2.5 s | No blocking framework JS |
| INP | < 200 ms | Partial hydration |
| CLS | < 0.1 | Skeleton placeholders for islands |
Deploy on Vercel
npm run build # outputs dist/
Vercel auto-detects Astro. Static assets serve from the Edge Network. Preview deployments on every PR let you validate View Transitions and Lighthouse scores before merging.
Cloudflare Pages and Netlify work equally well — Islands architecture is static-hosting friendly everywhere.
Questions? Telegram → or vic.kell@ya.ru
FAQ
Do View Transitions hurt indexing?
No. Each route is a separate HTML document with its own URL, title, and canonical. Transitions run only during client-side navigation. Crawlers fetch full HTML on first request.
Astro Islands vs Next.js 15 PPR?
Choose Astro for multi-page marketing sites where most content is static. Choose Next.js PPR when you need one page with several dynamic blocks (forms, personalization, live data) and your team already lives in React.
Can I use a headless CMS?
Yes — fetch at build time via Content Layer or getStaticPaths. Content lands in HTML. Trigger rebuilds via CMS webhooks, or explore adapter-level revalidation on Vercel.
client:visible vs client:idle?
client:visible defers JS until the element scrolls into view — best for forms below the fold. client:idle hydrates after the main thread clears — good for hero forms that must respond quickly without blocking LCP. Avoid client:only on SEO-critical content; it skips server rendering entirely.
Conclusion
Astro 5 Islands plus View Transitions deliver a practical stack for SEO landing pages and small marketing sites in 2026. Static HTML handles indexing and Core Web Vitals. Targeted JavaScript powers forms and motion. View Transitions add polish without SPA weight.
The workflow: SEO content in .astro, interactivity in React islands, structured data in your layout, static deploy on Vercel. For single-page landings heavy on dynamic features, Next.js 15 PPR remains the alternative — but for classic multi-page sites, Astro stays the lighter choice.