Skip to content

Project Directory Structure

The Astro Performance Starter follows a structured, scalable architecture designed for:

  • Developer Experience: Clear, predictable file locations
  • Performance First: Optimized build output and asset organization
  • Atomic Design: Component hierarchy that scales from simple to complex
  • Type Safety: TypeScript-first with generated types from content
  • AI-Friendly: Well-documented structure for AI development tools
Terminal window
astro-performance-starter/
├── .github/
├── workflows/
├── ci.yml # Quality gates, budgets, e2e
├── deploy.yml # GitHub Pages deployment
├── lighthouse.yml # Lighthouse CI gates (desktop + mobile)
├── mutation.yml # Stryker mutation testing
└── release.yml # Release automation
├── CODEOWNERS
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── ISSUE_TEMPLATE/
├── bug-report.md
└── feature-request.md
├── docs/
├── README.md # Docs overview & navigation
├── getting-started/ # Onboarding, FAQ, quick deploy
├── development/ # Contributor workflows & conventions
├── patterns/ # Pattern guides (islands, MDX, …)
├── snippets/ # Reusable doc snippets
├── ai-context/ # AI assistant context docs
├── assets/ # Doc images and assets
├── 2026-06_design_system/ # Design system reference sheets
├── logo.svg
├── personalization-guide.md
├── implementation-guides/ # Development guides
├── README.md # Implementation roadmap (tier model)
├── completed/ # Foundation phases (0-4)
├── phase-0-foundation.md
├── phase-1-content-arch.md
├── phase-2-design-system.md
├── phase-3-tooling.md
├── phase-4-skeleton.md
└── phase-{1..4}-code-examples.md
├── active-phases/ # Build & polish phases (5-12)
├── phase-5-components.md
├── phase-6-sections.md
├── phase-7-content.md
├── phase-8-qa.md
├── phase-9-performance.md
├── phase-10-deployment.md
├── phase-11-documentation.md
└── phase-12-post-launch.md
├── guides/ # Topic-specific guides
├── accessibility-guide.md
├── components-guide.md
├── content-model-guide.md
├── image-optimization-guide.md
├── responsive-design-guide.md
├── rollback-strategies-guide.md
└── testing-strategy-guide.md
├── code-examples/ # Implementation examples
└── phase-{5..10,12}-code-examples.md
└── reference/ # Technical reference
├── tech-stack.md
├── directory-structure.md
├── budgets-guardrails.md
├── portfolio-checklist.md
├── optional-analytics.md
└── table-format-guide.md
└── adr/ # Numbered ADRs through 062
├── README.md
├── template.md
├── 000-starter-decisions.md
└── # 001 … 062
├── src/
├── assets/
├── brand/ # Brand SVGs
├── fonts/ # Self-hosted woff2 (Astro Fonts API)
├── icons/ # SVG icon sources
└── logo.svg # Project logo
├── components/
├── atoms/ # Badge, Button, Icon, Image, ThemeToggle, …
├── molecules/ # Card, ContactForm, Dialog, Head, Tabs, …
├── structural/ # Container, Section, Grid, Header, Footer, …
├── islands/ # Preact islands (SignalsCounter, MotionLab)
├── mdx/ # MDX component set (Callout, Figure, …)
├── a11y/ # SkipLink
├── ThemeSetup.astro # Theme initialization
└── CLAUDE.md # Component guidelines
├── content.config.ts # Content Layer collection schemas
├── content/
├── bio/ # Bio/profile content
├── blog/ # Blog posts (four examples)
├── experience/ # Experience entries
├── navigation/ # Nav data (header.json, …)
└── projects/ # Portfolio projects
├── layouts/
├── BaseLayout.astro # Complete base layout
├── BlogLayout.astro
└── ProjectLayout.astro
├── pages/
├── index.astro # Homepage
├── about.astro, contact.astro, how-it-works.astro, showcase.astro
├── blog/, projects/, adr/ # Route directories ([slug] + index)
├── robots.txt.ts # robots.txt generated at build time
├── rss.xml.ts # RSS feed route
├── 404.astro
└── 500.astro
├── styles/
└── global.css # With token integration
├── types/
├── astro-content.d.ts # Generated types
├── content.ts # Shared content schemas
├── icons.ts
└── navigation.ts # Navigation types
├── utils/ # blog, formatDate, url-utils, …
└── config.ts # Site config
├── public/
├── _headers # Security headers
├── favicon.svg, favicon.ico, apple-touch-icon.png
├── og-*.png, og-*.svg # Open Graph images
├── logo.svg
└── site.webmanifest
├── scripts/
├── src/ # Script source files
├── build-tokens.ts # Token builder
├── validate-contrast.ts # Contrast validator
├── track-performance-budgets.ts # Budget tracking
└── # OG builder, gates, remark plugins
└── tsconfig.json # Scripts TypeScript config
├── tokens/
├── base.json # Complete token set
├── semantic.json
└── dist/ # Git-ignored
├── e2e/ # Playwright specs (9 page suites)
├── .devcontainer/ # Dev container config
├── .claude/ # AI constitution layers
├── .husky/ # pre-commit, commit-msg, pre-push hooks
├── .commitlintrc.cjs # Commit message linting
├── .editorconfig # Editor settings
├── .env.example # Environment template
├── .gitignore # Comprehensive ignore
├── .lintstagedignore # Lint staged ignore
├── .nvmrc # Node version
├── .windsurfrules # Windsurf overlay (thin; see AGENTS.md)
├── AGENTS.md # Generated agent instructions
├── CLAUDE.md # AI constitution
├── CHANGELOG.md # Release notes
├── CONTRIBUTING.md # Contribution guide
├── README.md # Project overview
├── SECURITY.md # Security policy
├── LICENSE.txt # MIT license
├── astro.config.mjs # Framework config
├── biome.json # Complete config
├── budget-overrides.json # Example overrides
├── budgets.json # Raw-size performance budgets
├── ec.config.mjs # Expressive Code config
├── lighthouserc.json # Lighthouse CI (desktop)
├── lighthouserc.mobile.json # Lighthouse CI (mobile)
├── package.json # All deps, no fluff
├── playwright.config.ts # E2E config
├── pnpm-lock.yaml # Lockfile
├── stryker.conf.json # Mutation testing config
├── tsconfig.json # Strict mode
├── versions.json # Public version manifest (ADR-061)
└── vitest.config.ts # Testing config
src/components/
├── atoms/ # Basic UI building blocks
│ ├── Button.astro # Interactive elements
│ ├── Badge.astro # Status/label badges
│ ├── Icon.astro # SVG icons
│ ├── Image.astro # Optimized images (astro:assets)
│ ├── ThemeToggle.astro # Light/dark switch
│ ├── Tooltip.astro
│ └── … # SocialLink, ScrollReveal, ReadingProgress, …
├── molecules/ # Simple component combinations
│ ├── Card.astro # Content cards
│ ├── ContactForm.astro # Complete contact form
│ ├── Dialog.astro # Modal dialog
│ ├── Head.astro # Document head (meta, fonts, OG)
│ ├── Tabs.astro
│ ├── PostCard.astro / ProjectCard.astro
│ └── … # ScrollSpy, SectionSeparator, TypeSpecimen, …
├── structural/ # Layout and positioning
│ ├── Container.astro # Content width constraints
│ ├── Section.astro # Semantic page sections
│ ├── Grid.astro # Layout grids
│ ├── Header.astro # Site header
│ ├── Footer.astro # Site footer
│ └── ParallaxSection.astro
├── islands/ # Preact islands (client-side state)
│ ├── SignalsCounter.tsx
│ └── MotionLab.tsx
├── mdx/ # Content-specific components
│ ├── Callout.astro # Information boxes
│ ├── Figure.astro # Images with captions
│ ├── Grid.astro, Blockquote.astro, Link.tsx, CodeFromFile.astro
│ └── index.ts # MDX component map
└── a11y/ # Accessibility helpers
└── SkipLink.astro

