Astro is a free and open-source all-in-one web framework for building fast, content-focused websites. It serves as a FOSS alternative to static site generators like Gatsby, Next.js static export, or Hugo, offering innovative features like Islands architecture, zero JavaScript by default, and first-class support for multiple UI frameworks including React, Vue, Svelte, and more - all in the same project.
1. Prerequisites
Hardware Requirements
Software Requirements
Network Requirements
2. Supported Operating Systems
Astro officially supports:
3. Installation
Method 1: Create New Project (Recommended)
#### Using npm
# Create new Astro project
npm create astro@latest
# Follow the prompts:
# - Where should we create your new project? ./my-astro-site
# - How would you like to start your new project? (Choose template)
# - Install dependencies? Yes
# - TypeScript? Yes (Recommended)
# - How strict? Strict
# Navigate to project
cd my-astro-site
# Start development server
npm run dev
#### Using yarn
# Create new Astro project
yarn create astro
# Navigate and start
cd my-astro-site
yarn
yarn dev
#### Using pnpm
# Create new Astro project
pnpm create astro@latest
# Navigate and start
cd my-astro-site
pnpm install
pnpm dev
Method 2: Manual Installation
#### RHEL/CentOS/Rocky Linux/AlmaLinux
# Install Node.js
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
# Create project directory
mkdir my-astro-site && cd my-astro-site
# Initialize package.json
npm init -y
# Install Astro
npm install astro
# Create Astro config
cat > astro.config.mjs << 'EOF'
import { defineConfig } from 'astro/config';
export default defineConfig({
// Configuration options
});
EOF
# Create source directory structure
mkdir -p src/pages src/components src/layouts
#### Debian/Ubuntu
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install pnpm (recommended for Astro)
npm install -g pnpm
# Create Astro project
pnpm create astro@latest my-astro-site
cd my-astro-site
pnpm dev
#### Arch Linux
# Install Node.js and pnpm
sudo pacman -S nodejs npm pnpm
# Create Astro project
pnpm create astro@latest my-astro-site
cd my-astro-site
pnpm dev
#### Alpine Linux
# Install Node.js and npm
apk add --no-cache nodejs npm
# Install pnpm globally
npm install -g pnpm
# Create Astro project
pnpm create astro@latest
cd my-astro-site
pnpm install
pnpm dev
#### openSUSE
# Install Node.js
sudo zypper install -y nodejs20 npm20
# Create Astro project
npm create astro@latest
cd my-astro-site
npm install
npm run dev
#### macOS
# Using Homebrew
brew install node
# Install pnpm
brew install pnpm
# Create Astro project
pnpm create astro@latest
cd my-astro-site
pnpm dev
#### Windows
# Using winget
winget install OpenJS.NodeJS
# Or using Chocolatey
choco install nodejs
# Create Astro project
npm create astro@latest
cd my-astro-site
npm run dev
Method 3: Clone Starter Templates
# Official Blog template
git clone https://github.com/withastro/astro/tree/main/examples/blog my-blog
cd my-blog
npm install
npm run dev
# Portfolio template
git clone https://github.com/withastro/astro/tree/main/examples/portfolio my-portfolio
# Documentation template
git clone https://github.com/withastro/astro/tree/main/examples/docs my-docs
# E-commerce template
git clone https://github.com/withastro/astro/tree/main/examples/ecommerce my-shop
4. Configuration
Basic Configuration
Create astro.config.mjs
:
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
// Site URL (required for sitemap)
site: 'https://example.com',
// Base path for GitHub Pages
base: '/my-repo',
// Output mode
output: 'static', // 'static' | 'server' | 'hybrid'
// Integrations
integrations: [
react(),
tailwind(),
mdx(),
sitemap()
],
// Server options
server: {
port: 3000,
host: true
},
// Build options
build: {
format: 'directory', // 'file' | 'directory'
assets: '_astro'
},
// Markdown options
markdown: {
shikiConfig: {
theme: 'dracula',
wrap: true
}
},
// Vite configuration
vite: {
optimizeDeps: {
exclude: ['@astrojs/lit']
}
}
});
TypeScript Configuration
Create tsconfig.json
:
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"],
"@assets/*": ["src/assets/*"]
}
}
}
Environment Variables
Create .env
:
# Public variables (exposed to client)
PUBLIC_API_URL=https://api.example.com
PUBLIC_SITE_NAME="My Astro Site"
# Private variables (server-side only)
DATABASE_URL=postgresql://user:pass@localhost:5432/db
API_SECRET=your-secret-key
Access in Astro:
// In .astro files
const apiUrl = import.meta.env.PUBLIC_API_URL;
const dbUrl = import.meta.env.DATABASE_URL; // Server-side only
// In client-side scripts
console.log(import.meta.env.PUBLIC_API_URL); // Works
console.log(import.meta.env.DATABASE_URL); // undefined
Content Collections
Create src/content/config.ts
:
import { z, defineCollection } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.date(),
author: z.string(),
tags: z.array(z.string()).optional(),
image: z.string().optional(),
draft: z.boolean().default(false)
})
});
const authorsCollection = defineCollection({
type: 'data',
schema: z.object({
name: z.string(),
bio: z.string(),
avatar: z.string(),
social: z.object({
twitter: z.string().optional(),
github: z.string().optional()
})
})
});
export const collections = {
blog: blogCollection,
authors: authorsCollection
};
5. Service Management
Development Server
# Start development server
npm run dev
astro dev
# Start with custom host/port
astro dev --host 0.0.0.0 --port 3000
# Start with verbose logging
astro dev --verbose
# Expose to network
astro dev --host
# Enable experimental features
npm run dev -- --experimental-integrations
Production Build
# Build static site
npm run build
astro build
# Preview production build
npm run preview
astro preview --port 8080
# Check for issues
astro check
# Build with verbose output
astro build --verbose
Server-Side Rendering (SSR) Deployment
#### Node.js Adapter
# Install Node adapter
npm install @astrojs/node
# Configure in astro.config.mjs
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
})
});
# Build and run
npm run build
node ./dist/server/entry.mjs
#### Systemd Service
Create /etc/systemd/system/astro-app.service
:
[Unit]
Description=Astro SSR Application
After=network.target
[Service]
Type=simple
User=astro
Group=astro
WorkingDirectory=/opt/astro-app
ExecStart=/usr/bin/node /opt/astro-app/dist/server/entry.mjs
Restart=always
RestartSec=3
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=HOST=0.0.0.0
[Install]
WantedBy=multi-user.target
Docker Deployment
# Multi-stage build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Static hosting
FROM nginx:alpine AS static
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# SSR hosting
FROM node:20-alpine AS ssr
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --production
EXPOSE 3000
CMD ["node", "./dist/server/entry.mjs"]
6. Troubleshooting
Common Issues
1. Build failures:
# Clear cache
rm -rf .astro node_modules/.vite
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# Check TypeScript errors
npx astro check
# Increase memory for large sites
NODE_OPTIONS="--max-old-space-size=4096" npm run build
2. 404 errors in development:
# Check file extensions
# Astro requires .astro extension for pages
# Verify routing
npx astro info
# Check for conflicting routes
find src/pages -name "*.astro" | sort
3. Integration conflicts:
// Fix order of integrations
export default defineConfig({
integrations: [
// Order matters for some integrations
mdx(), // Should come before others that process markdown
react(),
tailwind()
]
});
4. Image optimization issues:
# Install sharp for better image processing
npm install sharp
# Clear image cache
rm -rf node_modules/.astro
# Use explicit dimensions
<Image src={myImage} width={800} height={600} alt="Description" />
Debug Mode
# Enable debug logging
DEBUG=astro:* npm run dev
# Specific debug namespaces
DEBUG=astro:build npm run build
DEBUG=astro:assets npm run dev
DEBUG=vite:* npm run dev
# Verbose build output
astro build --verbose
7. Security Considerations
Content Security Policy
// astro.config.mjs
export default defineConfig({
integrations: [
{
name: 'csp-headers',
hooks: {
'astro:server:setup': ({ server }) => {
server.middlewares.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
);
next();
});
}
}
}
]
});
Environment Security
# Never commit .env with secrets
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
echo ".env.production" >> .gitignore
# Use environment-specific files
.env.development # Development variables
.env.production # Production variables
.env.local # Local overrides (gitignored)
Build Security
// Remove console logs in production
export default defineConfig({
vite: {
build: {
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}
}
});
8. Performance Tuning
Build Optimization
export default defineConfig({
build: {
// Inline small CSS
inlineStylesheets: 'auto',
// Split vendor chunks
splitting: true,
// Exclude large dependencies
excludeMiddleware: false
},
// Compress output
compressHTML: true,
// Optimize images
image: {
service: 'sharp',
config: {
limitInputPixels: false
}
},
// Prefetch links
prefetch: {
defaultStrategy: 'viewport',
prefetchAll: true
}
});
Component Islands Optimization
---
// Only hydrate when visible
---
<InteractiveComponent client:visible />
<!-- Load JavaScript when idle -->
<HeavyComponent client:idle />
<!-- Load on media query -->
<MobileComponent client:media="(max-width: 768px)" />
<!-- Never hydrate (static only) -->
<StaticComponent />
Caching Strategy
// Service worker for offline support
export default defineConfig({
integrations: [
{
name: 'service-worker',
hooks: {
'astro:build:done': async ({ dir }) => {
// Generate service worker
}
}
}
]
});
9. Backup and Restore
Project Backup
#!/bin/bash
# backup-astro-project.sh
PROJECT_DIR="/opt/astro-app"
BACKUP_DIR="/var/backups/astro"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup source files
tar -czf $BACKUP_DIR/astro_source_$DATE.tar.gz \
-C $PROJECT_DIR \
--exclude='node_modules' \
--exclude='dist' \
--exclude='.astro' \
.
# Backup built site
if [ -d "$PROJECT_DIR/dist" ]; then
tar -czf $BACKUP_DIR/astro_dist_$DATE.tar.gz -C $PROJECT_DIR/dist .
fi
# Backup content
tar -czf $BACKUP_DIR/astro_content_$DATE.tar.gz -C $PROJECT_DIR/src/content .
echo "Backup completed: $BACKUP_DIR"
Content Migration
# Export content to JSON
cat > export-content.js << 'EOF'
import { getCollection } from 'astro:content';
import fs from 'fs/promises';
const blog = await getCollection('blog');
await fs.writeFile(
'blog-export.json',
JSON.stringify(blog, null, 2)
);
EOF
node export-content.js
10. System Requirements
Minimum Requirements
Recommended Requirements
Large Site Requirements
11. Support
Official Resources
Community Support
12. Contributing
How to Contribute
1. Fork the repository on GitHub
2. Create a feature branch
3. Submit pull request
4. Follow TypeScript coding standards
5. Include tests and changeset
Development Setup
# Clone repository
git clone https://github.com/withastro/astro.git
cd astro
# Install dependencies
pnpm install
# Build packages
pnpm build
# Run tests
pnpm test
# Create changeset
pnpm changeset
13. License
Astro is licensed under the MIT License.
Key points:
14. Acknowledgments
Credits
15. Version History
Recent Releases
Major Features by Version
16. Appendices
A. Basic Site Example
---
// src/pages/index.astro
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
const posts = await Astro.glob('../content/blog/*.md');
---
<Layout title="Welcome to Astro">
<main>
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
<ul role="list" class="link-card-grid">
{posts.map((post) => (
<Card
href={post.url}
title={post.frontmatter.title}
body={post.frontmatter.description}
/>
))}
</ul>
</main>
</Layout>
<style>
.text-gradient {
background-image: linear-gradient(45deg, #4f39fa, #da62c4);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
B. API Routes Example
// src/pages/api/posts.json.js
export async function GET() {
const posts = await getCollection('blog');
return new Response(
JSON.stringify(posts),
{
status: 200,
headers: {
"Content-Type": "application/json"
}
}
);
}
// src/pages/api/contact.js
export async function POST({ request }) {
const data = await request.json();
// Process form submission
await sendEmail(data);
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: {
"Content-Type": "application/json"
}
});
}
C. Multi-Framework Example
---
// Using multiple frameworks in one page
import ReactCounter from '../components/Counter.jsx';
import VueAlert from '../components/Alert.vue';
import SvelteTimer from '../components/Timer.svelte';
---
<Layout>
<h1>Multi-Framework Demo</h1>
<!-- React component -->
<ReactCounter client:load />
<!-- Vue component -->
<VueAlert message="Hello from Vue!" client:visible />
<!-- Svelte component -->
<SvelteTimer client:idle />
</Layout>
D. Deployment Scripts
#!/bin/bash
# deploy.sh
# Build site
npm run build
# Deploy to Netlify
netlify deploy --prod --dir=dist
# Deploy to Vercel
vercel --prod
# Deploy to GitHub Pages
npm run build -- --base=/repo-name
gh-pages -d dist
# Deploy to S3
aws s3 sync dist/ s3://my-bucket --delete
aws cloudfront create-invalidation --distribution-id ABCD --paths "/*"
---
For more information and updates, visit https://github.com/howtomgr/astro