Skip to content

Quick Deploy

Ready to make the template your own and deploy to production? This guide walks you through personalization, deployment, and verification in under an hour.

Prerequisites: You should have completed the Launch Demo and have the site running locally.

Before starting this guide, ensure you have:

  • Completed Launch Demo successfully
  • Site runs locally without errors (pnpm run dev)
  • No console errors in browser (F12 → Console)
  • pnpm run build succeeds locally
  • Git basics understood (commit, push, remote)
  • Hosting platform account created (or will create during guide)

Why this matters: Deploying a broken local site wastes time. Fix issues locally first.

Test your local build:

Terminal window
pnpm run preview # Builds and serves production build locally

Open http://localhost:4321 - if this works, you’re ready to deploy.

Time Required: 45-75 minutes (first-time users)

Section titled “Time Required: 45-75 minutes (first-time users)”
  • Site personalized with your branding
  • Deployed to production
  • Live at your custom URL
  • Verified and tested
  • Completed Launch Demo - Local site running successfully
  • GitHub account (sign up)
  • Hosting platform account (see Platform Selection below)
  • Basic Git knowledge (commit, push)

Choose your hosting platform before starting:

PlatformBest ForFree TierSetup TimeAuto HTTPSRecommendation
Cloudflare PagesPerformance, global CDNUnlimited sites10-15 min✅ InstantBest for most
VercelNext.js ecosystem, teams100GB/month10-15 min✅ InstantGreat for existing Vercel users
NetlifyForms, split testing, CMS100GB/month10-15 min✅ InstantGood for marketing sites

When you run pnpm run build (or pnpm run build:full), here’s what happens:

  1. Token Compilation (build:tokens)

    • Reads tokens/base.json and tokens/semantic.json
    • Generates CSS custom properties
    • Outputs to src/styles/tokens.css
  2. Astro Build (astro build)

    • Compiles .astro components to HTML
    • Bundles JavaScript (only interactive islands)
    • Optimizes CSS (removes unused styles)
    • Processes images (AVIF + WebP)
    • Generates sitemap
  3. Output (dist/)

    • Static HTML files
    • Optimized assets (CSS, JS, images)
    • Public files (favicon, fonts, etc.)

The dist/ folder is what gets deployed - not your source code.

Copy this into your notes and check off as you go:

- [ ] Prerequisites verified
- [ ] Platform account created
- [ ] Repository created on GitHub
- [ ] Site configuration updated
- [ ] Metadata personalized
- [ ] Favicons replaced
- [ ] Design tokens customized (optional)
- [ ] Changes committed to Git
- [ ] Pushed to GitHub
- [ ] Connected to hosting platform
- [ ] Build successful
- [ ] Live site verified
- [ ] Mobile tested

🎨 Step 1: Personalize Your Site (20-30 min)

Section titled “🎨 Step 1: Personalize Your Site (20-30 min)”

File: astro.config.mjs (project root)
Why: Defines your site URL for SEO, sitemaps, and asset linking
Lines: ~15-20

astro.config.mjs
export default defineConfig({
site: 'https://example.com', // ← Change this
// ...
});
astro.config.mjs
export default defineConfig({
site: 'https://your-domain.com', // Your actual domain
// OR use Cloudflare Pages URL initially:
// site: 'https://your-project.pages.dev',
// ...
});
  1. Open astro.config.mjs in your editor
  2. Find the site property (around line 15-20)
  3. Replace with your domain or https://your-project.pages.dev
  4. Save the file

File: src/layouts/BaseLayout.astro
Why: Controls site title, description, and social sharing
Lines: ~5-30 (frontmatter and head section)

Open src/layouts/BaseLayout.astro and find these lines:

  • Line ~8: Default title in Props interface → 'Your Site Name'
  • Line ~9: Default description'Your site description'
  • Line ~15: <title> tag → Your Brand
  • Line ~17: <meta name="description"> content
  • Lines ~20-25: Open Graph tags
  • Lines ~27-30: Twitter Card tags
Show full diff with before/after
src/layouts/BaseLayout.astro
---
interface Props {
title?: string = 'Astro Starter Template';
title?: string = 'Your Site Name';
description?: string = 'A performance-focused Astro starter';
description?: string = 'Your site description for SEO';
// ...
}
const { title, description } = Astro.props;
---
<head>
<title>{title} | Astro Starter</title>
<title>{title} | Your Brand</title>
<meta name="description" content="A performance-focused Astro starter template" />
<meta name="description" content="Your compelling site description" />
<!-- Open Graph / Facebook -->
<meta property="og:title" content={title} />
<meta property="og:title" content="Your Site Name" />
<meta property="og:description" content={description} />
<meta property="og:description" content="Your site description" />
<!-- Twitter -->
<meta property="twitter:title" content={title} />
<meta property="twitter:title" content="Your Site Name" />
<meta property="twitter:description" content={description} />
<meta property="twitter:description" content="Your site description" />
</head>

