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.
🚦 Pre-Deployment Readiness Check
Section titled “🚦 Pre-Deployment Readiness Check”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 buildsucceeds locally (requiresSITE_URL— see Step 1.1) - 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:
pnpm run preview:build # Builds and serves the production build locallyOpen http://localhost:4321 - if this works, you’re ready to deploy.
🎯 What You’ll Accomplish
Section titled “🎯 What You’ll Accomplish”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
✅ Prerequisites
Section titled “✅ Prerequisites”Required
Section titled “Required”- Completed Launch Demo - Local site running successfully
- GitHub account (sign up)
- Hosting platform account (see Platform Selection below)
- Basic Git knowledge (commit, push)
Platform Selection
Section titled “Platform Selection”Choose your hosting platform before starting:
| Platform | Best For | Free Tier | Setup Time | Auto HTTPS | Recommendation |
|---|---|---|---|---|---|
| GitHub Pages ⭐ | Zero setup — the template ships the workflow | Public repos | 5 min | ✅ | Ships preconfigured (see Option E) |
| Cloudflare Pages | Performance, global CDN | Unlimited sites | 10-15 min | ✅ Instant | Best managed host for most |
| Vercel | Next.js ecosystem, teams | 100GB/month | 10-15 min | ✅ Instant | Great for existing Vercel users |
| Netlify | Forms, split testing, CMS | 100GB/month | 10-15 min | ✅ Instant | Good for marketing sites |
📦 Understanding Your Build
Section titled “📦 Understanding Your Build”When you run pnpm run build, here’s what happens:
-
Environment Validation (
env:validate)- Checks that
SITE_URL(orPUBLIC_SITE_URL) is set to a real URL - Fails the build if the variable is missing or still a placeholder (
example.com,your-username,your-domain,localhost)
- Checks that
-
Token Compilation (
tokens:build)- Reads
tokens/base.jsonandtokens/semantic.json - Generates CSS custom properties
- Outputs to
tokens/dist/tokens.cssandtokens/dist/tailwind-tokens.json(git-ignored, regenerated on every build)
- Reads
-
Astro Build (
astro build)- Compiles
.astrocomponents to HTML - Bundles JavaScript (only interactive islands)
- Optimizes CSS (removes unused styles)
- Processes images (AVIF + WebP)
- Generates sitemap
- Compiles
-
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.
📋 Deployment Checklist
Section titled “📋 Deployment Checklist”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)”1.1 Site Configuration
Section titled “1.1 Site Configuration”File: .env (project root — copy from .env.example)
Why: astro.config.mjs derives site from the SITE_URL (or PUBLIC_SITE_URL) environment variable, which drives SEO, sitemaps, and asset linking. There is no hardcoded URL to edit — and the build fails at the env:validate step if the variable is unset or still a placeholder (example.com, your-username, your-domain, localhost).
Before
Section titled “Before”# .env (copied from .env.example — dev-only default)PUBLIC_SITE_URL=http://localhost:4321SITE_URL=https://your-actual-domain.com# OR the origin your host gives you, e.g.# SITE_URL=https://<github-username>.github.io (shipped GitHub Pages workflow)# SITE_URL=https://my-project.pages.dev (Cloudflare Pages)Action Steps
Section titled “Action Steps”- Copy
.env.exampleto.envif you haven’t already (cp .env.example .env) - Set
SITE_URLto your domain or your expected*.pages.devURL - Save the file —
astro.config.mjsreads the variable at build time; don’t edit the config itself - In Step 2.2 you’ll add the same
SITE_URLas an environment variable on your hosting platform (.envis git-ignored, so the platform can’t see it). The shipped GitHub Pages workflow is the exception: it resolvesSITE_URLitself (see Option E)
1.2 Site Metadata & SEO
Section titled “1.2 Site Metadata & SEO”File: src/config.ts
Why: Controls the site title, description, author, and links used in meta tags and social sharing
Lines: ~10-40 (siteMetadata and siteLinks)
Quick Checklist: What to Update
Section titled “Quick Checklist: What to Update”Open src/config.ts and update these values (the layout’s <Head /> component reads them, so you don’t need to edit src/layouts/BaseLayout.astro directly):
-
siteMetadata.title→'Your Site Name'(appended to page titles asPage Title | Your Site Name, and used for Open Graph/Twitter tags) -
siteMetadata.description→ fallback description for pages that don’t provide their own -
siteMetadata.author→ your name (used in meta tags and structured data) -
siteLinks.github→ your repository URL (used in header, footer, and CTA links)
Show full diff with before/after
What to Change
Section titled “What to Change”export const siteMetadata = { title: "Astro Performance Starter", title: "Your Site Name", description: "A production-ready Astro starter focused on performance, accessibility, and DX.", description: "Your site description for SEO", author: "Your Name", author: "Jane Developer",} as const;
export const siteLinks = { github: "https://github.com/clownware/astro-performance-starter", github: "https://github.com/YOUR_USERNAME/YOUR_REPO", // ...} as const;1.3 Visual Branding
Section titled “1.3 Visual Branding”Favicon Replacement
Section titled “Favicon Replacement”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
Action Steps
Section titled “Action Steps”- Create your favicon (use Favicon.io or design tool)
- Replace
public/favicon.svgwith your SVG - (Optional) Add
public/favicon.icofor legacy browsers - (Optional) Add
public/favicon-32x32.pngandpublic/favicon-16x16.png
Verify:
# Check files existls -la public/favicon*
# Should show:# favicon.svg (required)# favicon.ico (optional)# favicon-32x32.png (optional)Logo & Brand Colors (Optional)
Section titled “Logo & Brand Colors (Optional)”Files:
tokens/semantic.json- Brand colorssrc/components/structural/Header.astro- Logo text
Quick Color Change:
Brand colors live in the role-based semantic.primary and semantic.secondary scales (ADR-047). Each step (50-950) aliases a color ramp defined in tokens/base.json — by default color.violet for primary and color.rose for secondary:
// tokens/semantic.json (excerpt — the real file has the full 50-950 scale){ "semantic": { "primary": { "500": { "value": "{color.violet.500}" } }, "secondary": { "500": { "value": "{color.rose.500}" } } }}To change brand colors, either repoint the primary/secondary steps at a different base ramp (e.g. {color.amber.500}), or edit the ramp’s HSL channel values in tokens/base.json (e.g. "500": { "value": "256 86% 63%" }).
Rebuild tokens:
pnpm run tokens:build # Compile tokens only# Or rebuild everything:pnpm run buildUpdate the logo:
Replace public/logo.svg with your own logo file. The header (src/components/structural/Header.astro) renders it as an image — update its alt text to your brand name while you’re there.
1.4 Verify Changes Locally
Section titled “1.4 Verify Changes Locally”Before deploying, verify everything looks correct:
# Restart dev serverpnpm run dev
# Open http://localhost:4321Verification 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)”2.1 Save Your Changes (Git)
Section titled “2.1 Save Your Changes (Git)”Check your Git status first:
# Check if Git is already initializedgit status
# If you see "not a git repository", initialize it:git initIf you already have commits
Section titled “If you already have commits”git add .git commit -m "feat: personalize site configuration and branding"git pushIf this is your first commit
Section titled “If this is your first commit”# Stage all changesgit add .
# Commit with messagegit commit -m "feat: personalize site configuration and branding"Create GitHub repository:
- Go to github.com/new
- Name your repository (e.g.,
my-astro-site) - Choose Public or Private
- Do NOT initialize with README (you already have files)
- Click Create repository
Connect and push:
# 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 master (the template's default branch, if needed)git branch -M master
# Push to GitHubgit push -u origin master2.2 Platform Configuration
Section titled “2.2 Platform Configuration”Option A: Cloudflare Pages (Recommended)
Section titled “Option A: Cloudflare Pages (Recommended)”Step 1: Create Cloudflare Account
Section titled “Step 1: Create Cloudflare Account”- Go to dash.cloudflare.com/sign-up
- Enter email and create password
- Verify email address
Step 2: Connect GitHub Repository
Section titled “Step 2: Connect GitHub Repository”- In Cloudflare dashboard, navigate to Workers & Pages
- Click Create Application
- Select Pages tab
- Click Connect to Git
- Choose GitHub and authorize Cloudflare
- Select your repository from the list
Step 3: Configure Build Settings
Section titled “Step 3: Configure Build Settings”Project name: your-project-nameProduction branch: masterBuild command: pnpm run buildBuild output directory: distRoot directory: (leave empty)Environment variables: SITE_URL=https://your-project-name.pages.dev (REQUIRED)Step 4: Deploy
Section titled “Step 4: Deploy”- Click Save and Deploy
- Wait 2-5 minutes for build to complete
- Your site will be live at
https://your-project-name.pages.dev
Step 5: Update Site URL & Redeploy
Section titled “Step 5: Update Site URL & Redeploy”Your site is now live, but it may be using the guessed URL from Step 1.1. Let’s fix that:
-
Copy your actual URL from Cloudflare (e.g.,
https://my-project-abc.pages.dev) -
Update the platform variable: in your Pages project, go to Settings → Environment Variables and set
SITE_URLto the actual URL -
Update your local
.envto match, so local production builds agree with the platform -
Trigger a rebuild — changing an environment variable doesn’t redeploy by itself: use Deployments → Retry deployment, or push any commit
-
Verify the new build succeeded in Cloudflare dashboard
2.3 Environment Variables (Optional)
Section titled “2.3 Environment Variables (Optional)”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
Type-Safe Environment Variables with astro:env:
The template already configures astro:env (the top-level env option in astro.config.mjs, see ADR-050) with a schema for its PUBLIC_* variables. Note that SITE_URL, PUBLIC_SITE_URL, and DEPLOY_TARGET are intentionally not in that schema — they’re read at config-load time (before astro:env exists) and validated by the env:validate prebuild script instead. Don’t add them to the schema or re-derive site yourself.
1. Add new variables to the existing schema in astro.config.mjs:
// astro.config.mjs — extend the existing env.schema blockenv: { schema: { // ...existing PUBLIC_* fields... API_KEY: envField.string({ context: 'server', access: 'secret', }), },},2. Add to your hosting platform:
Cloudflare Pages:
- Go to Settings → Environment Variables
- Add
SITE_URL,API_KEY, etc. - Separate variables for Production and Preview environments
Vercel:
- Go to Settings → Environment Variables
- Add variables with environment selection (Production, Preview, Development)
Netlify:
- Go to Site settings → Environment variables
- Add variables (applies to all deploys by default)
3. Use in your code:
---import { API_KEY } from 'astro:env/server';
const response = await fetch('https://api.example.com/endpoint', { headers: { Authorization: `Bearer ${API_KEY}` },});---Security best practices:
- Never commit
.envfiles 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)
Option B: Vercel
Section titled “Option B: Vercel”See Vercel Deployment Guide for detailed instructions.
Quick steps:
- Go to vercel.com/new
- Import your GitHub repository
- Build command:
pnpm run build - Output directory:
dist - Deploy
Option C: Netlify
Section titled “Option C: Netlify”See Netlify Deployment Guide for detailed instructions.
Quick steps:
- Go to app.netlify.com/start
- Connect to GitHub
- Build command:
pnpm run build - Publish directory:
dist - Deploy
More Platform Options
Option D: Render
Section titled “Option D: Render”Best for: Full-stack apps, databases, background workers
- Go to render.com
- Click New → Static Site
- Connect GitHub repository
- Build command:
pnpm run build - Publish directory:
dist - Deploy
Pros: Free SSL, global CDN, preview environments
Option E: GitHub Pages (ships preconfigured)
Section titled “Option E: GitHub Pages (ships preconfigured)”Best for: The zero-setup path — open source projects, portfolios, documentation sites
The template already ships this workflow — .github/workflows/deploy.yml (“Deploy to GitHub Pages”) runs on every push to master (and on manual workflow_dispatch), builds with pnpm run build, and publishes dist/ through actions/deploy-pages. Do not write your own. Its “Resolve SITE_URL” step is what makes the build pass env:validate without any .env on the runner:
# .github/workflows/deploy.yml (already in the template — excerpt)- name: Resolve SITE_URL shell: bash run: | if [ -n "${SITE_URL_OVERRIDE}" ]; then echo "SITE_URL=${SITE_URL_OVERRIDE}" >> "$GITHUB_ENV" echo "Using custom SITE_URL=${SITE_URL_OVERRIDE} (base path /)" else echo "SITE_URL=https://${{ github.repository_owner }}.github.io" >> "$GITHUB_ENV" echo "DEPLOY_TARGET=gh-pages" >> "$GITHUB_ENV" echo "Using default project-Pages SITE_URL (base path /${{ github.event.repository.name }})" fi env: SITE_URL_OVERRIDE: ${{ vars.SITE_URL }}
- name: Build site run: pnpm run build-
Enable GitHub Pages:
- Repo → Settings → Pages
- Source: GitHub Actions
-
Push to
master— the workflow builds and deploys; your site appears athttps://<github-username>.github.io/<repo-name>/. -
Base path is automatic: with
DEPLOY_TARGET=gh-pages,astro.config.mjsderives the/<repo-name>base path from thenamefield inpackage.json— do not hand-addbase(orsite) to the config. If you rename the repo, updatepackage.json’snameto match. -
Custom domain (optional): add the CNAME at your DNS provider, set the domain under Settings → Pages → Custom domain (enable Enforce HTTPS), then create a repository variable
SITE_URL=https://your-domain.example(Settings → Secrets and variables → Actions → Variables tab — a variable, not a secret). The workflow readsvars.SITE_URL, skipsDEPLOY_TARGET, so the base path becomes/(a custom domain serves the project site from the root), and bakes the new origin into canonical/OG URLs and the sitemap. Delete the variable to return to the default<github-username>.github.io/<repo-name>origin. No workflow edit is needed either way.
2.4 Custom Domain (Optional, +15 min)
Section titled “2.4 Custom Domain (Optional, +15 min)”Cloudflare Pages
Section titled “Cloudflare Pages”- In your Pages project, go to Custom domains
- Click Set up a custom domain
- Enter your domain (e.g.,
yourdomain.com) - Follow DNS configuration instructions:
- Add CNAME record pointing to
your-project.pages.dev - Or use Cloudflare nameservers (recommended)
- Add CNAME record pointing to
- Wait for DNS propagation (5-30 minutes)
Update the SITE_URL variable:
- In your Pages project, go to Settings → Environment Variables and set
SITE_URLtohttps://yourdomain.com - Update your local
.envto match - Trigger a rebuild (Deployments → Retry deployment, or push any commit)
GitHub Pages
Section titled “GitHub Pages”Custom domains on the shipped workflow are driven entirely by the SITE_URL repository variable — see Option E, step 4. Set the domain under Settings → Pages, add the SITE_URL variable, and re-run the workflow (push a commit or use Run workflow on the Actions tab). Update your local .env to the same origin so local production builds agree with CI.
2.5 CI/CD Integration (Optional, Advanced)
Section titled “2.5 CI/CD Integration (Optional, Advanced)”Custom Deployment Pipelines with GitHub Actions
You already have one. .github/workflows/deploy.yml is the template’s GitHub Pages pipeline (Option E). It is the deployment the template supports out of the box — keep it, even if you deploy elsewhere: it costs nothing while GitHub Pages is disabled for the repo, and it stays the reference for how SITE_URL and DEPLOY_TARGET are resolved in CI.
Why add a second Actions workflow instead of a platform’s native Git integration?
Managed hosts (Cloudflare Pages, Vercel, Netlify) deploy automatically when you push. GitHub Actions gives you more control for advanced use cases:
- 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, cache invalidation
- Monorepo deployments - Deploy multiple projects from one repo
If you just need “push to deploy,” stick with the shipped workflow or the platform’s native Git integration. A second workflow adds complexity.
Optional alternative: deploy to Cloudflare Pages from Actions
Section titled “Optional alternative: deploy to Cloudflare Pages from Actions”Add this as a new file — do not overwrite the shipped deploy.yml:
# .github/workflows/deploy-cloudflare.yml (new file — leaves deploy.yml untouched)name: Deploy to Cloudflare Pages
on: push: branches: [master]
jobs: deploy: runs-on: ubuntu-latest permissions: contents: read deployments: write
steps: - name: Checkout uses: actions/checkout@v7
- name: Setup Node.js uses: actions/setup-node@v7 with: node-version-file: '.nvmrc'
- name: Setup PNPM uses: pnpm/action-setup@v6 with: run_install: false
- name: Install dependencies run: pnpm install --frozen-lockfile
- name: Build site run: pnpm run build env: SITE_URL: ${{ vars.SITE_URL }}
- name: Deploy to Cloudflare Pages uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy dist --project-name=your-project-nameNotes on that file:
pnpm/action-setupreads the pinned version from thepackageManagerfield inpackage.json, the same way the shippeddeploy.ymldoes — noversion:input needed.SITE_URLmust reach the build orenv:validatefails it. Here it comes from a repository variable (Settings → Secrets and variables → Actions → Variables); leaveDEPLOY_TARGETunset so the site builds for the root path.- Disable the Cloudflare project’s own Git integration once this workflow is in place, or you’ll deploy twice per push.
-
Add secrets to GitHub:
- Go to your repo → Settings → Secrets and variables → Actions
- Add
CLOUDFLARE_API_TOKEN(get from Cloudflare dashboard) - Add
CLOUDFLARE_ACCOUNT_ID(found in Cloudflare URL)
-
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
Alternative: Vercel GitHub Integration
Section titled “Alternative: Vercel GitHub Integration”Vercel automatically deploys on push without additional configuration. Just connect your repo and set SITE_URL in the project’s environment variables.
Alternative: Netlify GitHub Integration
Section titled “Alternative: Netlify GitHub Integration”Netlify also auto-deploys on push. Configure in netlify.toml (versions match the template’s .nvmrc and packageManager pins):
[build] command = "pnpm run build" publish = "dist"
[build.environment] NODE_VERSION = "24.21.0" PNPM_VERSION = "11.27.1"✓ Step 3: Verify Your Deployment (5-10 min)
Section titled “✓ Step 3: Verify Your Deployment (5-10 min)”Deployment Checklist
Section titled “Deployment Checklist”Visit your live site and verify:
- Site loads without errors
- Correct title in browser tab
- Correct favicon displays
- Homepage displays correctly
- Showcase page works (
/showcase/) - Dark mode toggle works
- Mobile responsive (test on phone or DevTools)
- No console errors (F12 → Console)
- No 404 errors for assets
Performance Check
Section titled “Performance Check”Run a Lighthouse audit to verify performance:
Option 1: Chrome DevTools
Section titled “Option 1: Chrome DevTools”- Open your live site
- Press F12 → Lighthouse tab
- Click Analyze page load
- Check scores
Option 2: PageSpeed Insights
Section titled “Option 2: PageSpeed Insights”- Go to pagespeed.web.dev
- Enter your live URL
- Click Analyze
Option 3: Accessibility Testing
Section titled “Option 3: Accessibility Testing”WCAG AA Compliance Check:
-
WAVE Browser Extension
- Install: wave.webaim.org/extension
- Click WAVE icon on your live site
- Review errors, alerts, and contrast issues
-
Axe DevTools
- Install: Chrome Web Store
- Open DevTools (F12) → Axe DevTools tab
- Click Scan ALL of my page
- Fix any critical or serious issues
-
Lighthouse Accessibility Audit
- Already included in Lighthouse (see Option 1)
- Target: 95+ (the CI floor is 0.95)
Common accessibility checks:
- All images have
alttext - 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
Target Scores (Fresh Deploy)
Section titled “Target Scores (Fresh Deploy)”These scores assume:
- No additional content yet
- No third-party scripts (analytics, ads)
- Only the template’s two self-hosted fonts (Geist for display, Inter for body — vendored WOFF2 served through the Astro Fonts API, ADR-053)
- No large images
The template’s headline claim is 95+ in every category, and CI (.github/workflows/lighthouse.yml, using lighthouserc.json for desktop and lighthouserc.mobile.json for mobile) fails the build when a category drops below its floor:
| Metric | Target | CI floor | Why This Score |
|---|---|---|---|
| Performance | 95+ | 0.90 | Astro’s static output is blazing fast |
| Accessibility | 95+ | 0.95 | Semantic HTML + ARIA best practices |
| Best Practices | 95+ | 0.95 | HTTPS, modern standards, no deprecated APIs |
| SEO | 95+ | 0.90 | Meta 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: Stay above the CI floors as you add content (Performance and SEO ≥ 90, Accessibility and Best Practices ≥ 95) — lighthouse.yml fails the check otherwise.
Test on Multiple Devices
Section titled “Test on Multiple Devices”Quick Wins:
-
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
-
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
-
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)
🔎 Advanced Configuration
Section titled “🔎 Advanced Configuration”Staying Updated with Astro Releases
Current version: Astro v7.4.1 (see the starter’s package.json for the exact version)
Monitoring updates:
Astro releases new versions regularly. Stay informed to benefit from improvements and avoid breaking changes.
Update strategy:
-
Follow release channels:
- Astro changelog
- Astro blog for major announcements
- @astrodotbuild on Twitter/X
-
Before upgrading:
- Review Astro upgrade guide
- Check for breaking changes in the changelog
- Test in a separate branch first
-
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
- Create a new branch:
Staying updated:
# Check for updatespnpm outdated
# Update Astro (minor versions)pnpm update astro
# Update all dependenciespnpm update
# Major version upgrade (test first!)pnpm add astro@latest🆘 Troubleshooting
Section titled “🆘 Troubleshooting”Build Fails on Platform
Section titled “Build Fails on Platform”Error: pnpm: command not found
Section titled “Error: pnpm: command not found”Cause: Platform doesn’t have pnpm installed
Fix: Update build command to install pnpm first:
npm install -g pnpm && pnpm run buildMost platforms enable Corepack and honour the packageManager field in package.json (pnpm@11.27.1), in which case pnpm is already available. Do not switch to npm run build: the build script shells out to pnpm run env:validate and pnpm run tokens:build, so the template is pnpm-only (constitution rule 6).
Error: tokens:build failed
Section titled “Error: tokens:build failed”Cause: Missing token files in repository
Fix:
- Verify
tokens/base.jsonandtokens/semantic.jsonexist locally - Ensure they’re committed to Git:
git add tokens/git commit -m "fix: add token files"git pushError: Module not found: @/components/...
Section titled “Error: Module not found: @/components/...”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/*"] } }}Site Deploys But Shows Blank Page
Section titled “Site Deploys But Shows Blank Page”Cause 1: Incorrect SITE_URL
Section titled “Cause 1: Incorrect SITE_URL”Fix: Verify the SITE_URL environment variable on your platform matches the deployment URL exactly (including https://)
# ✅ CorrectSITE_URL=https://my-project.pages.dev
# ❌ IncorrectSITE_URL=my-project.pages.dev # Missing https://SITE_URL=http://my-project.pages.dev # Wrong protocolCause 2: Build output directory mismatch
Section titled “Cause 2: Build output directory mismatch”Fix: Ensure platform build settings use dist as output directory
Cause 3: Base path issue
Section titled “Cause 3: Base path issue”Fix: Don’t hardcode site or base in astro.config.mjs — both are derived at config-load time: site from SITE_URL (or PUBLIC_SITE_URL) and base from DEPLOY_TARGET:
// astro.config.mjs (already in the template — do not replace with literals)const envSite = process.env.SITE_URL || process.env.PUBLIC_SITE_URL;const isGhPages = process.env.DEPLOY_TARGET === "gh-pages";const base = isGhPages ? `/${pkg.name}` : "/";- Blank page at
https://<github-username>.github.io/<repo-name>/with 404s for/_astro/*assets → the build ran withoutDEPLOY_TARGET=gh-pages. The shipped workflow sets it; a local build needs it in the environment. - Blank page on a custom domain or a root-path host → the build ran with
DEPLOY_TARGET=gh-pages, so every asset URL carries/<repo-name>. Unset it (on GitHub Pages, set theSITE_URLrepository variable and the workflow drops it for you). - Renamed the repo? Update the
namefield inpackage.json— that is where the/<repo-name>base comes from.
Images Not Loading
Section titled “Images Not Loading”Cause: Incorrect asset paths
Section titled “Cause: Incorrect asset paths”Fix: Use Astro’s image component and relative imports:
---// ✅ Correctimport { Image } from 'astro:assets';import myImage from '@/assets/image.jpg';---<Image src={myImage} alt="Description" />
<!-- ❌ Incorrect --><img src="/src/assets/image.jpg" alt="Description" />Styles Look Broken
Section titled “Styles Look Broken”Cause: Design tokens not built
Section titled “Cause: Design tokens not built”Fix: The build script automatically compiles tokens. If styles are still broken:
# Test locally firstpnpm run buildpnpm run previewIf 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)
Fonts Not Loading
Section titled “Fonts Not Loading”Cause: Font files or Fonts API config out of sync
Section titled “Cause: Font files or Fonts API config out of sync”Fix: The template loads fonts through Astro’s Fonts API — the .woff2 files are vendored in src/assets/fonts/ and registered in astro.config.mjs via fontProviders.local(). Verify:
ls src/assets/fonts/*.woff2- Font files exist in
src/assets/fonts/and are committed to Git - The
fontsentries inastro.config.mjspoint at the correct file paths - No manual
<link rel="preload">tags are needed — the Fonts API generates preload tags automatically
Still Stuck?
Section titled “Still Stuck?”- Check build logs on your platform dashboard for detailed error messages
- Review deployment guide: Phase 10: Deployment
- Common issues: FAQ
- Search existing issues: GitHub Issues
- Ask for help: GitHub Discussions
🎓 What’s Next?
Section titled “🎓 What’s Next?”Now that you’re deployed, choose your path based on your goals:
Path A: Content-First (Recommended)
Section titled “Path A: Content-First (Recommended)”Best for: Blogs, portfolios, marketing sites
- Creating Your First Page
- Content Collections Guide
- Add blog posts or projects
- Customize page layouts
Time: 1-2 hours to first content page
Path B: Design Customization
Section titled “Path B: Design Customization”Best for: Unique branding, custom themes
- Design Tokens Guide
- Customize colors, typography, spacing
- Create custom components
- Build design system
Time: 2-4 hours for basic customization
Path C: Advanced Features
Section titled “Path C: Advanced Features”Best for: Complex sites, interactive elements
- Component Patterns
- Phase 5: Components
- Add interactive islands
- Implement advanced features
Time: 4-8 hours for advanced features
Path D: Full Implementation
Section titled “Path D: Full Implementation”Best for: Production-ready, feature-complete sites
- Implementation Guides overview — one progressive path in three tiers (ADR-033)
- Build tier (Phases 5-8): components, sections, content, QA — scope each phase to Essential / Recommended / Advanced
- Polish tier (Phases 9-12): performance, deployment, documentation, post-launch
- Stop when you’ve reached your goals
Time: 2-6 weeks depending on how far into the Polish tier you go
📊 Time Breakdown
Section titled “📊 Time Breakdown”Actual times for this guide:
| Phase | Time |
|---|---|
| Setup & Personalization | 20-30 min |
| Git & Repository Setup | 5-10 min |
| Platform Deployment | 10-20 min |
| Verification & Testing | 5-10 min |
| Custom Domain (optional) | +15 min |
| Total | 45-75 min |
🎉 Congratulations
Section titled “🎉 Congratulations”Your site is now live! You’ve successfully:
- ✅ Personalized your branding
- ✅ Deployed to production
- ✅ Verified performance
- ✅ Tested across devices
Share Your Success
Section titled “Share Your Success”We’d love to see what you’ve built:
- Twitter/X - Tag @clownware
- GitHub - Open a Show & Tell discussion
- Discord - Share in Astro Discord
Keep Building
Section titled “Keep Building”Your deployment is just the beginning. Explore the implementation guides, customize the design system, and let’s build something amazing.