Astro Installation Guide

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 or Next.js, offering Islands architecture, zero JavaScript by default, and support for multiple UI frameworks including React, Vue, and Svelte in the same project.

Development tools🟡 intermediate12 min⏱️ 10-20 minutes

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

  • CPU: Modern processor (1+ cores)
  • RAM: 512MB minimum (2GB+ recommended)
  • Storage: 250MB for Astro and dependencies
  • Network: Internet connection for package installation
  • Software Requirements

  • Node.js: 18.14.1+ or 20.3.0+
  • Package Manager: npm, yarn, or pnpm
  • Text Editor: VS Code recommended with Astro extension
  • Optional: Git for version control
  • Network Requirements

  • HTTPS: Access to npm registry
  • Ports:
  • 4321: Default dev server port
  • 3000: Common alternative port
  • 2. Supported Operating Systems

    Astro officially supports:

  • RHEL 8/9 and derivatives (CentOS Stream, Rocky Linux, AlmaLinux)
  • Debian 11/12
  • Ubuntu 20.04 LTS / 22.04 LTS / 24.04 LTS
  • Arch Linux
  • Alpine Linux 3.18+
  • openSUSE Leap 15.5+ / Tumbleweed
  • Fedora 38+
  • macOS 10.15+ (Catalina and later)
  • Windows 10/11
  • 3. Installation

    #### Using npm

    bash
    # 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

    bash
    # Create new Astro project
    yarn create astro
    
    # Navigate and start
    cd my-astro-site
    yarn
    yarn dev

    #### Using pnpm

    bash
    # 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

    bash
    # 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

    bash
    # 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

    bash
    # 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

    bash
    # 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

    bash
    # 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

    bash
    # Using Homebrew
    brew install node
    
    # Install pnpm
    brew install pnpm
    
    # Create Astro project
    pnpm create astro@latest
    cd my-astro-site
    pnpm dev

    #### Windows

    powershell
    # 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

    bash
    # 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:

    javascript
    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:

    json
    {
      "extends": "astro/tsconfigs/strict",
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"],
          "@components/*": ["src/components/*"],
          "@layouts/*": ["src/layouts/*"],
          "@assets/*": ["src/assets/*"]
        }
      }
    }

    Environment Variables

    Create .env:

    bash
    # 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:

    javascript
    // 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:

    typescript
    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

    bash
    # 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

    bash
    # 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

    bash
    # 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:

    ini
    [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

    dockerfile
    # 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:

    bash
    # 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:

    bash
    # 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:

    javascript
    // 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:

    bash
    # 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

    bash
    # 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

    javascript
    // 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

    bash
    # 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

    javascript
    // Remove console logs in production
    export default defineConfig({
      vite: {
        build: {
          terserOptions: {
            compress: {
              drop_console: true,
              drop_debugger: true
            }
          }
        }
      }
    });

    8. Performance Tuning

    Build Optimization

    javascript
    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

    astro
    ---
    // 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

    javascript
    // 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

    bash
    #!/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

    bash
    # 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

  • CPU: 1 core
  • RAM: 512MB
  • Storage: 250MB
  • Node.js: 18.14.1+
  • CPU: 2+ cores
  • RAM: 2GB+
  • Storage: 1GB+ SSD
  • Node.js: 20+ LTS
  • Large Site Requirements

  • CPU: 4+ cores
  • RAM: 8GB+
  • Storage: 10GB+ NVMe
  • Build Cache: 2GB+
  • 11. Support

    Official Resources

  • Website: https://astro.build
  • GitHub: https://github.com/withastro/astro
  • Documentation: https://docs.astro.build
  • Discord: https://astro.build/chat
  • Community Support

  • Discord Server: Very active community
  • GitHub Discussions: https://github.com/withastro/astro/discussions
  • Stack Overflow: [astro] tag
  • Twitter/X: @astrodotbuild
  • 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

    bash
    # 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:

  • Free to use, modify, and distribute
  • Commercial use allowed
  • No warranty provided
  • Attribution required
  • 14. Acknowledgments

    Credits

  • Fred K. Schott: Creator and lead developer
  • Astro Technology Company: Core team
  • Contributors: 500+ contributors
  • Sponsors: GitHub sponsors and corporate backers
  • 15. Version History

    Recent Releases

  • v4.x: View Transitions API, Content Layer API
  • v3.x: Image optimization, improved performance
  • v2.x: Content Collections, Hybrid rendering
  • Major Features by Version

  • v4.0: Faster builds, Dev toolbar, i18n routing
  • v3.0: View transitions, Image component
  • v2.0: Content collections, Error overlays
  • 16. Appendices

    A. Basic Site Example

    astro
    ---
    // 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

    javascript
    // 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

    astro
    ---
    // 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

    bash
    #!/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