Files: public/favicon.svg (and variants)
Why: Your site icon in browser tabs and bookmarks

Specifications:

  • SVG: Recommended, scalable, supports dark mode
  • PNG: Fallback, 32×32px minimum, 512×512px ideal
  • ICO: Legacy support, 16×16 and 32×32 sizes
  1. Create your favicon (use Favicon.io or design tool)
  2. Replace public/favicon.svg with your SVG
  3. (Optional) Add public/favicon.ico for legacy browsers
  4. (Optional) Add public/favicon-32x32.png and public/favicon-16x16.png

Verify:

Terminal window
# Check files exist
ls -la public/favicon*
# Should show:
# favicon.svg (required)
# favicon.ico (optional)
# favicon-32x32.png (optional)

Files:

  • tokens/semantic.json - Brand colors
  • src/components/structural/Header.astro - Logo text

Quick Color Change:

tokens/semantic.json
{
"color": {
"brand": {
"primary": {
"value": "#your-primary-color",
"description": "Primary brand color"
},
"secondary": {
"value": "#your-secondary-color",
"description": "Secondary brand color"
}
}
}
}

Rebuild tokens:

Terminal window
pnpm run build:tokens # Compile tokens only
# Or rebuild everything:
pnpm run build

Update logo text:

src/components/structural/Header.astro
<a href="/" class="logo">
- Astro Starter
+ Your Brand
</a>

Before deploying, verify everything looks correct:

Terminal window
# Restart dev server
pnpm run dev
# Open http://localhost:4321

Verification checklist:

  • New title appears in browser tab
  • New favicon displays
  • Updated metadata (view page source: Ctrl/Cmd+U)
  • Logo text updated (if changed)
  • Colors updated (if changed)
  • No console errors (F12 → Console)

🚀 Step 2: Deploy to Production (15-20 min)

Section titled “🚀 Step 2: Deploy to Production (15-20 min)”

Check your Git status first:

Terminal window
# Check if Git is already initialized
git status
# If you see "not a git repository", initialize it:
git init
Terminal window
git add .
git commit -m "feat: personalize site configuration and branding"
git push
Terminal window
# Stage all changes
git add .
# Commit with message
git commit -m "feat: personalize site configuration and branding"

Create GitHub repository:

  1. Go to github.com/new
  2. Name your repository (e.g., my-astro-site)
  3. Choose Public or Private
  4. Do NOT initialize with README (you already have files)
  5. Click Create repository

Connect and push:

Terminal window
# Add remote (replace with your GitHub username and repo name)
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
# Rename branch to main (if needed)
git branch -M main
# Push to GitHub
git push -u origin main
  1. Go to dash.cloudflare.com/sign-up
  2. Enter email and create password
  3. Verify email address
  1. In Cloudflare dashboard, navigate to Workers & Pages
  2. Click Create Application
  3. Select Pages tab
  4. Click Connect to Git
  5. Choose GitHub and authorize Cloudflare
  6. Select your repository from the list
Project name: your-project-name
Production branch: main
Build command: pnpm run build
Build output directory: dist
Root directory: (leave empty)
Environment variables: (see below if needed)
  1. Click Save and Deploy
  2. Wait 2-5 minutes for build to complete
  3. Your site will be live at https://your-project-name.pages.dev

