Back to Blog
Tutorial11 min read2026-07-31

Astro Docs Site with One-Click Deploy and GitHub Actions CI

Ship an Astro static site with a README button for instant clones, GitHub Actions for auto-deploys, and CDN edge caching with instant purges on every push.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Documentation sites built with Astro compile to static HTML with zero client JavaScript unless you opt in. Fast builds, fast page loads, and zero hosting cost when idle because there's no server process. The deployment flow is simple — run the build, upload the output directory to a CDN — but wiring it to CI and making it easy for others to fork requires some setup. A deploy button in the README lets anyone clone your docs and get a live site in one click. GitHub Actions redeploys on every push to main.

This guide builds an Astro docs site, adds a deploy button that reads config from the repo, sets up GitHub Actions to call PandaStack's API on push, and shows how CDN cache purges happen automatically so new content goes live instantly.

The Astro site

Create a new Astro project:

npm create astro@latest astro-docs
cd astro-docs

Choose the "Documentation" template when prompted. This sets up Starlight, Astro's docs theme. Install dependencies:

npm install

The default build outputs to dist/. Verify it works:

npm run build
npx serve dist

Visit http://localhost:3000. The docs site should load with a sidebar, search, and dark mode toggle. Push to GitHub:

git init
git add .
git commit -m "Initial Astro docs site"
git remote add origin https://github.com/yourname/astro-docs.git
git push -u origin main

Add a deploy button to the README

Create pandastack.json in the repo root:

{
  "type": "static",
  "name": "astro-docs",
  "buildCommand": "npm run build",
  "outputDir": "dist"
}

This config tells PandaStack:

  • The site is static (no server process)
  • Run npm run build to generate static files
  • The output is in dist/

Commit and push:

git add pandastack.json
git commit -m "Add PandaStack config"
git push

Update README.md to include a deploy button:

# Astro Docs

