replicate/getting-started-vinext: The Next.js Starter That Isn’t Running Next.js

It keeps the App Router feel, routes AI inference through Replicate, and shows how vinext and Cloudflare Workers can carry the stack without the usual Node-heavy assumptions.

8 min read • View on GitHub • More from replicate

A wide workshop scene shows a familiar web app blueprint being mounted onto a lighter chassis beside a tall edge tower. The image visualizes the article's thesis that the front-end experience stays recognizable even when the runtime changes.
The real story is not the model. It is the machine underneath it.

This is a vinext starter app that uses Replicate to generate images with [FLUX.2 [klein]]. It deploys to Cloudflare Workers.

zeke, Top Contributor · replicate/getting-started-vinext
Key Takeaways

A Next.js starter with a different engine

At first glance, this looks like another Replicate starter. It is actually a bet that the App Router experience can live outside Next.js, on vinext, Vite, and Cloudflare Workers.

That is the useful twist. The repo keeps the familiar folder shape, route handlers, and client patterns, then changes the machine underneath them. The AI demo is real, but it is also a decoy that hides the deeper story: runtime portability.

A split scene contrasts a heavy adapter stack on the left with a compact edge-native setup on the right. It explains why patching a framework is different from re-platforming its runtime.
The point is not to imitate Next.js forever. It is to keep the ergonomics while changing the engine.

Why vinext exists at all

vinext exists because a lot of developers want Next.js-like DX without inheriting a Node-first runtime. This starter is a practical proof that you can keep the mental model and move the deployment target to Cloudflare Workers.

That shows up everywhere in the repo. You see App Router conventions next to Cloudflare-specific files like `wrangler.jsonc` and `.dev.vars`, which is a quiet but important signal that the app was built for the edge, not translated there after the fact.

Hedcut portrait of zeke, the repository's top contributor.

The quote is blunt because the repo is blunt. It is not trying to reinvent generative AI. It is trying to make a familiar React app shape fit an edge runtime without forcing every team through an adapter maze.

One prediction, two clocks

The most interesting machinery in the repo is the prediction lifecycle. The browser starts a mutation, the app polls for immediate state, and Replicate sends a signed webhook when the job is actually done.

Polling gives the UI immediate feedback. The webhook gives the result a trustworthy finish line.

const query = useQuery({
  queryKey: ['prediction', id],
  queryFn: () => fetch(`/api/predictions/${id}`).then((r) => r.json()),
  refetchInterval: (state) => {
    const status = state.state.data?.status;
    return status === 'succeeded' || status === 'failed' ? false : 250;
  },
});

That is a smart split. Polling makes the interface feel alive the moment the user clicks, while the webhook route is what lets the app trust completion data instead of hoping the tab stays open.

The webhook handler also does the unglamorous work that matters in production. It clones the request before validation, then verifies the signature so only Replicate can finalize the state.

The Worker shim that makes images feel native

The cleanest edge-specific trick is in `worker/index.ts`. It intercepts `/_vinext/image`, sends that path through Cloudflare Images, and lets every other request flow into the vinext handler untouched.

A narrow gate diverts one stream through a lens-like processor while the main flow keeps moving. The image explains how `/_vinext/image` is intercepted without turning the worker into a general-purpose server.
One route gets special treatment. Everything else keeps moving through the same lightweight edge runtime.
if (new URL(request.url).pathname === '/_vinext/image') {
  // Route the request through Cloudflare Images, then return the optimized asset.
}

return vinextHandler.fetch(request, env);

This is the pattern repeated across the repo. Instead of asking Next.js to behave everywhere, the app carves out a few edge-native bridges and keeps the rest simple. That keeps the surface familiar and the runtime small.

What this starter proves, and what it does not

The comparison is not really between image models. It is between runtime strategies. Replicate/getting-started-vinext preserves the App Router feel, Replicate/getting-started-nextjs stays with the canonical Next.js path, and adapter-based deployments like OpenNext try to translate between the two.

ProjectRuntime modelDeployment targetImage handlingWebhook supportOperational complexityBest fit
replicate/getting-started-vinextNext.js-style App Router on vinext and ViteCloudflare WorkersWorker shim maps `/_vinext/image` to Cloudflare ImagesValidated webhook plus pollingModerateEdge-first teams that want App Router ergonomics
replicate/getting-started-nextjsNative Next.js on the standard Next.js runtimeVercel or similar Next.js hostsStandard Next.js image pipelineStandard API routes and webhooksLow if you stay in the happy pathTeams that want the canonical Next.js stack
Next.js plus an adapter layer like OpenNextNext.js compiled through a compatibility layerCloudflare Workers or other edge runtimesAdapter-dependent and more fragileVaries by adapterHighestTeams that must keep an existing Next.js codebase

The takeaway is simple. This repo is not trying to beat Next.js at being Next.js. It is trying to show that the App Router experience can be detached from the Next.js runtime, and that the edge can carry the load without the usual translation tax.