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-docsChoose the "Documentation" template when prompted. This sets up Starlight, Astro's docs theme. Install dependencies:
npm installThe default build outputs to dist/. Verify it works:
npm run build
npx serve distVisit 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 mainAdd 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 buildto generate static files - The output is in
dist/
Commit and push:
git add pandastack.json
git commit -m "Add PandaStack config"
git pushUpdate README.md to include a deploy button:
# Astro Docs
[](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:
- 1Reads
pandastack.jsonfrom the repo'smainbranch via GitHub's API - 2Pre-fills the deploy form with the build command and output directory
- 3Clones the repo, runs
npm install && npm run build, and uploadsdist/to a CDN - 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:
- 1Triggers on push to
main - 2Calls PandaStack's API to trigger a deploy
- 3Extracts the deployment ID from the response
- 4Fails the workflow if the deploy request failed
You need two GitHub secrets:
PANDASTACK_TOKEN— a project-scoped API tokenPANDASTACK_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 staticThis creates the project and prints the project ID. Generate a project-scoped token:
panda projects token astro-docsCopy the psk_live_xxx token. In your GitHub repo, go to Settings → Secrets → Actions, and add:
PANDASTACK_TOKEN=psk_live_xxxPANDASTACK_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 pushThe 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:
- 1Runs
npm run buildto generate new static files - 2Uploads them to the CDN (overwrites old files)
- 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}/logsThe 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.ioAdd 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)