Minimal GitHub Actions for Static Sites (When You Outgrow Manual Wrangler)
Manual wrangler pages deploy is perfect for pilots. Eventually you may want pushes to main to publish themselves. This article sketches a minimal GitHub Actions approach for static sites, with emphasis on secrets hygiene and knowing when CI is premature.
When CI is worth it
Add CI when two or more people publish, when you forget deploys after merging, or when a build step (Eleventy/Hugo) must run cleanly on a neutral machine. Stay manual when you are still inventing information architecture—CI will just automate thrash.
Secrets and least privilege
Store CLOUDFLARE_API_TOKEN and account ID in GitHub Actions secrets. Grant the token only Pages Edit (and read as needed). Never echo secrets in logs. Never commit .env. Rotate tokens if workflows are forked publicly with pull_request targets that could exfiltrate secrets—understand GitHub’s permission model before enabling risky triggers.
A minimal workflow shape
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: Deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: npx wrangler pages deploy ./public --project-name=negency-lab-pilot
Adjust the publish directory. Add a build step before deploy if you generate HTML. Keep the workflow readable; avoid twenty community actions you do not understand.
Node version alignment
Match the Node version Wrangler requires. Pin versions in the workflow. Document the pin in README so local deploys do not drift. If Actions uses Node 20 and Wrangler needs 22, you will see the same engine error you saw locally—fix once on a clean runner mindset.
Pre-deploy checks
Optional cheap checks: ensure index.html exists; grep for accidental API_TOKEN strings; verify article count; run HTML validator if you tolerate the setup time. Fail the job on secrets patterns found in the publish dir.
Rollback habits
Cloudflare Pages keeps prior deployments—know how to roll back in the dashboard. Tag Git commits that match production deploys. When a bad article ships, revert Git and redeploy, or roll back then fix forward. Your runbook should say which approach you prefer.
CI is a multiplier. Multiply a clean manual process, not a messy one.
Keep the manual path alive
Even after CI works, retain a documented one-liner for emergency deploys from a laptop or box. CI outages happen. Token rotations happen. When Search Console shows a critical typo during AdSense review week, you want a five-minute fix path that does not depend on debugging YAML.
Store the manual command in the runbook next to the workflow file path. When they diverge, treat that as a bug.
Environments and preview deploys
GitHub Environments can gate production secrets behind approvals. For a solo pilot that may be overkill; for a future team, it prevents intern push-to-main accidents. Preview deployments—whether Cloudflare’s per-branch URLs or Actions artifacts—help reviewers comment on content before it is canonical. Do not submit preview URLs to AdSense; submit the stable production hostname.
Caches and build speed
Cache npm dependencies in Actions to keep deploys under a couple of minutes. For pure static HTML with no build, skip package installs entirely and call npx wrangler with a pinned version. Pinning avoids surprise major upgrades breaking your pipeline on a Sunday.
- run: npx wrangler@4.145.0 pages deploy ./public --project-name=negency-lab-pilot
Record the pin in README. Upgrade intentionally.
Observability without vanity metrics
Actions email or chat notifications on failure are enough at small scale. Add uptime checks later if the site becomes business-critical. Do not wire ten analytics scripts pre-AdSense; each script is another privacy disclosure and another failure mode. Prefer host analytics or a single privacy-friendly option after content quality is proven.
CI should make publishing calmer. If your workflow becomes a second full-time job, simplify until deploying feels boring again.
Actions vs direct upload: decision table
Situation | Prefer
--------------------------------- | ----------------------
Solo pilot, HTML already built | Manual Wrangler
Scheduled weekly article drops | Actions on push/tag
Designers need preview URLs | Git-connected Pages
Secrets only on a private box | Manual from that box
Open-source docs in same repo | Actions + Pages/GitHub
You can mix modes: use Actions for mainline publishes and keep manual Wrangler for hotfixes. Just ensure both paths upload the same directory layout so you never “fix” production with a partial tree from a different working folder.
Write the decision into the runbook so contributors do not invent a third pipeline under pressure.
FAQ
Can I deploy from a fork PR? Not with production secrets unless you fully understand GitHub’s pull_request security model. Prefer pushing to a branch in the same repo.
Should ads.txt be validated in CI? Yes—assert the file exists at the publish root. After AdSense approval, optionally assert it no longer contains only placeholders.