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 # Working CI pipeline
├── FUNDING.yml # Optional sponsorship
└── ISSUE_TEMPLATE/
├── bug_report.md
└── phase_completion.md
├── docs/
├── README.md # Docs overview & navigation
├── implementation-guides/ # Development guides
├── README.md # Implementation roadmap
├── completed/ # Foundation phases (0-4)
├── phase-0-foundation.md
├── phase-1-content.md
├── phase-2-design.md
├── phase-3-performance.md
└── phase-4-quality.md
├── active-phases/ # Current development (5-12)
├── phase-5-components.md # ← AI starting point
├── phase-6-sections.md # (not started)
├── phase-7-pages.md
├── phase-8-features.md
├── phase-9-optimization.md
├── phase-10-deployment.md
├── phase-11-monitoring.md
└── phase-12-maintenance.md
├── guides/ # Topic-specific guides
├── accessibility.md
├── components.md
├── content-model.md
└── testing.md
├── code-examples/ # Implementation examples
├── component-patterns/
├── content-collections/
└── performance-patterns/
├── reference/ # Technical reference
├── tech-stack.md
├── directory-structure.md
└── budgets-guardrails.md
└── tracks/ # Implementation tracks
├── mvp-track.md
└── showcase-track.md
└── adr/
├── template.md
└── 001-starter-decisions.md
├── src/ # Minimal implementation
├── assets/
└── logo.svg # Project logo
├── components/
├── atoms/
└── Button.astro # One example component
├── structural/
├── Container.astro
└── Section.astro
└── README.md # Component guidelines
├── content/
├── config.ts # Full schema setup
├── docs/ # Starlight docs content
└── blog/
└── example-post.mdx # One example
├── layouts/
├── BaseLayout.astro # Complete base layout
└── partials/
├── Header.astro
└── Footer.astro
├── pages/
├── index.astro # Minimal homepage
└── 404.astro
├── styles/
└── global.css # With token integration
├── types/
├── astro-content.d.ts # Generated types
└── navigation.ts # Navigation types
└── utils/
└── url-utils.ts # Example utility
├── public/
├── _headers # Security headers
├── favicon.svg
└── robots.txt
├── scripts/
├── src/ # Script source files
├── build-tokens.ts # Working token builder
├── validate-contrast.ts # Working validator
├── baseline-performance.ts # Performance baseline
└── track-performance-budgets.ts # Budget tracking
└── tsconfig.json # Scripts TypeScript config
├── tokens/
├── base.json # Complete token set
├── semantic.json
└── dist/ # Git-ignored
├── .vscode/
├── extensions.json # Recommended extensions
└── settings.json # Project settings
├── .husky/
└── pre-commit # Working git 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 AI rules
├── CHANGELOG.md # Release notes
├── CONTRIBUTING.md # Contribution guide
├── ONBOARDING.md # Quick start guide
├── README.md # Project overview
├── LICENSE.txt # MIT license
├── airules.example # AI rules template
├── astro.config.mjs # Minimal config
├── biome.json # Complete config
├── budget-overrides.json # Example overrides
├── package.json # All deps, no fluff
├── pnpm-lock.yaml # Lockfile
├── tailwind.config.ts # Token integration
├── tsconfig.json # Strict mode
└── vitest.config.ts # Testing config
src/components/
├── atoms/ # Basic UI building blocks
│ ├── Button.astro # Interactive elements
│ ├── Input.astro # Form controls
│ ├── Icon.astro # SVG icons
│ └── Link.astro # Navigation links
├── molecules/ # Simple component combinations
│ ├── Card.astro # Content cards
│ ├── FormField.astro # Input + label + validation
│ ├── Navigation.astro # Link lists
│ └── SearchBox.astro # Input + button
├── organisms/ # Complex page sections
│ ├── Header.astro # Site header
│ ├── Hero.astro # Hero sections
│ ├── ArticleList.astro # Content listings
│ └── ContactForm.astro # Complete forms
├── structural/ # Layout and positioning
│ ├── Container.astro # Content width constraints
│ ├── Section.astro # Semantic page sections
│ ├── Grid.astro # Layout grids
│ └── Stack.astro # Vertical spacing
└── mdx/ # Content-specific components
├── CodeBlock.astro # Syntax highlighted code
├── Callout.astro # Information boxes
└── Figure.astro # Images with captions
// 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
├── blog/ # Blog posts
│ ├── 2024-01-01-example.mdx
│ └── index.ts # Collection exports
├── projects/ # Portfolio items
│ ├── project-one.mdx
│ └── index.ts
└── docs/ # Documentation (Starlight)
├── getting-started/
├── implementation-guides/
└── patterns/
// Schema definition pattern
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
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
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: @fontsource packages (self-hosted)
format: WOFF2 variable fonts preferred
loading: font-display: swap
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
├── assets/ # Hashed assets
├── index-abc123.js
├── index-def456.css
└── hero-ghi789.avif
├── _astro/ # Astro runtime assets
├── pages/ # Static HTML files
└── _headers # Deployment headers
Terminal window
# New component workflow
1. Create component file: src/components/atoms/NewButton.astro
2. Add to appropriate category (atoms/molecules/organisms)
3. Export component with proper TypeScript props
4. Document usage in component README or Astrobook
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 (Tailwind, MDX, Sitemap)
- build settings
- deployment config
tailwind.config.ts: # Design system integration
- design token imports
- custom utilities
- component styles
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/README.md
  2. Review patterns: Check /implementation-guides/patterns/
  3. Understand content: Read /implementation-guides/patterns/content-collections/
  4. Learn islands: Study /implementation-guides/patterns/islands-architecture/
  5. Performance focus: Review /implementation-guides/00-overview/budgets-guardrails/

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