A lean, production-ready Astro v6 monorepo template with Tailwind v4, Svelte 5 and Biome.
Status: Astro v6 is stable. This template tracks the latest Astro v6 releases.
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:
starter and blog)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/.
This template succeeds astro-v5-template. It was rebuilt from scratch with a focus on simplicity and the Astro v6 feature set.
| 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 |
@casoon/astro-speed-measure for build performance tracking@casoon/astro-post-audit for SEO, link and WCAG checks after every build@casoon/nosecrets in pre-commit plus manual workspace scans@casoon/astro-site-files generates robots.txt, sitemap.xml, llms.txt, security.txt and humans.txt at build time@casoon/astro-structured-data generates JSON-LD via typed Astro components (ArticleSchema, WebSiteSchema, FAQSchema, …)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
# 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
| 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 fallow:dead |
Detect unused files, exports and dependencies |
pnpm fallow:health |
Complexity score, hotspots and refactor targets |
pnpm fallow:audit |
Combined dead-code + complexity + duplication audit |
pnpm clean |
Remove build artifacts + node_modules |
Landing page featuring:
Blog template featuring:
readTime, articleType, series and seriesOrder/rss.xml) with article:readingTime, article:series and OG image enclosures/sitemap.xml) with i18n hreflang via @casoon/astro-site-filesUse apps/starter or apps/blog as the starting point, depending on whether the new project is page-focused or content-focused.
apps/<name>/ with its own package.json, astro.config.mjs, tsconfig.json, src/ and public/ folders.@astro-v6/<name> and add scripts for dev, build, preview, type-check, clean and deploy.@astro-v6/shared/styles/global.css in the app layout, and import shared components, layouts, SEO helpers and utilities via @astro-v6/shared/*.tsconfig.json path aliases so @/* points to local src/* and @astro-v6/shared/* points to ../../shared/src/*.astro.config.mjs with the same core integrations: Tailwind, Svelte, @casoon/astro-site-files, @casoon/astro-structured-data, @casoon/astro-post-audit and @casoon/astro-speed-measure.dev:<name>, build:<name> and preview:<name> when the app should be addressable from the workspace root.playwright.config.ts plus tests under e2e/<name>/ when the app needs CI browser coverage.@astro-v6/shared)All shared code lives in shared/:
Navbar.astro, ThemeToggle.svelte, TableOfContents.svelte, ReadingProgress.svelteBaseLayout.astro (HTML base with skip link)PageSEO.astro (meta tags, Open Graph, JSON-LD via @casoon/astro-structured-data)env.ts, api.ts, cn.ts, i18n.ts, og.tsBoth apps support English (default) and German:
/, /contact, /blog/welcome/de/, /de/contactsrc/i18n/@astro-v6/shared/utils/i18nOpen 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
public/og/*.png (1200x630, gitignored)<PageSEO ogImage={...}># 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.
fallow is included as a dev dependency for static analysis of the TypeScript/JavaScript codebase.
# Detect unused files, exports, types and dependencies
pnpm fallow:dead
# Complexity score with hotspots and refactor targets
pnpm fallow:health
# Combined audit: dead code + complexity + duplication
pnpm fallow:audit
fallow understands the monorepo structure and resolves cross-workspace imports correctly. It also integrates as an MCP server for AI-assisted analysis directly in your editor — see the fallow MCP docs for setup.
# Scan the whole workspace
pnpm secrets:scan
# Scan only staged files (used by pre-commit)
pnpm secrets:scan:staged
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.
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.
Both apps use @casoon/astro-structured-data to generate JSON-LD markup via typed Astro components. The integration is registered in astro.config.mjs and provides a virtual config module consumed by the components at build time.
PageSEO.astro in shared/ selects the right schema automatically:
ogType="article") — renders <ArticleSchema> with headline, author, dates, image and publisher<Schema> with @type: "WebPage", name, description and canonical URLAdditional schema components are available for FAQs, products, local businesses, events, breadcrumbs and more:
---
import { ArticleSchema, FAQSchema, BreadcrumbSchema } from '@casoon/astro-structured-data/components';
---
<ArticleSchema
title="My Post"
description="..."
datePublished="2026-01-01"
authorName="Author"
imageUrl="/og/post.png"
/>
The integration also adds a Structured Data validator to Astro's dev toolbar for real-time inspection. JSON-LD validity is verified at build time by @casoon/astro-post-audit (structured_data: { check_json_ld: true }).
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.
This template enforces WCAG 2.1 Level AA compliance through two complementary layers:
@casoon/astro-post-audit runs automatically after every build and checks the raw HTML output for:
alt attributes on images<a> without text or aria-label)<h1> elements per pageaxe-core via @axe-core/playwright validates the fully rendered pages in a real browser:
# 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.
BaseLayout<header>, <nav>, <main>, <article>, <section> throughoutaria-label, aria-current, role where neededprefers-color-scheme, OKLCH colors maintain contrast in both modesThe 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.
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.
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.
This template leverages the key features of Astro v6:
glob() loader instead of legacy type: 'content'z.email(), z.url() as top-level functionsThis template includes a Claude Code setup for AI-assisted development:
.claude/mcp.json) — Pre-configured MCP servers for context7 documentation lookup and Cloudflare toolingCLAUDE.md) — Architecture rules, code conventions, and dependency constraintsFor the full set of reusable Claude Code skills (Astro, Tailwind, Svelte, SEO, Playwright, and more), see casoon/ai-agent-config.
MIT