Your site is now live, but it’s using the placeholder URL from Step 1. Let’s fix that:

  1. Copy your actual URL from Cloudflare (e.g., https://my-project-abc.pages.dev)

  2. Update config:

    astro.config.mjs
    export default defineConfig({
    site: 'https://my-project-abc.pages.dev', // ← Your actual Cloudflare URL
    });
  3. Commit and push:

    Terminal window
    git add astro.config.mjs
    git commit -m "fix: update site URL with Cloudflare Pages domain"
    git push
  4. Wait for rebuild (1-2 min) - Cloudflare auto-deploys on push

  5. Verify the new build succeeded in Cloudflare dashboard

When and How to Use Environment Variables

When you need environment variables:

  • API keys for third-party services
  • Analytics tracking IDs
  • CMS endpoints
  • Feature flags

Astro v5.x Type-Safe Environment Variables:

Astro v5 includes built-in type-safe environment variable handling via astro:env.

1. Define in astro.config.mjs:

import { defineConfig, envField } from 'astro/config';
export default defineConfig({
site: import.meta.env.SITE_URL || 'https://example.com',
experimental: {
env: {
schema: {
SITE_URL: envField.string({
context: 'server',
access: 'public',
default: 'https://example.com',
}),
API_KEY: envField.string({
context: 'server',
access: 'secret',
}),
},
},
},
});

2. Add to your hosting platform:

Cloudflare Pages:

  • Go to SettingsEnvironment Variables
  • Add SITE_URL, API_KEY, etc.
  • Separate variables for Production and Preview environments

Vercel:

  • Go to SettingsEnvironment Variables
  • Add variables with environment selection (Production, Preview, Development)

Netlify:

  • Go to Site settingsEnvironment variables
  • Add variables (applies to all deploys by default)

3. Use in your code:

---
import { SITE_URL, API_KEY } from 'astro:env/server';
const response = await fetch(`${API_KEY}/endpoint`);
---

Security best practices:

  • Never commit .env files to Git (already in .gitignore)
  • Use access: 'secret' for sensitive data (API keys, tokens)
  • Use access: 'public' for non-sensitive config (site URL, feature flags)

See Vercel Deployment Guide for detailed instructions.

Quick steps:

  1. Go to vercel.com/new
  2. Import your GitHub repository
  3. Build command: pnpm run build
  4. Output directory: dist
  5. Deploy

See Netlify Deployment Guide for detailed instructions.

Quick steps:

  1. Go to app.netlify.com/start
  2. Connect to GitHub
  3. Build command: pnpm run build
  4. Publish directory: dist
  5. Deploy
More Platform Options

Best for: Full-stack apps, databases, background workers

  1. Go to render.com
  2. Click NewStatic Site
  3. Connect GitHub repository
  4. Build command: pnpm run build
  5. Publish directory: dist
  6. Deploy

Pros: Free SSL, global CDN, preview environments

Best for: Open source projects, documentation sites

Setup with GitHub Actions:

  1. Create .github/workflows/deploy.yml:

    name: Deploy to GitHub Pages
    on:
    push:
    branches: [main]
    permissions:
    contents: read
    pages: write
    id-token: write
    jobs:
    build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: pnpm/action-setup@v3
    - uses: actions/setup-node@v4
    with:
    node-version: '22'
    cache: 'pnpm'
    - run: pnpm install --frozen-lockfile
    - run: pnpm run build
    - uses: actions/upload-pages-artifact@v3
    with:
    path: dist
    deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
    name: github-pages
    url: ${{ steps.deployment.outputs.page_url }}
    steps:
    - uses: actions/deploy-pages@v4
    id: deployment
  2. Enable GitHub Pages:

    • Repo → Settings → Pages
    • Source: GitHub Actions
  3. Update astro.config.mjs:

    export default defineConfig({
    site: 'https://username.github.io',
    base: '/repo-name', // Only if not using custom domain
    });

    Note: GitHub Pages requires base path if using username.github.io/repo-name format.

  1. In your Pages project, go to Custom domains
  2. Click Set up a custom domain
  3. Enter your domain (e.g., yourdomain.com)
  4. Follow DNS configuration instructions:
    • Add CNAME record pointing to your-project.pages.dev
    • Or use Cloudflare nameservers (recommended)
  5. Wait for DNS propagation (5-30 minutes)

Update astro.config.mjs:

export default defineConfig({
site: 'https://yourdomain.com', // ← Your custom domain
// ...
});

Commit and push:

Terminal window
git add astro.config.mjs
git commit -m "fix: update site URL with custom domain"
git push

2.5 CI/CD Integration (Optional, Advanced)

Section titled “2.5 CI/CD Integration (Optional, Advanced)”
Custom Deployment Pipelines with GitHub Actions

Why use GitHub Actions instead of native Git integration?

Most platforms (Cloudflare Pages, Vercel, Netlify) automatically deploy when you push to Git. GitHub Actions gives you more control for advanced use cases.

Use cases for GitHub Actions:

  • Run tests before deployment - Prevent broken builds from going live
  • Custom build steps - Complex preprocessing, code generation
  • Multi-environment deploys - Staging, preview, production from one workflow
  • Service integrations - Slack notifications, database migrations, cache invalidation
  • Monorepo deployments - Deploy multiple projects from one repo

If you just need “push to deploy,” stick with native Git integration. GitHub Actions adds complexity.

Setup:

  1. Create workflow file .github/workflows/deploy.yml:
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build site
run: pnpm run build
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: your-project-name
directory: dist
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
  1. Add secrets to GitHub:

    • Go to your repo → SettingsSecrets and variablesActions
    • Add CLOUDFLARE_API_TOKEN (get from Cloudflare dashboard)
    • Add CLOUDFLARE_ACCOUNT_ID (found in Cloudflare URL)
  2. Get Cloudflare credentials:

    • API Token: Cloudflare dashboard → My Profile → API Tokens → Create Token
    • Use “Edit Cloudflare Workers” template
    • Account ID: In Cloudflare Pages project URL

Vercel automatically deploys on push without additional configuration. Just connect your repo.

Netlify also auto-deploys on push. Configure in netlify.toml:

[build]
command = "pnpm run build"
publish = "dist"
[build.environment]
NODE_VERSION = "22"
PNPM_VERSION = "9"

✓ Step 3: Verify Your Deployment (5-10 min)

Section titled “✓ Step 3: Verify Your Deployment (5-10 min)”

Visit your live site and verify:

  • Site loads without errors
  • Correct title in browser tab
  • Correct favicon displays
  • Homepage displays correctly
  • Example landing page works (/examples/landing)
  • Dark mode toggle works
  • Mobile responsive (test on phone or DevTools)
  • No console errors (F12 → Console)
  • No 404 errors for assets

Run a Lighthouse audit to verify performance:

  1. Open your live site
  2. Press F12 → Lighthouse tab
  3. Click Analyze page load
  4. Check scores
  1. Go to pagespeed.web.dev
  2. Enter your live URL
  3. Click Analyze

WCAG AA Compliance Check:

  1. WAVE Browser Extension

  2. Axe DevTools

    • Install: Chrome Web Store
    • Open DevTools (F12) → Axe DevTools tab
    • Click Scan ALL of my page
    • Fix any critical or serious issues
  3. Lighthouse Accessibility Audit

    • Already included in Lighthouse (see Option 1)
    • Target: 100/100 score

Common accessibility checks:

  • All images have alt text
  • Heading hierarchy is logical (h1 → h2 → h3)
  • Color contrast meets WCAG AA (4.5:1 for text)
  • Keyboard navigation works (Tab, Enter, Escape)
  • Focus indicators are visible
  • Form inputs have labels
  • ARIA attributes used correctly

These scores assume:

  • No additional content yet
  • No third-party scripts (analytics, ads)
  • No custom fonts beyond system fonts
  • No large images
MetricTargetWhy This Score
Performance95+Astro’s static output is blazing fast
Accessibility100Semantic HTML + ARIA best practices
Best Practices100HTTPS, modern standards, no deprecated APIs
SEO100Meta tags, sitemap, semantic structure

As you add content, scores will change. This is normal. Focus on:

  • Image optimization (use Astro’s <Image /> component)
  • Lazy loading for non-critical content
  • Keeping third-party scripts minimal

Common score impacts:

  • Performance drops to 85-90 - After adding 10+ images, custom fonts, or analytics
  • Accessibility drops to 95-98 - Missing alt text on new images, contrast issues in custom designs
  • Best Practices drops to 95 - Third-party scripts (Google Analytics, ad networks)
  • SEO stays 100 - Unless you forget meta descriptions or have broken internal links

Goal: Keep Performance > 85, everything else > 95 as you add content.

Quick Wins:

  1. Chrome DevTools Device Mode (Ctrl/Cmd+Shift+M)

    • Test iPhone 14 Pro, Pixel 7, iPad Pro
    • Toggle device toolbar, rotate orientation
    • Good enough for most cases
  2. Free Real Device Testing

    • LambdaTest - 100 minutes/month free
    • BrowserStack - Free trial, then $29-99/month
    • Use if you need cross-browser testing on real devices
  3. Your Own Devices (Recommended)

    • iOS Safari (iPhone/iPad)
    • Android Chrome
    • Desktop browsers (Chrome, Firefox, Safari)
    • Most reliable for catching real issues

Test Checklist:

  • Navigation works on mobile
  • Dark mode toggle accessible
  • Text readable without zooming
  • No horizontal scroll
  • Touch targets ≥ 44×44px
  • Forms usable on mobile (if applicable)
Staying Updated with Astro Releases

Current version: Astro v5.x (as of 2025)

Monitoring updates:

Astro releases new versions regularly. Stay informed to benefit from improvements and avoid breaking changes.

Update strategy:

  1. Follow release channels:

  2. Before upgrading:

    • Review Astro upgrade guide
    • Check for breaking changes in the changelog
    • Test in a separate branch first
  3. Safe upgrade process:

    • Create a new branch: git checkout -b upgrade-astro
    • Update dependencies: pnpm update astro
    • Run build: pnpm run build
    • Test locally: pnpm run preview
    • Fix any breaking changes
    • Merge when stable

Staying updated:

Terminal window
# Check for updates
pnpm outdated
# Update Astro (minor versions)
pnpm update astro
# Update all dependencies
pnpm update
# Major version upgrade (test first!)
pnpm add astro@latest

Cause: Platform doesn’t have pnpm installed

Fix: Update build command to install pnpm first:

Terminal window
npm install -g pnpm && pnpm run build

Or use npm instead:

Terminal window
npm install && npm run build

Cause: Missing token files in repository

Fix:

  1. Verify tokens/base.json and tokens/semantic.json exist locally
  2. Ensure they’re committed to Git:
Terminal window
git add tokens/
git commit -m "fix: add token files"
git push

Cause: Path aliases not resolved

Fix: Ensure tsconfig.json has proper paths configuration (should be default in template). If missing, add:

{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@layouts/*": ["src/layouts/*"],
"@utils/*": ["src/utils/*"]
}
}
}

Fix: Verify URL in astro.config.mjs matches deployment URL exactly (including https://)

// ✅ Correct
site: 'https://my-project.pages.dev'
// ❌ Incorrect
site: 'my-project.pages.dev' // Missing https://
site: 'http://my-project.pages.dev' // Wrong protocol

Fix: Ensure platform build settings use dist as output directory

Fix: If deploying to subdirectory, add base to config:

astro.config.mjs
export default defineConfig({
site: 'https://yourdomain.com',
base: '/subdirectory', // Only if deploying to subdirectory
});

Fix: Use Astro’s image component and relative imports:

---
// ✅ Correct
import { Image } from 'astro:assets';
import myImage from '@/assets/image.jpg';
---
<Image src={myImage} alt="Description" />
<!-- ❌ Incorrect -->
<img src="/src/assets/image.jpg" alt="Description" />

Fix: The build script automatically compiles tokens. If styles are still broken:

Terminal window
# Test locally first
pnpm run build
pnpm run preview

If it works locally but not on the platform, check:

  • Build logs for token compilation step
  • Ensure tokens/ directory is committed to Git
  • Verify platform is using pnpm run build (not a custom command)

Cause: Font files not in public directory or incorrect paths

Section titled “Cause: Font files not in public directory or incorrect paths”

Fix: Verify font imports in BaseLayout.astro:

<link rel="preload" href="/fonts/your-font.woff2" as="font" type="font/woff2" crossorigin />

Ensure font files are in public/fonts/ directory.

  1. Check build logs on your platform dashboard for detailed error messages
  2. Review deployment guide: Phase 10: Deployment
  3. Common issues: FAQ
  4. Search existing issues: GitHub Issues
  5. Ask for help: GitHub Discussions

Now that you’re deployed, choose your path based on your goals:

Best for: Blogs, portfolios, marketing sites

  1. Creating Your First Page
  2. Content Collections Guide
  3. Add blog posts or projects
  4. Customize page layouts

Time: 1-2 hours to first content page

Best for: Unique branding, custom themes

  1. Design Tokens Guide
  2. Customize colors, typography, spacing
  3. Create custom components
  4. Build design system

Time: 2-4 hours for basic customization

Best for: Complex sites, interactive elements

  1. Component Patterns
  2. Phase 5: Components
  3. Add interactive islands
  4. Implement advanced features

Time: 4-8 hours for advanced features

Best for: Production-ready, feature-complete sites

  1. MVP Track Guide (2-3 weeks)
  2. Showcase Track Guide (4-6 weeks)
  3. Complete all 12 phases
  4. Production optimization

Time: 2-6 weeks depending on track

Actual times for this guide:

PhaseTime
Setup & Personalization20-30 min
Git & Repository Setup5-10 min
Platform Deployment10-20 min
Verification & Testing5-10 min
Custom Domain (optional)+15 min
Total45-75 min

Your site is now live! You’ve successfully:

  • Personalized your branding
  • Deployed to production
  • Verified performance
  • Tested across devices

We’d love to see what you’ve built:

Your deployment is just the beginning. Explore the implementation guides, customize the design system, and let’s build something amazing.