Vite Config Examples
These examples stay minimal on purpose. If you add custom build tuning on Vite 8, prefer oxc, optimizeDeps.rolldownOptions, and build.rolldownOptions / worker.rolldownOptions over older esbuild and build.rollupOptions settings.
Pages Router — Local Development
No Cloudflare, no deployment. Simplest possible config.
import vinext from "vinext";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [vinext()],
});App Router — Local Development
vinext auto-registers @vitejs/plugin-rsc when an app/ directory is detected and the rsc option is not false. No extra config needed.
import vinext from "vinext";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [vinext()],
});To disable auto-registration (e.g., Pages Router only project with an unused app/ dir):
export default defineConfig({
plugins: [vinext({ rsc: false })],
});Pages Router — Cloudflare Workers
import vinext from "vinext";
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [vinext(), cloudflare()],
});App Router — Cloudflare Workers
Cloudflare multi-environment setup. RSC plugin registration stays automatic — do not add an explicit
rsc() call, or the build fails with [vinext] Duplicate @vitejs/plugin-rsc detected.
import { defineConfig } from "vite";
import vinext from "vinext";
import { cloudflare } from "@cloudflare/vite-plugin";
export default defineConfig({
plugins: [
vinext(),
cloudflare({
viteEnvironment: { name: "rsc", childEnvironments: ["ssr"] },
}),
],
});@vitejs/plugin-rsc is an optional peer dependency: it must be installed in the project, but vinext
registers it for you. Only register it yourself after passing rsc: false to vinext().
In most cases npx @vinext/cloudflare deploy generates this automatically. Only use manual config when customizing the worker entry or adding bindings.
wrangler.jsonc — Cloudflare Workers
Minimal config for deployment:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-app",
"compatibility_date": "2026-02-12",
"compatibility_flags": ["nodejs_compat"],
"main": "vinext/server/app-router-entry",
"assets": {
"not_found_handling": "none",
},
}For custom worker entries (e.g., adding KV cache, image optimization bindings):
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-app",
"compatibility_date": "2026-02-12",
"compatibility_flags": ["nodejs_compat"],
"main": "./worker/index.ts",
"assets": {
"not_found_handling": "none",
"binding": "ASSETS",
},
"images": { "binding": "IMAGES" },
}Accessing Cloudflare Bindings
Use import { env } from "cloudflare:workers" in server components, route handlers, and server actions. No custom worker entry needed.
// app/page.tsx (server component)
import { env } from "cloudflare:workers";
export default async function Page() {
const result = await env.DB.prepare("SELECT * FROM posts").all();
return <div>{JSON.stringify(result)}</div>;
}// app/api/data/route.ts (route handler)
import { env } from "cloudflare:workers";
export async function GET() {
const value = await env.CACHE.get("key");
return Response.json({ value });
}Define bindings in wrangler.jsonc:
{
"name": "my-app",
"compatibility_date": "2026-02-12",
"compatibility_flags": ["nodejs_compat"],
"main": "vinext/server/app-router-entry",
"d1_databases": [{ "binding": "DB", "database_name": "my-db", "database_id": "..." }],
"kv_namespaces": [{ "binding": "CACHE", "id": "..." }],
"r2_buckets": [{ "binding": "BUCKET", "bucket_name": "my-bucket" }],
"ai": { "binding": "AI" },
}Run wrangler types to generate TypeScript types for the env object.
Do NOT use getPlatformProxy(), getRequestContext(), or custom worker entries with fetch(request, env). These are older patterns. cloudflare:workers is the recommended approach.
App Router — Other Platforms (via Nitro)
For deploying to Vercel, Netlify, AWS, Deno Deploy, or any other Nitro-supported platform:
import { defineConfig } from "vite";
import vinext from "vinext";
import { nitro } from "nitro/vite";
export default defineConfig({
plugins: [vinext(), nitro()],
});Build with a preset:
NITRO_PRESET=vercel npx vite build
NITRO_PRESET=netlify npx vite build
NITRO_PRESET=deno_deploy npx vite build
NITRO_PRESET=node npx vite buildNitro auto-detects the platform in most CI/CD environments, so the NITRO_PRESET is often unnecessary.
For Cloudflare Workers, Nitro works but the native integration (npx @vinext/cloudflare deploy / vp exec vinext-cloudflare deploy / @cloudflare/vite-plugin) is recommended for the best experience with cloudflare:workers bindings, KV caching, and one-command deploys.
VinextOptions
| Option | Type | Default | Description |
|---|---|---|---|
appDir |
string |
project root | Custom base directory for app/ and pages/ |
rsc |
boolean |
true |
Auto-register @vitejs/plugin-rsc for App Router |
@vinext/cloudflare deploy flags
| Flag | Description |
|---|---|
--preview |
Deploy to preview environment |
--name <name> |
Override worker name |
--skip-build |
Skip build step (deploy existing output) |
--dry-run |
Generate config without deploying |
--warm-cache |
Warm discovered routes before promotion |
--traffic-aware-warm-cache |
Enable traffic-aware cache warming |