[![Deploy to PandaStack](https://dashboard.pandastack.io/deploy-button.svg)](https://dashboard.pandastack.io/deploy?repo=yourname/astro-docs)

Documentation site built with Astro and Starlight.

## Deploy

Click the button above to deploy this site to PandaStack. The site will be live on a CDN with automatic SSL.

Commit and push. Now anyone who visits your GitHub repo can click the button, and PandaStack:

  1. 1Reads pandastack.json from the repo's main branch via GitHub's API
  2. 2Pre-fills the deploy form with the build command and output directory
  3. 3Clones the repo, runs npm install && npm run build, and uploads dist/ to a CDN
  4. 4Returns a live URL like https://astro-docs-abc123.pandastack.io

The user doesn't type any config — it's all in the file.

Set up GitHub Actions for auto-deploys

For your own repo, you want pushes to main to trigger a redeploy. Create .github/workflows/deploy.yml:

name: Deploy to PandaStack

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Deploy to PandaStack
        run: |
          RESPONSE=$(curl -s -X POST https://api.pandastack.io/v1/projects/${{ secrets.PANDASTACK_PROJECT_ID }}/deploy \
            -H "Authorization: Bearer ${{ secrets.PANDASTACK_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{"branch": "main"}')

          echo "$RESPONSE"

          # Extract deploymentId from response
          DEPLOYMENT_ID=$(echo "$RESPONSE" | jq -r '.data.deploymentId')

          if [ "$DEPLOYMENT_ID" = "null" ]; then
            echo "Deploy failed"
            exit 1
          fi

          echo "Deployment started: $DEPLOYMENT_ID"

This workflow:

  1. 1Triggers on push to main
  2. 2Calls PandaStack's API to trigger a deploy
  3. 3Extracts the deployment ID from the response
  4. 4Fails the workflow if the deploy request failed

You need two GitHub secrets:

  • PANDASTACK_TOKEN — a project-scoped API token
  • PANDASTACK_PROJECT_ID — the project's numeric ID

Generate the token via the PandaStack CLI:

panda login
panda projects create astro-docs --repo yourname/astro-docs --type static

This creates the project and prints the project ID. Generate a project-scoped token:

panda projects token astro-docs

Copy the psk_live_xxx token. In your GitHub repo, go to Settings → Secrets → Actions, and add:

  • PANDASTACK_TOKEN = psk_live_xxx
  • PANDASTACK_PROJECT_ID = the project ID from above

Commit and push the workflow:

git add .github/workflows/deploy.yml
git commit -m "Add GitHub Actions deploy workflow"
git push

The workflow runs, calls the API, and triggers a deploy. Check the Actions tab in GitHub to see the run. Check the PandaStack dashboard to see the deployment logs.

How CDN cache purges work

When you redeploy an Astro site, PandaStack:

  1. 1Runs npm run build to generate new static files
  2. 2Uploads them to the CDN (overwrites old files)
  3. 3Purges the CDN cache so the new content is served immediately

Astro hashes asset filenames (/_astro/index.abc123.js), so new builds produce different filenames. The old files are left in place (for any client that cached the old HTML), and the new files are served to new visitors. The HTML files (/index.html, /about/) are cached with a short TTL (1 minute), so they're refreshed almost immediately.

This means:

  • Old clients (who loaded the site before the redeploy) continue to work with the old assets
  • New clients (who load after the redeploy) get the new assets
  • No broken page loads or mixed asset versions

Deploy the site via the API (first time)

If you haven't created the project via the CLI, create it via the API:

curl -X POST https://api.pandastack.io/v1/projects \
  -H "Authorization: Bearer psk_live_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "static",
    "name": "astro-docs",
    "repositoryName": "yourname/astro-docs",
    "branch": "main",
    "buildCommand": "npm run build",
    "outputDir": "dist",
    "autoDeploy": true
  }'

The response includes projectId and deploymentId. The build starts immediately. Check the logs:

curl -H "Authorization: Bearer psk_live_your_token_here" \
  https://api.pandastack.io/v1/projects/{projectId}/deployments/{deploymentId}/logs

The site goes live at a URL like https://astro-docs-abc123.pandastack.io.

Add a custom domain

In the PandaStack dashboard, go to the project's Settings → Domains and add your custom domain (e.g., docs.yourapp.com). PandaStack provisions an SSL certificate via Let's Encrypt and shows DNS records to configure:

CNAME docs.yourapp.com → astro-docs-abc123.pandastack.io

Add the CNAME to your DNS provider. Within a few minutes, https://docs.yourapp.com serves your site with automatic SSL.

What breaks and how to fix it

Build succeeds but site shows 404: The outputDir is wrong. Astro's default is dist/, but if you changed it in astro.config.mjs, update pandastack.json to match. Check the build log to see where Astro wrote the files.

Assets 404 with /astro/ prefix: Your Astro config has a custom base path that doesn't match the deploy URL. Either remove base from astro.config.mjs or set it to / for root-level deploys.

Deploy button shows empty form: pandastack.json is missing from the repo root, or it's malformed JSON. Test it locally with cat pandastack.json | jq to verify it's valid.

GitHub Actions workflow fails with 401: The PANDASTACK_TOKEN is expired or wrong. Regenerate it with panda projects token astro-docs and update the GitHub secret.

Site loads but search doesn't work: Astro's search index is generated at build time. If you added new pages but didn't rebuild, the search index is stale. Redeploy to regenerate it.

Comparing static and SSR Astro

This guide deploys Astro in static mode (output: 'static'), which pre-renders all pages at build time. For docs sites, this is ideal — the content doesn't change per request, and static pages are faster than server-rendered ones.

If you need server-side rendering (user-specific content, auth, dynamic data), switch to output: 'server' and deploy as a container app:

{
  "type": "container",
  "name": "astro-ssr",
  "buildCommand": "npm run build",
  "startCommand": "node ./dist/server/entry.mjs",
  "healthCheckPath": "/"
}

The container runs Node.js, renders pages on demand, and scales to zero when idle (free tier). Static mode is simpler and cheaper (no idle cost), so use it unless you need SSR.

Enabling preview deployments per pull request

For docs sites with multiple contributors, preview deployments let reviewers see changes before merging. PandaStack supports this via branch deploys. In pandastack.json:

{
  "type": "static",
  "name": "astro-docs",
  "buildCommand": "npm run build",
  "outputDir": "dist",
  "previewDeployments": true
}

Now every pull request triggers a preview deploy. The PR gets a comment with the preview URL (e.g., https://astro-docs-pr-42.pandastack.io). Reviewers can test the changes before merging.

Configure this via the dashboard (Settings → Preview Deployments) or the API by setting previewDeployments: true on the project.

Next steps

You've deployed an Astro docs site with three workflows: a one-click deploy button for forks, GitHub Actions for auto-deploys on push, and manual API calls for scripting. The site is served from a CDN with automatic SSL, instant cache purges on redeploy, and zero cost when idle.

For production docs sites, consider:

  • Enabling preview deployments for pull requests
  • Adding a sitemap.xml (Astro generates this automatically)
  • Configuring analytics (PandaStack's server-side analytics capture page views without client JavaScript)
  • Wiring a search service like Algolia for full-text search across docs

The same deploy pattern works for any static site generator — VitePress, Docusaurus, MkDocs, Hugo. Just point outputDir at the framework's build output.

References

  • [Astro documentation](https://docs.astro.build/en/getting-started/)
  • [Starlight docs theme](https://starlight.astro.build/)
  • [PandaStack deploy button](https://docs.pandastack.io/projects/deploy-button)
  • [GitHub Actions with PandaStack](https://docs.pandastack.io/integrations/github-actions)

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also