Codify SaaS Blog
Code-first guides and deep dives on building B2B SaaS products, designing APIs, scaling web apps, and modernizing legacy software.

Next.js Server Actions Not Working With Static Export
A form submission using a Server Action works perfectly against next dev. Set output: 'export' and run the build, and Next.js stops the build cold with an error naming Server Actions specifically — sometimes for a form you wrote, sometimes for one you didn't even know existed, quietly pulled in by a library import.

Next.js Static Export Blank Page on Cloudflare Pages
The build log says success. Every step completed, no errors, a green checkmark all the way down. Open the actual deployed URL, and there's nothing there — no error page, no 404, just white space where a website should be. A successful build and a working site are two different claims, and this bug lives in the gap between them.

Next.js Build Failing on Vercel But Working Locally — Cache Corruption Fix
next build finishes cleanly on your machine. Push the exact same commit, and Vercel fails with an error that has nothing to do with anything you changed. Retrying the deploy doesn't help, because a failed build never overwrites the cache that's causing the problem — you're stuck redeploying against the same broken state until you explicitly tell Vercel to skip it.

Next.js Hydration Mismatch Only in Production, Not in Dev
Every local run is clean. Deploy the exact same commit, and the console fills with hydration mismatch warnings the moment a real user loads the page. It's not that dev is hiding a bug production reveals — it's that dev and production genuinely aren't the same environment, and this bug only exists in the gap between them.

Next.js App Router Params Promise Breaking Change (Next 15) in Production
The upgrade to Next.js 15 went smoothly. Locally, everything type-checked, everything ran. Then a build somewhere else — CI, a teammate's clean clone — starts throwing errors on params.slug, treating params like an object when your code has always read it as one. Nothing about your logic changed. params itself did.

Next.js Environment Variables Undefined After Docker Build
The .env file is right there in the repo. The variable works perfectly in local dev. Build the same code into a Docker image, and the value your frontend reads back is undefined — not wrong, not empty string, genuinely undefined, as if the variable never existed at all.

Next.js Image Optimization Failing on Static Export
next/image worked fine in dev, and the moment you run output: export, the build either throws outright or ships images that were never actually optimized at all. Neither is a bug. The default image optimizer needs a running server to resize images on demand, and a static export, by definition, doesn't have one.

Next.js ISR Not Revalidating on Self-Hosted Docker Deployments
revalidate is set. The page should update. Refresh it enough times, though, and you get two or three different versions of the same page depending on which container happened to answer — because ISR's default cache lives on each container's own disk, and nothing is telling the other replicas a page just changed.

Next.js Middleware Not Running on Cloudflare Pages
The exact same middleware that redirects, rewrites, and checks auth cleanly on Vercel just doesn't fire on Cloudflare — no error, no log line, it simply never runs. Before troubleshooting the middleware itself, it's worth knowing that a lot of the guidance still floating around for 'Next.js on Cloudflare Pages' describes a setup Cloudflare has since moved away from entirely.

Next.js API Routes Not Working With output: export — What to Use Instead
Weeks into a project, someone reaches for an API route to handle a form submission or a webhook — and discovers output: export doesn't support it at all, not as a bug to patch, but as a fundamental incompatibility. The frustrating part isn't the limitation. It's finding out this late, after the frontend and the missing backend have already grown apart.

Next.js "Dynamic Server Usage" Breaking Static Export Builds
The build was clean for months. Then a routine feature — reading a cookie, checking a request header — quietly breaks next build with output: export, and the error message names an API that doesn't obviously look dynamic at all. It's not a bug in the API. It's static export refusing to pretend a server exists at request time when there isn't going to be one.

BullMQ Sandboxed Processors Failing to Load in Docker Production Build
The sandboxed processor runs perfectly in local development with ts-node watching your source files. Build the same code into a Docker image, and the worker throws a file-not-found error the moment it tries to load the processor — because a sandboxed processor doesn't get compiled into your bundle the way the rest of your code does. It's loaded from disk, by an explicit path, at runtime.