My old domain expired, so this site needed a home while I sort out a new one. Rather than wait, I set up GitHub Pages as a temporary deployment target alongside the existing Cloudflare Pages setup. Here's what that actually involved.
Why Run Two Deployments
The site was already deploying to Cloudflare Pages as a static export, triggered on every push to master. Rather than rip that out, I added GitHub Pages as a second, independent deployment target:
- Cloudflare keeps deploying exactly as before, no changes to that workflow.
- A new GitHub Actions workflow builds the same static export and publishes it to GitHub Pages.
- Once a new domain is in place, the GitHub Pages deployment can be dropped without touching anything Cloudflare-related.
Making One Build Work for Both Hosts
The two hosts don't serve the site from the same place. Cloudflare serves it from the domain root; GitHub Pages serves a project site from a /portfolio subpath, since the URL is username.github.io/portfolio. Next.js handles this with basePath and assetPrefix, but those need to differ per deployment target from the exact same codebase.
Conditional Base Path
The fix was a single environment variable read at build time:
const isGithubPages = process.env.GITHUB_PAGES === "true";
const nextConfig = {
basePath: isGithubPages ? "/portfolio" : undefined,
assetPrefix: isGithubPages ? "/portfolio/" : undefined,
};The GitHub Pages workflow sets GITHUB_PAGES=true before running the build; the Cloudflare workflow doesn't set it at all, so it falls through to the root-relative behavior it already had.
Static Export and Image Optimization
Next.js's built-in image optimizer needs a server to run on. Neither deployment target has one for this static export, which meant next/image usage anywhere in the app would silently 404 in production. Setting images.unoptimized: true was the fix — it was arguably already a latent bug on Cloudflare, just one that hadn't been noticed yet.
What's Next
Once a new domain is bought and pointed at Cloudflare, the GitHub Pages workflow and this temporary URL go away, and the canonical site URL swaps back over. Until then, this is the live version.