Back to all posts
Tutorial

The Ultimate Fix: Migrating Next.js 15 from Cloudflare Pages to Workers with OpenNext

If you've been building Next.js 15 applications and deploying them to Cloudflare Pages using @cloudflare/next-on-pages, you've likely hit a wall.

The dreaded "Invalid prerender config" error, inconsistent static and dynamic route rendering, and edge runtime configuration clashes have been major headaches for the community. After hours of debugging these exact issues on my portfolio site, I finally found the bulletproof solution: Migrating from Cloudflare Pages to Cloudflare Workers using OpenNext.

In this guide, I'll show you exactly why Next.js on Pages fails and how to cleanly migrate your architecture to Cloudflare Workers for a flawless, robust deployment.


The Problem: Next-on-Pages Limitations

Cloudflare Pages was originally designed for purely static sites. While it has evolved to support server-side rendering (SSR) and Edge Functions via @cloudflare/next-on-pages, the integration with Next.js 15's App Router remains fragile.

When you mix static SSG routes (like blog posts) with dynamic edge routes (like API endpoints or database queries), the build process often chokes:

Error: Invalid prerender config for /app/[locale]/about
The following routes were not configured to run with the Edge Runtime...

The underlying issue is a misalignment between how Vercel's build output expects functions to be structured and how next-on-pages interprets them for the Pages environment.


The Solution: OpenNext and Cloudflare Workers

Instead of fighting the Pages build system, the modern approach is to use OpenNext (@opennextjs/cloudflare) and deploy directly to Cloudflare Workers.

Workers provide a true serverless execution environment that perfectly aligns with Next.js's SSR and API route requirements, while Cloudflare Assets handles the static files.

Here is the step-by-step migration path.


Step 1: Install Dependencies

Remove next-on-pages and install OpenNext for Cloudflare:

npm uninstall @cloudflare/next-on-pages
npm install -D @opennextjs/cloudflare

Step 2: Configure OpenNext

Create an open-next.config.ts file in the root of your project. This tells OpenNext how to adapt your Next.js build for Cloudflare:

import type { OpenNextConfig } from 'open-next/types/open-next.js';

export default {
  default: {
    override: {
      wrapper: 'cloudflare-node',
      converter: 'edge',
      incrementalCache: 'dummy',
      tagCache: 'dummy',
      queue: 'dummy',
    },
  },
  middleware: {
    external: true,
    override: {
      wrapper: 'cloudflare-edge',
      converter: 'edge',
      proxyExternalRequest: 'fetch',
    },
  },
} as OpenNextConfig;

Step 3: Set Up Wrangler for Workers

You need a wrangler.jsonc (or wrangler.toml) to define your Worker deployment. Notice how we point the main entry to the generated OpenNext worker, and bind the static assets.

{
  "main": ".open-next/worker.js",
  "name": "your-project-name",
  "compatibility_date": "2026-06-15",
  "compatibility_flags": [
    "nodejs_compat"
  ],
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  }
}

Step 4: Update Build Scripts

Update your package.json to build with Next.js first, then process with OpenNext:

"scripts": {
  "build": "next build && opennextjs-cloudflare",
  "preview": "npm run build && wrangler dev",
  "deploy": "npm run build && wrangler deploy"
}

Step 5: Clean Up Edge Configs

With OpenNext, you no longer need to strictly enforce export const runtime = 'edge' at the top of every single dynamic file just to appease the build system. OpenNext's cloudflare-node wrapper intelligently handles Node.js APIs and Edge APIs, drastically simplifying your codebase.


What About Cloudflare R2?

During this migration, you might wonder if you need to provision a Cloudflare R2 bucket.

The short answer: No, not immediately. Your Next.js static assets (images, CSS, JS chunks) are perfectly served by the Cloudflare Assets binding defined in your wrangler.jsonc.

However, if your application scales to handle user-uploaded media, large videos, or massive datasets, R2 seamlessly integrates into this Worker architecture. You simply bind the R2 bucket in your wrangler.jsonc and access it via env.MY_BUCKET in your Server Actions or API routes.

The Result

By migrating to Cloudflare Workers with OpenNext, you achieve:

  • Zero build errors: No more tearing your hair out over prerender configs.
  • Flawless localization: Internationalized routing (/[locale]/) works out of the box.
  • Node.js compatibility: The nodejs_compat flag allows for broader npm package support.

Cloudflare Pages is fantastic for simple static sites, but for ambitious Next.js 15 applications, OpenNext on Cloudflare Workers is the definitive way forward.