Why Next.js
Next.js has become the dominant React framework for good reason. The App Router, introduced in Next.js 13 and matured through 14 and 15, brings a file-system based routing model where each folder in the app/ directory becomes a route. Layouts, loading states, error boundaries and server components are all first-class concepts — you compose your application from these primitives rather than wiring them together yourself.
React Server Components (RSC) are the other significant change. Components marked without "use client" run only on the server — they can fetch data, read the filesystem, and access environment variables without any of it reaching the browser. Client components, marked with "use client", handle interactivity. The practical result is smaller JavaScript bundles, better performance, and a cleaner separation between data fetching and rendering.
For a content-focused site — a marketing page, a documentation site, a portfolio — Next.js with the App Router is an excellent choice. TypeScript is first-class, Tailwind CSS integrates cleanly, and the ecosystem of components and utilities is mature.
The hosting problem
Next.js is built and maintained by Vercel, and it shows. The framework is optimised for Vercel's infrastructure — serverless functions, edge middleware, image optimisation, incremental static regeneration. Running it on Vercel is seamless. Running it anywhere else requires either a Node.js server, a Docker container, or a static export that gives up most of the dynamic features.
For low-traffic sites this creates a disproportionate cost. A basic Vercel Pro plan runs $20/month per seat before you start adding compute. A self-hosted Node.js server on a VPS adds infrastructure management overhead. Neither is ideal for a site that serves a few thousand visits a month and just needs to be fast, reliable and cheap.
Don't have a Next.js project yet?
This guide assumes you already have a Next.js App Router project. If you're starting from scratch, we have a separate guide that covers the full process — from installing Node.js through to routing, data-driven components, MDX, dynamic pages, and SEO fundamentals. Read the Next.js build guide first, then come back here when your site is ready to deploy.
Enter vinext and Cloudflare Workers
vinext is an open-source project from Cloudflare that reimplements the Next.js API surface on top of Vite. It supports the App Router, React Server Components, server actions, MDX, middleware, and the full next/* import surface — targeting approximately 94% of the Next.js API. Critically, it deploys natively to Cloudflare Workers.
Cloudflare Workers is a serverless compute platform that runs JavaScript at Cloudflare's edge — over 300 data centres globally. Requests are handled close to the user, cold starts are sub-millisecond, and the free tier covers 100,000 requests per day. For a marketing site or small business web presence this is effectively free hosting with better performance than a shared VPS.
The migration from Next.js to vinext is non-destructive. Your existing codebase continues to work — vinext adds parallel scripts alongside your existing npm run dev without removing anything.
The migration process
1. Compatibility check
Before touching anything, run the compatibility scanner. This analyses your codebase and reports what vinext supports, what needs attention, and what will be handled automatically.
npx vinext checkThe output lists every next/* import in use, whether it's fully supported, partially supported, or unsupported. Common issues like missing "type": "module" in package.json are flagged with a note that they'll be fixed automatically.
2. Initialise vinext
The init command does the migration in one step:
npx vinext init --skip-checkThis installs the required packages (vinext, vite, @vitejs/plugin-react, @vitejs/plugin-rsc), adds "type": "module" to package.json, generates a minimal vite.config.ts, and adds three new scripts: dev:vinext, build:vinext, and start:vinext.
3. Handle any additional plugins
If your project uses MDX (.mdx files for content), install and register the MDX plugin — vinext doesn't include this by default:
npm install -D @mdx-js/rollupThen update vite.config.ts:
import vinext from "vinext";
import { defineConfig } from "vite";
import mdx from "@mdx-js/rollup";
export default defineConfig({
plugins: [mdx(), vinext()],
});4. Test locally
Start the vinext dev server on port 3001 (your existing Next.js dev server continues on 3000 unchanged):
npm run dev:vinextIf you hit a native binding error from rolldown on Apple Silicon, clear the lockfile and reinstall:
rm -rf node_modules package-lock.json
npm installDeploying to Cloudflare Workers
Authenticate with Cloudflare
You need a Cloudflare account (free tier is sufficient). Authenticate wrangler once — it caches the token for all future deployments:
npx wrangler loginDeploy
A single command builds the application and deploys it to Cloudflare's edge network:
npx vinext deployvinext auto-generates the wrangler configuration, creates the Worker if it doesn't exist, bundles the application, and uploads it. The output includes a live *.workers.dev URL. From there, a custom domain is pointed at the Worker via a DNS CNAME record in the Cloudflare dashboard — no server configuration required.
The cost argument
Cloudflare Workers on the free tier handles 100,000 requests per day — enough for most small business websites. The paid tier (Cloudflare Workers Paid, $5/month) extends this to 10 million requests per month with 30ms CPU time per request, which covers almost any content site. Compare this to a Vercel Pro plan at $20+/month, or a VPS at $5-10/month that still requires maintenance, patching, and monitoring.
Beyond cost, Workers brings genuine performance advantages. Requests are handled at the nearest Cloudflare data centre — typically within single-digit milliseconds of the user globally. There are no cold starts in the traditional sense. No containers to spin up, no Node.js process to initialise. The Worker is always warm because it runs in Cloudflare's V8 isolate environment, not a traditional serverless function.
When it makes sense
This stack works well for: marketing sites, small business web presence, documentation, portfolios, and any content-focused application with moderate traffic. It's less suitable for applications that rely heavily on server-side sessions, complex database connections that can't tolerate a distributed edge environment, or features that depend on undocumented Next.js/Vercel internals.
vinext is experimental and targets the stable Next.js API surface. For applications already using standard Next.js features — routing, server components, server actions, MDX, Tailwind — the migration is straightforward and the resulting deployment is simpler and cheaper than the alternatives.
Website support as a managed service
Building and deploying a site like this is one thing. Keeping it running, updated, and correctly configured over time is another. If you're running a business, your website shouldn't be something you have to think about. That's what a managed website support service covers — ongoing maintenance, content updates, DNS and domain management, security patches, and the ability to spin up new sites to the same standard when needed.
If this is something you're looking for, see our services or get in touch.
