diff --git a/.github/workflows/deploy-cloudflare-pages.yml b/.github/workflows/deploy-cloudflare-pages.yml index 81d5072..21f818c 100644 --- a/.github/workflows/deploy-cloudflare-pages.yml +++ b/.github/workflows/deploy-cloudflare-pages.yml @@ -23,11 +23,7 @@ jobs: 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: "" + - run: npm run build:cf - name: Publish to Cloudflare Pages uses: cloudflare/wrangler-action@v3 with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0ac60fb..d9382f8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -24,7 +24,7 @@ jobs: node-version: 20 cache: npm - run: npm ci - - run: npx next build + - run: npm run build:gh - uses: actions/upload-pages-artifact@v3 with: path: out diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md index fdfe53b..ec520a3 100644 --- a/docs/deployment-guide.md +++ b/docs/deployment-guide.md @@ -1,29 +1,45 @@ # Deployment Guide +## Build Profiles + +Two named profiles select the basePath for the deploy target: + +| Script | basePath | Target URL | +|---|---|---| +| `npm run build:gh` | `/loto` | `https://tiennm99.github.io/loto` | +| `npm run build:cf` | `""` (root) | `https://loto.miti99.com` | +| `npm run build` | `/loto` | legacy default — same as `build:gh` | + +Implementation: `next.config.mjs` reads `BUILD_PROFILE` (`gh` or `cf`) and +picks the basePath. `NEXT_BASE_PATH` overrides everything for one-off +custom-domain builds. + ## Production Deployment -### GitHub Pages (default) +### GitHub Pages -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`. +Auto-deploys from `master` via `.github/workflows/deploy.yml`. Runs +`npm run build:gh`, then uploads `out/` as a Pages artifact. -basePath is set to `/loto` because GH Pages serves the project under that path -prefix. See `next.config.mjs`. +URL: `https://tiennm99.github.io/loto`. basePath `/loto` because GH Pages +serves the project under that path prefix. ### Cloudflare Pages -Two ways to wire it up: +Custom domain target: `https://loto.miti99.com` (basePath `""`). **Option A — Dashboard:** -1. dash.cloudflare.com → Workers & Pages → Create → Pages → Connect to Git → pick the repo +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 command: `npm run build:cf` - 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. +3. After first deploy, add the custom domain: + Project → Custom domains → `loto.miti99.com`. Cloudflare gives DNS + records to add at your registrar (or auto-configures if `miti99.com` is + on Cloudflare DNS). **Option B — GitHub Actions (`.github/workflows/deploy-cloudflare-pages.yml`):** @@ -32,17 +48,18 @@ Add two repo secrets: `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 workflow runs `npm run build:cf`, then publishes `out/` via +`cloudflare/wrangler-action@v3` to a Pages project named `loto`. Custom +domain setup is the same dashboard step as Option A — done once. -The two providers can run in parallel — they don't conflict. Disable whichever -you stop wanting by deleting its workflow file. +The two providers can run in parallel — different artifacts, different +URLs. Drop whichever you stop wanting by deleting its workflow file. ### Manual Deploy ```bash -npm run build +npm run build:gh # for GH Pages +npm run build:cf # for CF Pages / any root-served host # out/ directory ready for upload to any static host ``` diff --git a/next.config.mjs b/next.config.mjs index 7f6a112..2ef92dd 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,8 +1,10 @@ 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"; + +// Build profiles select basePath for the deploy target: +// gh — GitHub Pages, served at tiennm99.github.io/loto +// cf — Cloudflare Pages, served at loto.miti99.com (custom domain, root) +const buildProfile = process.env.BUILD_PROFILE; // In dev under code-server's reverse proxy, basePath/assetPrefix must match // the proxy URL so links, assets, and the HMR socket all resolve. @@ -21,11 +23,23 @@ function codeserverConfig() { } const cs = isCodeserver ? codeserverConfig() : null; -// NEXT_BASE_PATH wins so custom-domain / fork deploys don't have to edit code. + +// basePath resolution order (first non-null wins): +// 1. NEXT_BASE_PATH — explicit override (escape hatch for forks / custom domains) +// 2. codeserver dev profile +// 3. BUILD_PROFILE=gh|cf — explicit deploy target +// 4. NODE_ENV=production — legacy fallback (bare `npm run build` → GH Pages) +// 5. local dev — empty const basePath = process.env.NEXT_BASE_PATH ?? cs?.basePath ?? - (isCfPages ? "" : isProd ? "/loto" : ""); + (buildProfile === "gh" + ? "/loto" + : buildProfile === "cf" + ? "" + : isProd + ? "/loto" + : ""); const nextConfig = { output: "export", diff --git a/package.json b/package.json index 7ad817e..905587e 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,8 @@ "dev": "next dev", "dev:codeserver": "NEXT_DEV_PROFILE=codeserver next dev -H 0.0.0.0", "build": "next build", + "build:gh": "BUILD_PROFILE=gh next build", + "build:cf": "BUILD_PROFILE=cf next build", "start": "next start", "lint": "eslint" },