Skip to content

casoon/astro-v6-template

Repository files navigation

Astro v6 Template

CI Astro Tailwind CSS Svelte TypeScript Biome Zod pnpm nosecrets License: MIT

A lean, production-ready Astro v6 monorepo template with Tailwind v4, Svelte 5 and Biome.

Live Demos: Starter · Blog

Status: Astro v6 is stable. This template tracks the latest Astro v6 releases.

Multi-Project Architecture

This template uses pnpm workspaces with a shared library, making it an ideal foundation for running multiple projects from a single repository. Typical use cases:

  • Main site + Blog (included as starter and blog)
  • Landing pages for campaigns or product launches
  • Online shop storefront
  • Documentation site

All projects share the same design tokens, UI components and utilities — ensuring a consistent look and feel while keeping each app independently deployable. Adding a new project is as simple as creating a new folder under apps/ and importing from shared/.

Predecessor

This template succeeds astro-v5-template. It was rebuilt from scratch with a focus on simplicity and the Astro v6 feature set.

What Changed from v5?

Area v5 v6
Apps 3 (blank, base, demo) 2 (starter, blog)
Linting Biome + ESLint + Prettier Biome only
Fonts 16 packages 3 (Inter, Lora, Fira Code)
Styling @casoon/atlas + Tailwind Custom tokens + Tailwind v4
Node >= 20 >= 22.12.0
Zod v3 v4
Content Legacy Collections Loader API
Dev server Standard Vite Vite Environment API

Features

  • Astro v6 — New dev server, Live Content Collections, CSP
  • Tailwind v4 — CSS-first config, Vite plugin, OKLCH colors
  • Svelte 5 — Runes API ($state, $derived) for reactive islands
  • i18n — Multi-language support (en/de) with Astro i18n routing
  • OG Images — Auto-generated Open Graph images at build time (Satori + resvg)
  • Astro Actions — Server-side contact form handling
  • CSP — Content Security Policy with SHA-256 nonces
  • Build Metrics@casoon/astro-speed-measure for build performance tracking
  • Post-Build Audit@casoon/astro-post-audit for SEO, link and WCAG checks after every build
  • Secret Scanning@casoon/nosecrets in pre-commit plus manual workspace scans
  • Playwright — E2E tests for both apps with axe-core a11y scanning
  • Biome — Single tool for linting + formatting (replaces ESLint + Prettier)
  • Zod v4 — Runtime validation for env and forms
  • pnpm Workspaces — Monorepo with catalog for centralized dependency management
  • Dark Mode — System preference + manual toggle
  • Site Files@casoon/astro-site-files generates robots.txt, sitemap.xml, llms.txt, security.txt and humans.txt at build time
  • SEO — robots.txt, canonical URLs, meta descriptions, JSON-LD
  • WCAG 2.1 AA — Two-layer accessibility: axe-core runtime checks + static HTML audit
  • TypeScript Strict — Fully typed throughout

Structure

astro-v6-template/
├── apps/
│   ├── starter/          # Landing page + contact form + i18n
│   └── blog/             # Blog with MDX + RSS + i18n
├── shared/                # Design tokens, components, layouts, SEO, utilities
├── e2e/
│   ├── starter/          # Playwright E2E tests for starter
│   └── blog/             # Playwright E2E tests for blog
├── .github/workflows/    # CI pipeline
├── biome.json            # Linting & formatting
├── playwright.config.ts  # E2E test configuration
└── pnpm-workspace.yaml   # Workspace + catalog

Prerequisites

  • Node.js >= 22.12.0
  • pnpm >= 11.0.0

Quick Start

# Clone the repository
git clone https://github.com/casoon/astro-v6-template.git
cd astro-v6-template

# Install dependencies
pnpm install

# Start the starter app
pnpm dev

# Start the blog app
pnpm dev:blog

Available Scripts

Script Description
pnpm dev Start the starter app (port 4321)
pnpm dev:blog Start the blog app (port 4322)
pnpm build Build all apps
pnpm build:starter Build starter only
pnpm build:blog Build blog only
pnpm check Run Biome lint + format check
pnpm check:fix Biome auto-fix
pnpm format Format all files
pnpm test:e2e Run all Playwright E2E tests
pnpm test:e2e:starter E2E tests for starter only
pnpm test:e2e:blog E2E tests for blog only
pnpm type-check TypeScript check
pnpm clean Remove build artifacts + node_modules

Apps

Starter

Landing page featuring:

  • Hero section with feature grid
  • Contact form with Astro Actions + Zod validation
  • i18n (English + German) with language switcher
  • OG image generation per page and locale
  • Dark mode toggle
  • SEO component with JSON-LD

Blog

