Deploy
Every deployable Astro / Vite app in the monorepo ships the same deploy
script shape and lands on a Cloudflare Pages project. Long-running Node
services (weiqi-server, auth-app, billing-indexer,
recognition-service, katago-service) deploy via Docker images to a
container platform; their docs live in the respective service pages.
This page covers the Cloudflare Pages convention used by the static / SSR frontends.
The convention
Section titled “The convention”// apps/<name>/wrangler.jsonc{ "$schema": "node_modules/wrangler/config-schema.json", "name": "<project-name>", "pages_build_output_dir": "./dist", "compatibility_date": "2025-04-01", "compatibility_flags": ["nodejs_compat"]}// apps/<name>/package.json — scripts block{ "scripts": { "deploy:cf": "pnpm dlx wrangler pages deploy ./dist --project-name <name> --branch main --commit-dirty=true", "deploy:cf:preview": "pnpm dlx wrangler pages deploy ./dist --project-name <name> --branch dev --commit-dirty=true", "cf:login": "pnpm dlx wrangler login" }}| Script | Branch | Effect |
|---|---|---|
deploy:cf | main | Production deploy. Overwrites the live URL. |
deploy:cf:preview | dev | Preview deploy to the dev branch alias (see below). |
cf:login | — | Opens the Cloudflare OAuth flow to refresh your local token. |
Both scripts pass --commit-dirty=true so a dirty working tree can still be
deployed in emergencies. CI uses the same scripts.
Branch aliases
Section titled “Branch aliases”Cloudflare Pages assigns each branch a stable URL of the form
https://<commit-hash>.<project>.pages.dev. For a stable URL that follows
the branch, attach a custom domain:
| Branch | CNAME target | URL |
|---|---|---|
main | <project>.pages.dev | <project>.pages.dev |
dev | dev.<project>.pages.dev | dev.<project>.pages.dev |
The dev branch does not get the bare <project>.pages.dev URL — that
belongs to main. CNAME dev.<your-domain> to dev.<project>.pages.dev
to serve the dev branch under a stable hostname.
GitHub Actions
Section titled “GitHub Actions”The reference workflow is .github/workflows/main-app-astro-pages.yaml.
Each Astro / Vite app has its own workflow file with the same shape:
name: deploy <app-name>on: push: branches: [main, dev]jobs: deploy: runs-on: ubuntu-latest environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }} env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: 9.15.0 } - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile # Pipe per-environment env into the app's .env at deploy time. - name: Write env run: | cat <<EOF > apps/<app>/.env ${{ secrets.<APP>_ENV }} EOF - run: pnpm --dir apps/<app> build - run: pnpm --dir apps/<app> deploy:cf:${{ github.ref == 'refs/heads/main' && '' || 'preview' }} env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}secrets.<APP>_ENV holds the raw env-file contents for that environment.
It is base64-decoded (or used directly, depending on the workflow) by the
Write env step.
Cloudflare Pages projects
Section titled “Cloudflare Pages projects”| App | wrangler.jsonc name |
|---|---|
apps/main-app-astro | sharp-go-main |
apps/weiqi-docs | sharp-go-docs |
apps/game-web | game-web |
apps/admin-app | (uses default — wrangler name) |
apps/comunity-app | weiqi-comunity-app |
Local auth
Section titled “Local auth”For a one-off deploy from your laptop:
pnpm --dir apps/weiqi-docs cf:login# Browser opens, you grant Pages:Edit on the account.pnpm --dir apps/weiqi-docs deploy:cf:previewcf:login writes the OAuth credentials to ~/.config/.wrangler/. They
expire after 30 days; re-run when wrangler complains.
Cloudflare adapter note
Section titled “Cloudflare adapter note”The adapter is wired up even for output: "static" sites because the
deploy infra assumes it. With output: "static", no _worker.js is
emitted, but the functions/ directory (if present) still deploys as Pages
Functions. Keep the adapter; do not remove it just because the site is
fully static.