If you've tried deploying Next.js 15 App Router to
Cloudflare Workers, you've probably hit builds that
randomly fail with cryptic errors.
I've been running a production app on CF Workers for
months. Here are the 4 bugs I found — none of them
are documented in one place.
Bug 1: Race condition on pages-manifest.json
Next.js 15.5+ uses worker threads during build. This
causes intermittent ENOENT errors:
Error: ENOENT: no such file or directory,
open '.next/server/pages-manifest.json'
Fix: Disable worker threads in your build script:
process.env.NEXT_PRIVATE_WORKER_THREADS = 'false'
Bug 2: pages-manifest.json is never generated
App Router-only projects don't generate
pages-manifest.json — but opennextjs-cloudflare
requires it at deploy time.
Fix: Pre-create it after build:
const manifest = {
'/_app': 'pages/_app.js',
'/_document': 'pages/_document.js',
'/_error': 'pages/_error.js',
}
fs.writeFileSync(manifestPath, JSON.stringify(manifest))
Bug 3: Turbopack stubs break esbuild
Next.js generates Pages Router stubs that reference
[turbopack]_runtime.js. This causes esbuild to
fail silently during the Cloudflare bundle step.
Fix: Delete the stubs after Next.js build completes:
const stubFiles = ['_app.js', '_document.js', '_error.js']
for (const f of stubFiles) {
const p = path.join(pagesDir, f)
if (fs.existsSync(p)) fs.unlinkSync(p)
}
Bug 4: Supabase auth cookies break on edge
The standard Supabase client stores cookies in a way
that doesn't work on Cloudflare Workers (no
document.cookie access in SSR context).
Fix: Use @supabase/ssr with explicit cookie handlers:
import { createServerClient } from '@supabase/ssr'
export function createClient() {
const cookieStore = cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return cookieStore.getAll() },
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
},
},
}
)
}
Putting it all together
All 4 fixes live in a single scripts/build.mjs that
wraps next build. Run it instead of next build
directly.
I packaged this build script along with all the other
patterns (Tailwind CSS 4, i18n, PWA, security headers,
WCAG 2.2 AA) into a starter template:
👉 Edge Starter on Lemon Squeezy — $39
The template builds consistently and is tested in
production. Happy to answer questions about any of
the fixes in the comments.
Top comments (0)