Blog template featuring:

  • MDX support with remark-gfm, rehype-slug, code block language labels and Shiki title transformer
  • Content Collections (Loader API) with schema fields for readTime, articleType, series and seriesOrder
  • Table of Contents — sticky sidebar on desktop with IntersectionObserver scrollspy
  • Reading progress bar — thin indicator at the top of every post
  • Enriched RSS feed (/rss.xml) with article:readingTime, article:series and OG image enclosures
  • Automatic sitemap (/sitemap.xml) with i18n hreflang via @casoon/astro-site-files
  • i18n (English + German) with language switcher
  • OG image generation per page and blog post
  • Tag display

Adding Another App

Use apps/starter or apps/blog as the starting point, depending on whether the new project is page-focused or content-focused.

  1. Create apps/<name>/ with its own package.json, astro.config.mjs, tsconfig.json, src/ and public/ folders.
  2. Set the package name to @astro-v6/<name> and add scripts for dev, build, preview, type-check, clean and deploy.
  3. Import shared styles from @astro-v6/shared/styles/global.css in the app layout, and import shared components, layouts, SEO helpers and utilities via @astro-v6/shared/*.
  4. Copy the app-level tsconfig.json path aliases so @/* points to local src/* and @astro-v6/shared/* points to ../../shared/src/*.
  5. Configure astro.config.mjs with the same core integrations: Tailwind, Svelte, @casoon/astro-site-files, @casoon/astro-post-audit and @casoon/astro-speed-measure.
  6. Choose a unique dev port if the app should run alongside the existing apps.
  7. Add root scripts such as dev:<name>, build:<name> and preview:<name> when the app should be addressable from the workspace root.
  8. Add an optional Playwright project in playwright.config.ts plus tests under e2e/<name>/ when the app needs CI browser coverage.

Shared Package (@astro-v6/shared)

All shared code lives in shared/:

  • Styles — Design tokens (OKLCH), global CSS, Tailwind theme
  • ComponentsNavbar.astro, ThemeToggle.svelte, TableOfContents.svelte, ReadingProgress.svelte
  • LayoutsBaseLayout.astro (HTML base with skip link)
  • SEOPageSEO.astro (meta tags, Open Graph, JSON-LD)
  • Utilitiesenv.ts, api.ts, cn.ts, i18n.ts, og.ts

i18n

Both apps support English (default) and German:

  • English pages at root: /, /contact, /blog/welcome
  • German pages with prefix: /de/, /de/contact
  • Language switcher in the navbar (EN/DE links)
  • Translation files per app in src/i18n/
  • Shared locale utilities in @astro-v6/shared/utils/i18n

OG Image Generation

Open Graph images are generated at build time:

# Generate manually
pnpm --filter starter generate:og
pnpm --filter blog generate:og

# Runs automatically before `astro build`
pnpm build
  • Output: public/og/*.png (1200x630, gitignored)
  • Blog script reads MDX frontmatter to generate post-specific images
  • All pages reference their OG image via <PageSEO ogImage={...}>

E2E Tests

# Run all tests (builds must exist)
pnpm test:e2e

# Run per app
pnpm test:e2e:starter
pnpm test:e2e:blog

Tests covering navigation, i18n, SEO/OG meta tags, contact form, theme toggle, RSS, accessibility (axe-core WCAG 2.1 AA), robots.txt and sitemap.

Secret Scanning

# Scan the whole workspace
pnpm secrets:scan

# Scan only staged files (used by pre-commit)
pnpm secrets:scan:staged

Build Performance Metrics

Both apps include @casoon/astro-speed-measure to track build performance. It measures integration hooks, Vite plugin timing, per-page rendering and asset processing — giving you visibility into what slows down your build.

// astro.config.mjs
import speedMeasure from '@casoon/astro-speed-measure';

export default defineConfig({
  integrations: [
    // ... other integrations
    speedMeasure(), // always add as last integration
  ],
});

Each build prints a performance report to the console and writes a JSON baseline for trend comparisons. Supports budgets, HTML reports and GitHub Actions CI summaries.

Post-Build Audit

Both apps include @casoon/astro-post-audit for automatic SEO, link and WCAG checks after every build. It runs a fast Rust binary against the build output via the astro:build:done hook.

The template ships with comprehensive rules enabled out of the box:

// astro.config.mjs
postAudit({
  preset: 'standard',
  failOn: 'errors',
  hints: { sourceFiles: true },
  rules: {
    filters: { exclude: ['404.html'] },
    canonical: { self_reference: true },
    opengraph: { require_og_image: true },
    a11y: { require_skip_link: true },
    links: { check_fragments: true },
    structured_data: { check_json_ld: true },
    content_quality: {
      detect_duplicate_titles: true,
      detect_duplicate_descriptions: true,
    },
  },
}),

Checks include canonical self-references, Open Graph image presence, skip navigation link, fragment link integrity, JSON-LD validity and duplicate title/description detection — on top of everything the standard preset covers. Use failOn: 'warnings' for stricter CI enforcement.

Site Files

Both apps use @casoon/astro-site-files to generate all standard site meta-files at build time:

@casoon/astro-site-files replaces the older split packages @casoon/astro-sitemap and @casoon/astro-crawler-policy.

// astro.config.mjs
import siteFiles from '@casoon/astro-site-files';

siteFiles({
  sitemap: {
    i18n: { defaultLocale: 'en', locales: { en: 'en', de: 'de-DE' } },
    sources: [getBlogSitemapEntries],  // blog: inject lastmod from MDX frontmatter
  },
  robots: {},   // allow all, sitemap URL auto-derived from astro.config.site
  llms: {
    title: 'Astro v6 Blog',
    description: 'A blog template built with Astro v6, MDX and Content Collections.',
  },
}),

Generated files: robots.txt, sitemap.xml (with i18n hreflang), llms.txt. Optional: /.well-known/security.txt, humans.txt.

The blog RSS feed is generated as a prerendered page endpoint (src/pages/rss.xml.ts) using @astrojs/rss + getCollection(). Posts are sorted by lastmod ?? date and enriched with article:readingTime, article:series and OG image <enclosure> elements via a custom article: XML namespace.

Accessibility (WCAG 2.1 AA)

This template enforces WCAG 2.1 Level AA compliance through two complementary layers:

Layer 1: Static HTML Audit (Build Time)

@casoon/astro-post-audit runs automatically after every build and checks the raw HTML output for:

  • Missing alt attributes on images
  • Empty links (<a> without text or aria-label)
  • Missing page landmarks and heading structure
  • Duplicate <h1> elements per page

Layer 2: Runtime Accessibility Testing (E2E)

axe-core via @axe-core/playwright validates the fully rendered pages in a real browser:

  • Color contrast ratios (>= 4.5:1)
  • ARIA roles and attributes
  • Keyboard navigation and focus management
  • Form label associations
# Run accessibility tests
pnpm test:e2e           # all tests including a11y

Tests are located in e2e/starter/a11y.spec.ts and e2e/blog/a11y.spec.ts.

Built-in Accessibility Features

  • Skip to content link in BaseLayout
  • Semantic HTML<header>, <nav>, <main>, <article>, <section> throughout
  • ARIA attributesaria-label, aria-current, role where needed
  • Link underlines — Always visible, not just on hover
  • Focus indicators — Visible focus rings on all interactive elements
  • Dark mode — Respects prefers-color-scheme, OKLCH colors maintain contrast in both modes

Deployment

The template ships pre-configured for Cloudflare Workers — the default deployment target. All application logic (forms, i18n, routing, SEO) is platform-agnostic. Switching platforms requires only three config changes.

Cloudflare Workers (default)

No changes needed. Deploy after building:

pnpm build:starter
wrangler deploy --config apps/starter/dist/server/wrangler.json

pnpm build:blog
cd apps/blog && wrangler deploy

Cloudflare's edge runtime gives you global low-latency SSR out of the box, without managing servers.

Other platforms (Node.js, Vercel, Netlify, …)

Three config changes per app:

1. Swap the adapter in astro.config.mjs:

// Node.js
import node from '@astrojs/node';
adapter: node({ mode: 'standalone' })

// Vercel
import vercel from '@astrojs/vercel';
adapter: vercel()

// Netlify
import netlify from '@astrojs/netlify';
adapter: netlify()

2. Enable Sharp image optimization (Sharp runs on Node.js but not on Cloudflare Workers):

image: {
  service: {
    entrypoint: 'astro/assets/services/sharp',
  },
},

3. Delete wrangler.toml — not needed outside of Cloudflare.

Everything else — Astro Actions, contact form, i18n, CSP, post-build audit, sitemap — works identically on every platform.

Astro v6 Highlights

This template leverages the key features of Astro v6:

  • Vite Environment API — Dev server runs in the same runtime as production
  • Content Collections Loader APIglob() loader instead of legacy type: 'content'
  • Content Security Policy — Built-in CSP with SHA-256 nonces
  • Astro Actions — Type-safe server-side form handling
  • Zod v4z.email(), z.url() as top-level functions
  • Node 22+ — Minimum requirement

Claude Code Integration

This template includes a Claude Code setup for AI-assisted development:

  • MCP Servers (.claude/mcp.json) — Pre-configured MCP servers for context7 documentation lookup and Cloudflare tooling
  • Project instructions (CLAUDE.md) — Architecture rules, code conventions, and dependency constraints

For the full set of reusable Claude Code skills (Astro, Tailwind, Svelte, SEO, Playwright, and more), see casoon/ai-agent-config.

License

MIT

About

Production-ready Astro v6 monorepo template with Tailwind v4, Svelte 5, Zod v4 and Biome. Multi-project architecture with shared design tokens, UI components and utilities.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors