Astro Standards
Architecture
- •Server-first by default — zero client JS unless explicitly needed
- •Islands architecture: interactive components are opt-in exceptions, not the norm
- •Static pages for content, server endpoints for dynamic data
- •Prefer
.astrocomponents over framework components when no interactivity needed
Client Directives (hydration)
- •
client:load— interactive immediately on page load (modals, nav menus) - •
client:idle— interactive after page idle (below-fold widgets) - •
client:visible— interactive when scrolled into viewport (counters, carousels) - •
client:only="react"— client-render only, skip SSR (browser-only APIs) - •NEVER add
client:*to a component that doesn't need interactivity - •Prefer
client:visibleorclient:idleoverclient:loadfor performance
Content Collections
- •Define schemas in
src/content.config.tsusing Zod viaastro/zod - •ALWAYS validate with
defineCollection+z.object({})— NEVER untyped frontmatter - •Use
reference()for cross-collection relationships - •Loaders:
glob()for file-based,file()for single-file data sources - •Query with
getCollection()/getEntry()— NEVER raw file reads
typescript
import { defineCollection, reference } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
author: reference('authors'),
}),
});
Components
- •Frontmatter (
---) for server-only logic: imports, data fetching, props - •Props typed via
Astro.propswith explicit interface - •Slots for composition: named slots for complex layouts
- •NEVER put side effects in frontmatter — it runs at build/request time
Pages & Routing
- •File-based routing in
src/pages/ - •Dynamic routes:
[slug].astrowithgetStaticPaths()for static - •API routes:
.tsfiles insrc/pages/api/returningResponseobjects - •Prefer static generation (
output: 'static') unless SSR is required
Styling
- •Scoped
<style>blocks in.astrofiles by default - •Tailwind for utility classes when configured
- •
is:globalonly when scoped styles genuinely can't work - •CSS custom properties for theming across components