-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Evaluate replacing the current Next.js + OpenNext for Cloudflare stack with cloudflare/vinext
Summary
cloudflare/vinext is now credible enough to evaluate seriously for this repo, but it is not yet a safe drop-in replacement for our current production path.
As of 2026-03-14:
- Cloudflare officially backs
vinextand positions it as a Vite-based reimplementation of the Next.js API surface for Cloudflare Workers and other targets. vinextis still explicitly marked as experimental / under heavy development.vinextitself says OpenNext is the more mature and safer option today for serious Next.js-on-Cloudflare deployments.
This issue tracks whether we should:
- keep the current
Next.js 16 + OpenNextstack as the default, - build a
vinextPoC branch in parallel, or - fully replace the current stack later if the migration risk becomes acceptable.
Why evaluate this now
- Vite continues to gain framework gravity, and Cloudflare is investing heavily in the Workers + Vite path.
vinextgives a Vite-first path for existing Next.js apps instead of adaptingnext buildoutput after the fact.- Cloudflare's Vite plugin runs app code in
workerdduring local development and preview, which is materially different from the current OpenNext model where day-to-day dev stays onnext devand Cloudflare behavior is validated later. - Vite 8 is now the current supported Vite major, so the broader ecosystem is clearly moving in this direction.
Current repo assumptions that matter
This repo is not just "a Next app":
Next.js 16App Routernext-rspack@opennextjs/cloudflare- custom
src/worker.tsthat combines:- web fetch handling via
.open-next/worker.js scheduled()cron handling viasrc/cron.ts
- web fetch handling via
- Cloudflare bindings used across the app:
D1KVWorkers AIImagesR2- service bindings / assets fetcher
next/image- dynamic OGP route
- Next middleware
- a server action (
src/lib/actions/report-error.ts) - tRPC route handlers and server components that currently resolve bindings via
getCloudflareContext() - custom
webpacklogic innext.config.ts - OpenNext-specific build patches/scripts/config:
open-next.config.tsscripts/patch-opennext-webpack-runtime.tsscripts/patch-opennext-setimmediate.tsbuild:cf,preview,upload,deploy
So this is not a bundler swap. It is a framework-runtime migration.
What vinext improves
1. Worker-native dev/build/runtime path
vinext uses @cloudflare/vite-plugin, and Cloudflare documents that this path runs code directly in the Workers runtime during local dev.
That is the main architectural attraction here:
- better local fidelity to
workerd - less OpenNext adapter indirection
- native
cloudflare:workersbindings access
2. Vite-first toolchain
vinext replaces the Next compiler/bundler path with Vite and @vitejs/plugin-rsc.
That gives us:
- access to the Vite ecosystem directly
- a more standard plugin model than our current
next-rspack + OpenNextpipeline - a clearer future path if the Vite/Workers ecosystem keeps consolidating
3. Simpler Cloudflare binding access model
vinext recommends import { env } from "cloudflare:workers" rather than getCloudflareContext() or a custom fetch(request, env) worker entry for routine binding access.
That likely simplifies a lot of the current binding plumbing in:
src/server/trpc/context.tssrc/server/db/index.tssrc/app/archive/page.tsxsrc/app/opengraph-image.tsxsrc/lib/workers-ai-client.ts
What vinext does not solve for us yet
1. It is still explicitly experimental
The vinext README is unusually direct:
- under heavy development
- use at your own risk
- not battle-tested at meaningful scale
That is not a footnote. It should directly affect migration timing.
2. OpenNext is still the safer production answer for Next.js on Cloudflare
This is stated both by:
- Cloudflare's official Next.js guide, which still points to OpenNext for Next.js on Workers
- the
vinextREADME itself, which says OpenNext is more mature and safer
3. Our current webpack / next-rspack customizations do not carry over
next.config.ts currently contains custom webpack logic for:
- alias stubbing during Cloudflare builds
- vendor chunking
- wallet / 3D / Metaplex bundle handling
vinext check flags this directly:
webpackconfig is unsupported and needs migration to Vite equivalents
This means we must either:
- re-express the intent in Vite config/plugins/manual chunking, or
- delete those optimizations and verify that the resulting bundle/runtime still behaves correctly
4. Our current cron model is a real migration problem
Today we rely on:
src/worker.tsforfetchsrc/worker.tsforscheduled
vinext's Cloudflare story is optimized around the app request pipeline, not around our current "single worker handles both web and cron" structure.
The likely migration outcome is:
- the web app moves to
vinext - the scheduled generation pipeline moves to a separate Worker, or another Cloudflare-managed entrypoint
That split is probably the right architecture anyway, but it is still a migration cost.
5. next/image behavior changes
vinext marks next/image as partial support:
- remote images are handled via
@unpic/react - local build-time optimization is not there yet
imagesconfig is parsed but not used for optimization
This matters here because we currently rely on:
next/imageimages.remotePatterns- Cloudflare image handling around our archive / OGP / Arweave gateway usage
We should assume image behavior changes unless we test it directly.
6. A few repo-specific features are only partial / caveated
vinext check on this repo reported:
- 77% compatible
- unsupported:
webpackexperimental.typedRoutes- missing
"type": "module" - one unrecognized
next/dist/server/next-server.jsimport path that needs source confirmation
- partial:
next/font/googleimagesViewTransition
The ViewTransition finding is specifically relevant because this repo currently sets experimental.viewTransition in next.config.ts.
Repo-specific migration surface
These are the concrete places we would need to touch for a real vinext migration.
A. Build and deployment layer
package.jsonnext.config.tsopen-next.config.tswrangler.tomlsrc/worker.tsscripts/patch-opennext-webpack-runtime.tsscripts/patch-opennext-setimmediate.ts
Expected changes:
- add
"type": "module" - replace
next/opennextjs-cloudflarescripts withvinext/ Vite equivalents - introduce
vite.config.ts - remove OpenNext patch scripts/config if no longer needed
- decide where cron lives after the split
B. Cloudflare bindings access
Current access is heavily tied to @opennextjs/cloudflare.
Likely migration direction:
- replace
getCloudflareContext()access withcloudflare:workers - make sure no top-level I/O happens before bindings are safe to read
Affected areas include:
- DB creation
- tRPC context
- archive page data loading
- OGP route
- Workers AI client
C. Worker entrypoint shape
Current state:
- one Worker for both fetch and scheduled
Likely vinext state:
- app request worker handled by
vinext - scheduled generation moved elsewhere
Possible directions:
- separate scheduled Worker with its own trigger and service bindings
- multi-Worker setup using Cloudflare's newer auxiliary Worker story where appropriate
- validate whether a custom
vinextCloudflare entrypoint can still hostscheduled()cleanly
At the moment, option 1 looks like the lowest-risk migration shape.
D. Next-specific features that must be regression-tested
- App Router pages/layouts
- route handlers (
src/app/api/trpc/...) - Next middleware (
src/middleware.ts) - dynamic OGP (
src/app/opengraph-image.tsx) - server action (
src/lib/actions/report-error.ts) next/image- metadata generation
- MDX setup
Recommended migration approach
Recommendation now
Do not replace the mainline production stack immediately.
The evidence today supports:
- keep
Next.js + OpenNextas the default production path - build a focused
vinextevaluation branch / spike - revisit replacement only after repo-specific gates are proven
Phase 1: low-risk evaluation branch
Create a vinext spike branch that does the minimum needed to answer the real questions:
- run
vinext init - add the required Cloudflare App Router Vite config
- get the web request path booting under
vinext - do not migrate cron yet; split or stub it intentionally
- replace
getCloudflareContext()usage withcloudflare:workerswhere needed for the web path
Phase 2: port repo-specific platform concerns
After the web app boots:
- port or remove custom
webpackbehavior - validate bundle behavior for:
- Three.js
- Solana wallet deps
- Metaplex deps
- MDX
- validate
next/imagebehavior against Arweave / permagate usage - validate middleware and OGP routes on Workers
Phase 3: split cron cleanly
Move the scheduled generation path out of the framework entrypoint:
- extract cron-specific binding/runtime code into its own Worker boundary
- keep D1 / AI / asset fetch dependencies explicit
- validate local/dev/prod behavior separately from the web app
This split should probably happen even if we ultimately stay on OpenNext.
Success criteria for saying "vinext is viable here"
vinext devworks for the web app- Cloudflare preview/deploy works for the web app
- archive page works with D1 on Workers
- tRPC route handlers work
- middleware works as expected
- dynamic OGP works
next/imagebehavior is acceptable for current archive/gallery usage- no unacceptable regressions in bundle size or boot/runtime stability
- cron pipeline has a clean post-OpenNext story
Decision criteria for full replacement
We should only replace the current stack if the spike proves all of the following:
- developer experience is materially better, not just different
- Worker-runtime fidelity meaningfully reduces bugs or complexity
- we can remove more complexity than we add
- cron has a clean architecture after the split
- image / metadata / middleware behavior stays acceptable
- the remaining
vinextmaturity risk is acceptable for production
If those are not true, we should keep OpenNext and revisit later.
Source notes
Primary sources checked on 2026-03-14:
- Cloudflare launch post for
vinext(2026-02-24) cloudflare/vinextREADME and current repo- latest
vinextrelease visible during review:v0.0.30(2026-03-13) vinextissue about currently Cloudflare-specific deployment adapters- Cloudflare Workers Vite plugin docs
- Cloudflare
cloudflare:workersenv docs - Cloudflare changelog for auxiliary Workers in Vite-backed full-stack setups (2026-01-15)
- Cloudflare Next.js on Workers guide
- OpenNext Cloudflare get-started docs
- Vite releases / migration direction / SSR docs
Appendix: vinext check result on this repo
Ran on 2026-03-14 with:
bunx vinext@latest checkKey output:
- overall:
77% compatible - issues:
webpackexperimental.typedRoutes- missing
"type": "module" - unrecognized
next/dist/server/next-server.js
- partial support:
next/font/googleimagesViewTransition