DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Astro 5 for SaaS Landing Pages: Islands Architecture in Production

Next.js is right for your SaaS app. It might not be right for your landing page.

Landing pages need static content, fast load, minimal JS, great SEO. Astro 5 is purpose-built for this.

Zero JS by Default

Astro ships no JavaScript unless you opt in. Every component renders to HTML at build time.

---
// Runs at BUILD TIME — zero bytes sent to browser
const features = await fetch('https://api.yourapp.com/features').then(r => r.json())
---

<section>
  {features.map(f => (
    <div class="card"><h3>{f.title}</h3><p>{f.description}</p></div>
  ))}
</section>
Enter fullscreen mode Exit fullscreen mode

Pure HTML. No hydration. No bundle. No runtime.

Islands Architecture

For interactive components, use client: directives to create isolated hydrated islands:

---
import PricingToggle from '../components/PricingToggle.tsx'
import ContactForm from '../components/ContactForm.tsx'
---

<!-- Static — zero JS -->
<Hero />
<Features />

<!-- React hydrates only when scrolled into view -->
<PricingToggle client:visible monthly={prices.monthly} annual={prices.annual} />
<ContactForm client:visible />
Enter fullscreen mode Exit fullscreen mode

Directives: client:load, client:visible, client:idle, client:media="(max-width: 768px)"

Type-Safe Content Collections (Astro 5)

// src/content/config.ts
import { defineCollection, z } from 'astro:content'

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    publishDate: z.date(),
    tags: z.array(z.string()).default([]),
  }),
})

export const collections = { blog }
Enter fullscreen mode Exit fullscreen mode
---
import { getCollection } from 'astro:content'
const posts = (await getCollection('blog')).sort(
  (a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf()
)
---
{posts.map(p => <a href={`/blog/${p.slug}`}>{p.data.title}</a>)}
Enter fullscreen mode Exit fullscreen mode

Full type safety. All at build time. Zero runtime schema validation.

The Hybrid Architecture

yourapp.com/       → Astro (Cloudflare Pages, free tier)
app.yourapp.com/   → Next.js (Vercel or Fly.io)
Enter fullscreen mode Exit fullscreen mode

Static landing at the edge. App server only for the actual product. Clean separation.

Quick Setup

npm create astro@latest landing -- --template minimal
cd landing
npx astro add tailwind react
Enter fullscreen mode Exit fullscreen mode

Performance Reality

Typical Astro landing page vs Next.js:

  • ~15KB JS vs ~150KB
  • 100 Lighthouse performance (consistently achievable)
  • <1s LCP on cold CDN edge

These numbers move conversion rates.

When to Stay on Next.js

  • Server-side personalization per request
  • Heavy interactivity throughout the page
  • Want one deployment for everything

For everything else: Astro is the right tool for the landing page job.


Ship Faster With AI

If you're building a SaaS and want to skip the boilerplate, check out whoffagents.com:

Top comments (0)