diff --git a/.github/workflows/deploy-cloudflare-pages.yml b/.github/workflows/deploy-cloudflare-pages.yml new file mode 100644 index 0000000..81d5072 --- /dev/null +++ b/.github/workflows/deploy-cloudflare-pages.yml @@ -0,0 +1,36 @@ +name: Deploy to Cloudflare Pages + +on: + push: + branches: [master] + workflow_dispatch: + +permissions: + contents: read + deployments: write + +concurrency: + group: cf-pages + cancel-in-progress: true + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run build + env: + # Force root basePath: CF Pages serves the site at the project root + # (loto.pages.dev), unlike GH Pages which prefixes with /loto. + NEXT_BASE_PATH: "" + - name: Publish to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy out --project-name=loto --branch=${{ github.ref_name }} diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md index 6959f08..fdfe53b 100644 --- a/docs/deployment-guide.md +++ b/docs/deployment-guide.md @@ -1,26 +1,51 @@ # Deployment Guide -## Production Deployment (GitHub Pages) +## Production Deployment -### Automatic Deploy -The app auto-deploys from the `master` branch via `.github/workflows/deploy.yml`. +### GitHub Pages (default) -**Workflow**: -1. Push to `master` -2. GitHub Actions runs `npm run build` -3. Static export written to `out/` directory -4. Pages deployed to `https://{user}.github.io/loto` +Auto-deploys from `master` via `.github/workflows/deploy.yml`. Static export is +written to `out/`, then uploaded as a Pages artifact. Reachable at +`https://{user}.github.io/loto`. -**Note**: basePath is set to `/loto` in production (`next.config.mjs:23`). +basePath is set to `/loto` because GH Pages serves the project under that path +prefix. See `next.config.mjs`. + +### Cloudflare Pages + +Two ways to wire it up: + +**Option A — Dashboard:** +1. dash.cloudflare.com → Workers & Pages → Create → Pages → Connect to Git → pick the repo +2. Build settings: + - Framework preset: `Next.js (Static HTML Export)` + - Build command: `npm run build` + - Build output directory: `out` + - Production branch: `master` +3. No env vars needed — `next.config.mjs` detects `CF_PAGES=1` (auto-injected by + Cloudflare) and switches basePath to root automatically. + +**Option B — GitHub Actions (`.github/workflows/deploy-cloudflare-pages.yml`):** + +Add two repo secrets: +- `CLOUDFLARE_API_TOKEN` — dash → My Profile → API Tokens → Create with the + `Pages — Edit` template +- `CLOUDFLARE_ACCOUNT_ID` — visible in the dash sidebar + +Then push to `master` and the workflow uses `cloudflare/wrangler-action@v3` to +publish `out/` to a Pages project named `loto`. The workflow sets +`NEXT_BASE_PATH=""` explicitly so the build produces root-relative asset paths. + +The two providers can run in parallel — they don't conflict. Disable whichever +you stop wanting by deleting its workflow file. + +### Manual Deploy -### Manual Deploy (if needed) ```bash npm run build -# out/ directory ready for upload +# out/ directory ready for upload to any static host ``` -Then deploy `out/` folder to GitHub Pages or any static host. - ## Development Environment ### Local Dev diff --git a/next.config.mjs b/next.config.mjs index 1ae7b0b..7f6a112 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,5 +1,8 @@ const isProd = process.env.NODE_ENV === "production"; const isCodeserver = process.env.NEXT_DEV_PROFILE === "codeserver"; +// Cloudflare Pages injects CF_PAGES=1 during its build; avoid the GH Pages +// /loto basePath there since CF serves the site at the root. +const isCfPages = process.env.CF_PAGES === "1"; // In dev under code-server's reverse proxy, basePath/assetPrefix must match // the proxy URL so links, assets, and the HMR socket all resolve. @@ -20,7 +23,9 @@ function codeserverConfig() { const cs = isCodeserver ? codeserverConfig() : null; // NEXT_BASE_PATH wins so custom-domain / fork deploys don't have to edit code. const basePath = - process.env.NEXT_BASE_PATH ?? cs?.basePath ?? (isProd ? "/loto" : ""); + process.env.NEXT_BASE_PATH ?? + cs?.basePath ?? + (isCfPages ? "" : isProd ? "/loto" : ""); const nextConfig = { output: "export",