There is no organisms/ directory — complex page sections are composed in pages from structural/ and molecules/ components.

// File naming: PascalCase
Button.astro
HeroSection.astro
NavigationMenu.astro
// Component exports: Match filename
export default Button;
export default HeroSection;
export default NavigationMenu;
// Props interface: ComponentProps
interface ButtonProps {
variant?: 'primary' | 'secondary';
size?: 'sm' | 'md' | 'lg';
}
interface HeroSectionProps {
title: string;
subtitle?: string;
backgroundImage?: string;
}

Pre-configured path aliases for clean imports:

// Available aliases
import Button from '@components/atoms/Button.astro';
import { formatDate } from '@utils/date-utils';
import { siteConfig } from '@/config';
import heroImage from '@assets/hero.jpg';
import BaseLayout from '@layouts/BaseLayout.astro';
import type { NavigationItem } from '@types/navigation';
// tsconfig.json configuration
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"],
"@utils/*": ["src/utils/*"],
"@styles/*": ["src/styles/*"],
"@types/*": ["src/types/*"],
"@assets/*": ["src/assets/*"],
"@content/*": ["src/content/*"]
}
}
}
src/content.config.ts # Collection schemas (Content Layer, at src root)
src/content/
├── blog/ # Blog posts (directories per post)
├── projects/ # Portfolio items
├── bio/ # Bio/profile content
├── experience/ # Experience entries
└── navigation/ # Nav data (header.json, …)
# A sixth collection, `adr`, loads from docs/adr/ (outside src/content/)
# via a glob() loader and powers the /adr/ routes.
// Schema definition pattern (src/content.config.ts — Content Layer)
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.date(),
author: z.string().optional(),
tags: z.array(z.string()).optional(),
draft: z.boolean().default(false),
}),
});
// Usage pattern — entries are keyed by `id`, not `slug`
import { getCollection, getEntry } from 'astro:content';
const allPosts = await getCollection('blog');
const post = await getEntry('blog', 'example-post');
Performance Strategy:
images:
location: src/assets/ (processed) | public/ (static)
formats: AVIF → WebP → JPEG fallback
optimization: Automatic via Astro Image component
fonts:
source: Astro Fonts API, fontProviders.local() (woff2 vendored in src/assets/fonts/)
format: WOFF2 variable fonts preferred
loading: metric-adjusted fallbacks generated by Astro (cuts CLS)
icons:
format: SVG inline (< 2KB) or sprite
optimization: SVGO processing
scripts:
bundling: Vite automatic code splitting
islands: Lazy loaded via client directives
critical: Inlined via is:inline (sparingly)
Terminal window
dist/ # Generated at build time
├── _astro/ # Hashed JS/CSS/image assets
├── index.abc123.js
├── index.def456.css
└── hero.ghi789.avif
├── index.html # Static HTML at route directories
├── about/, blog/, projects/, adr/,
├── 404.html
├── robots.txt # Emitted by src/pages/robots.txt.ts
└── _headers # Deployment headers
Terminal window
# New component workflow
1. Create component file: src/components/atoms/NewButton.astro
2. Add to appropriate category (atoms/molecules/structural/islands)
3. Export component with proper TypeScript props
4. Document usage per src/components/CLAUDE.md guidelines
5. Add to component index if needed
# New content workflow
1. Define schema in src/content.config.ts
2. Create collection directory: src/content/[collection]/
3. Add content files with proper frontmatter
4. Test with pnpm run check
5. Build and validate output
  • Directories: kebab-case (e.g., hero-section/)
  • Components: PascalCase.astro (e.g., HeroSection.astro)
  • Utilities: camelCase.ts (e.g., formatDate.ts)
  • Content: kebab-case.mdx (e.g., getting-started.mdx)
  • Types: camelCase.ts or descriptive names (e.g., navigation.ts)
Critical Files:
astro.config.mjs: # Framework configuration
- integrations (MDX, Sitemap, Preact)
- Tailwind v4 via the @tailwindcss/vite plugin
- build settings
- deployment config
src/styles/global.css: # Design system integration (Tailwind v4 CSS-first)
- imports tokens/dist/tokens.css
- maps tokens to utilities via @theme inline
- dark mode @variant
tsconfig.json: # TypeScript configuration
- strict mode enabled
- path aliases
- content collections types
biome.json: # Code quality
- linting rules
- formatting preferences
- import organization

This directory structure is enforced by ADR-003: Unified Component Structure, which establishes:

  • Atomic Design as the mandatory component organization pattern
  • Import alias requirements for clean code
  • Component placement rules and exceptions
  • Migration guidelines for existing projects
  1. Explore components: Start with src/components/CLAUDE.md
  2. Review patterns: Check common patterns
  3. Understand content: Read content collections
  4. Learn islands: Study islands architecture
  5. Performance focus: Review budgets & guardrails

This structure provides a scalable foundation that grows with your project while maintaining performance, accessibility, and developer experience as core principles.