Cloudflare Opennext
Deploy Next.js to Cloudflare Workers with full App Router, Pages Router, ISR, and SSG support. Load when creating Next.js projects for Workers, migrating from Vercel/next-on-pages, configuring caching (R2/KV/D1), accessing Cloudflare bindings via getCloudflareContext, or fixing bundle size issues.
- Skill ID
- null-shot/cloudflare-skills/cloudflare-opennext
- Publisher
- null-shot
- Repository
- cloudflare-skills
- Installs
- 0
- Files
- 5
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
null-shot/cloudflare-skills/cloudflare-opennextInstalls these files- SKILL.md
- references/caching.md
- references/configuration.md
- references/database-orm.md
- references/troubleshooting.md
What this skill tells the agent
Cloudflare OpenNext
Deploy Next.js applications to Cloudflare Workers using the @opennextjs/cloudflare adapter with full support for App Router, Pages Router, ISR, SSG, and Cloudflare bindings.
When to Use
- Creating new Next.js apps for Cloudflare Workers
- Migrating existing Next.js apps to Cloudflare
- Configuring ISR/SSG caching with R2, KV, or D1
- Accessing Cloudflare bindings (KV, R2, D1, Durable Objects, AI)
- Using databases and ORMs (Drizzle, Prisma) in Next.js
- Troubleshooting deployment issues or bundle size problems
Getting Started
New App
npm create cloudflare@latest -- my-next-app --framework=next --platform=workers
cd my-next-app
npm run dev # Local development with Next.js
npm run preview # Preview in Workers runtime
npm run deploy # Deploy to CloudflareExisting App Migration
# 1. Install dependencies
npm install @opennextjs/cloudflare@latest
npm install --save-dev wrangler@latest
# 2. Create wrangler.jsonc (see Configuration section)
# 3. Create open-next.config.ts
# 4. Update next.config.ts
# 5. Add scripts to package.json
# 6. Deploy
npm run deployCore Concepts
How OpenNext Works
The @opennextjs/cloudflare adapter:
- Runs
next buildto generate the Next.js build output - Transforms the build output to work in Cloudflare Workers runtime
- Outputs to
.open-next/directory withworker.jsentry point - Uses Workers Static Assets for static files (
_next/static,public)
Node.js Runtime (Not Edge)
Critical: OpenNext uses Next.js Node.js runtime, NOT the Edge runtime:
// ❌ Remove this - Edge runtime not supported
export const runtime = "edge";
// ✅ Default Node.js runtime - fully supported
// No export needed, this is the defaultThe Node.js runtime provides:
- Full Node.js API compatibility via
nodejs_compatflag - More Next.js features than Edge runtime
- Access to all Cloudflare bindings
Configuration Files
wrangler.jsonc
Minimal configuration for OpenNext:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-nextjs-app",
"main": ".open-next/worker.js",
"compatibility_date": "2024-12-30",
"compatibility_flags": [
"nodejs_compat", // Required for Node.js APIs
"global_fetch_strictly_public" // Security: prevent local IP fetches
],
"assets": {
"directory": ".open-next/assets", // Static files
"binding": "ASSETS"
},
"services": [
{
"binding": "WORKER_SELF_REFERENCE",
"service": "my-nextjs-app" // Must match "name" above
}
],
"images": {
"binding": "IMAGES" // Optional: Enable image optimization
}
}Required settings:
nodejs_compatcompatibility flagcompatibility_date>=2024-09-23WORKER_SELF_REFERENCEservice binding (must match worker name)mainandassetspaths should not be changed
See references/configuration.md for complete configuration with R2, KV, D1 bindings.
open-next.config.ts
Configure caching and OpenNext behavior:
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: r2IncrementalCache,
});This file is auto-generated if not present. See references/caching.md for cache options.
next.config.ts
Initialize OpenNext for local development:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// Your Next.js configuration
};
export default nextConfig;
// Enable bindings access during `next dev`
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
initOpenNextCloudflareForDev();.dev.vars
Environment variables for local development:
# .dev.vars
NEXTJS_ENV=developmentThe NEXTJS_ENV variable selects which Next.js .env file to load:
development→.env.developmentproduction→.env.production(default)
Accessing Cloudflare Bindings
Use getCloudflareContext() to access bindings in any route:
import { getCloudflareContext } from "@opennextjs/cloudflare";
// Route Handler (App Router)
export async function GET(request: Request) {
const { env, cf, ctx } = getCloudflareContext();
// Access KV
const value = await env.MY_KV.get("key");
// Access R2
const object = await env.MY_BUCKET.get("file.txt");
// Access D1
const result = await env.DB.prepare("SELECT * FROM users").all();
// Access Durable Objects
const stub = env.MY_DO.idFromName("instance-1");
const doResponse = await stub.fetch(request);
// Access request info
const country = cf?.country;
// Background tasks
ctx.waitUntil(logAnalytics());
return Response.json({ value });
}
// API Route (Pages Router)
export default async function handler(req, res) {
const { env } = getCloudflareContext();
const data = await env.MY_KV.get("key");
res.json({ data });
}
// Server Component
export default async function Page() {
const { env } = getCloudflareContext();
const data = await env.MY_KV.get("key");
return <div>{data}</div>;
}SSG Routes with Async Context
For Static Site Generation routes, use async mode:
// In SSG route (generateStaticParams, etc.)
const { env } = await getCloudflareContext({ async: true });
const products = await env.DB.prepare("SELECT * FROM products").all();Warning: During SSG, secrets from .dev.vars and local binding values are included in the static build. Be careful with sensitive data.
TypeScript Types
Generate types for your bindings:
npx wrangler types --env-interface CloudflareEnv cloudflare-env.d.tsAdd to package.json:
{
"scripts": {
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
}
}Run after any binding changes in wrangler.jsonc.
CLI Commands
The opennextjs-cloudflare CLI wraps Wrangler with OpenNext-specific behavior:
# Build the Next.js app and transform for Workers
npx opennextjs-cloudflare build
# Build and preview locally with Wrangler
npm run preview
# or
npx opennextjs-cloudflare preview
# Build and deploy to Cloudflare
npm run deploy
# or
npx opennextjs-cloudflare deploy
# Build and upload as a version (doesn't deploy)
npm run upload
# or
npx opennextjs-cloudflare upload
# Populate cache (called automatically by preview/deploy/upload)
npx opennextjs-cloudflare populateCache local # Local bindings
npx opennextjs-cloudflare populateCache remote # Remote bindingsRecommended package.json scripts:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
}
}Caching Strategies
OpenNext supports Next.js caching with Cloudflare storage:
| Cache Type | Use Case | Storage Options |
|---|---|---|
| Incremental Cache | ISR/SSG page data | R2, KV, Static Assets |
| Queue | Time-based revalidation | Durable Objects, Memory |
| Tag Cache | On-demand revalidation | D1, Durable Objects |
Quick setup examples:
// Static Site (SSG only)
import staticAssetsCache from "@opennextjs/cloudflare/overrides/incremental-cache/static-assets-incremental-cache";
export default defineCloudflareConfig({
incrementalCache: staticAssetsCache,
enableCacheInterception: true,
});
// Small Site with ISRUse this skill in a project
Open any RiverX project, search the Skills panel for null-shot/cloudflare-skills/cloudflare-opennext, and install it in one click.
