Astro Hybrid Project Structure
SSR + static pages with island components. React, Vue, or Svelte islands.
Project Directory
my-app/
src/
components/
Header.astro
Footer.astro
islands/
Interactive components
Counter.tsx
React island
Search.tsx
Client-side search
ThemeToggle.tsx
content/
blog/
post.mdx
config.ts
layouts/
Base.astro
App.astro
App shell
lib/
Shared utilities
api.ts
API client
auth.ts
Auth helpers
pages/
index.astro
Static home
about.astro
Static page
blog/
[...slug].astro
dashboard/
SSR routes
index.astro
Server-rendered
settings.astro
api/
API endpoints
auth.ts
Login/logout
data.ts
Data endpoint
middleware.ts
Auth middleware
styles/
global.css
public/
favicon.svg
astro.config.mjs
output: hybrid
package.json
tsconfig.json
.env
API keys, secrets
.env.example
.gitignore
Why This Structure?
Hybrid mode (output: 'hybrid') pre-renders pages by default while allowing SSR opt-in. Island components hydrate interactively with client:* directives. API routes in src/pages/api/ run server-side. Best of both worlds.
Key Directories
- src/components/islands/-React/Vue components that hydrate
- src/pages/dashboard/-SSR pages with
export const prerender = false - src/pages/api/-Server endpoints (
.tsfiles) - src/middleware.ts-Runs before every request
Island Directives
- client:load-Hydrate immediately on page load
- client:idle-Hydrate when browser is idle
- client:visible-Hydrate when scrolled into view
- client:only-Skip SSR, render client-only
Getting Started
npm create astro@latest my-app
npx astro add react
# Set output: 'hybrid' in config
npm run dev
When To Use This
- Mix of static content and dynamic features
- Dashboards with public marketing pages
- Apps needing auth-protected SSR routes
- Sites with isolated interactive widgets
Trade-offs
- Server required-Deploy to Node/edge runtime
- Multiple frameworks-Bundle size per island framework
- Complexity-More moving parts than static-only