This is a SaaS template for Cloudflare Workers. It uses Vinext on Vite to run a Next.js App Router application directly on Cloudflare Workers.
Vinext is Cloudflare's experimental implementation of the public Next.js API surface on top of Vite. The goal is to let a Next.js app keep familiar App Router patterns, React Server Components, route handlers, and next/* imports while using Vite as the build and dev toolchain instead of the standard Next.js compiler pipeline.
For this template, Vinext is the runtime and deployment path for Cloudflare Workers. pnpm dev starts the Vinext development server, pnpm build produces the Vinext/Vite production output, and pnpm deploy uses vinext deploy to build and deploy the Worker. Vinext has first-class Cloudflare Workers support, including access to bindings such as D1, KV, R2, Images, Durable Objects, and AI through cloudflare:workers.
Vinext is not a fork of Next.js and is not affiliated with Vercel. It is still experimental, so framework-sensitive changes should be verified with pnpm run check:vinext, pnpm run typecheck, pnpm run lint, and pnpm run build.
Tip
This template is brought to you by π AgenticDev π - where we help businesses automate operations and boost productivity through custom AI implementations. Just like this open-source project demonstrates technical excellence, we deliver:
- Process automation with LLM-powered workflows
- AI strategy consulting for sustainable scaling
- Custom SaaS development using cutting-edge stacks
Hundrets of developers already trust our codebase - Just Imagine what we could build for your business.
- π Authentication with Lucia Auth
- π§ Email/Password Sign In
- π Email/Password Sign Up
- π WebAuthn/Passkey Authentication
- π Google OAuth/SSO Integration
- π Forgot Password Flow
- π Change Password
- βοΈ Email Verification
- ποΈ Session Management with Cloudflare KV
- π€ Turnstile Captcha Integration
- β‘ Rate Limiting for Auth Endpoints
- π‘οΈ Protected Routes and Layouts
- π Session Listing and Management
- π Anti-Disposable Email Protection
- πΎ Database with Drizzle and Cloudflare D1
- ποΈ Type-safe Database Operations
- π Automatic Migration Generation
- π» SQLite for Local Development
- β‘ Efficient Data Fetching
- π Type-safe Queries
- π¨ Email Service with Cloudflare Email Service
- π¨ Beautiful Email Templates
- π Email Preview Mode
- π§ Local Email Development Server
- π¬ Transactional Emails
- βοΈ Email Verification Flow
- π± Responsive Email Templates
- π Deployment with Github Actions
- βοΈ Automatic Deployments
- π Environment Variables Management
- π¦ Database Migrations
- π Comprehensive CI/CD Pipeline
- π§Ή Cache Purging
- β Type Checking
- π§ͺ Integration Tests
- π§ͺ End-to-end Tests
- π Deploy Size Tracking
- π¨ Modern UI
- π¨ Tailwind CSS
- π§© Shadcn UI Components
- π Dark/Light Mode
- π± Responsive Design
- β‘ Loading States and Animations
- π Toast Notifications
- βοΈ Settings Dashboard
- π Landing Page
- β¨ Beautiful Email Templates
- π€ Profile Settings Page
- π― Form Validation States
- π³ Credit Billing System
- π° Credit-based Pricing Model
- π Monthly Credit Refresh
- π Credit Usage Tracking
- π³ Stripe Payment Integration
- π Transaction History
- π¦ Credit Package Management
- πΈ Pay-as-you-go Model
- π Usage Analytics
- π Admin Dashboard
- π₯ User Management
- π Content Management System
- ποΈ Config-driven collections for blog and docs content
- βοΈ Rich TipTap editor with markdown paste, markdown copy, tables, code highlighting, and alert blocks
- π§ Docs navigation builder with managed public URLs
- πΌοΈ Media library with R2-backed image uploads, alt text editing, and featured images
- π·οΈ Tags and categories with entry usage tracking
- π Draft, published, archived, and scheduled entry workflows
- π§Ύ Version history for CMS entries
- β‘ KV-backed CMS entry caching and cache maintenance actions
- π Full-text docs search
- π€ AI-assisted SEO description generation
- π§± Blog, docs, sitemap.xml, JSON-LD schema, and llms.txt rendering
- β¨ Validations with Zod and React Hook Form
- π‘οΈ Type-safe Form Validations
- π Server-side Validations
- π Client-side Validations
- π§Ή Input Sanitization
- β‘ Real-time Validation
- π Form State Management
- π¨βπ» Developer Experience
- π§ͺ Local Development Setup
- π TypeScript Support
- π Oxlint Configuration
- π§ͺ Co-located Vitest Unit Tests
- π§ͺ Cloudflare Workers Vitest Integration Tests
- π§ͺ Vitest and Playwright E2E Tests
- β‘ Vinext and Vite Build Pipeline
- π Type-safe Environment Variables
- ποΈ Cloudflare Types Generation
- π€ AI-powered Development with AI Agents
- π Comprehensive Documentation
- π Project Structure Best Practices
- β‘ Edge Computing
- π Global Deployment with Cloudflare Workers
- π Zero Cold Starts
- π¨ Edge Caching
- βοΈ React Server Components
- π₯οΈ Server-side Rendering
- πΎ Edge Database with D1
- ποΈ Session Storage with KV
- πΌοΈ Cloudflare Images-powered Image Optimization
- β‘ API Rate Limiting
- π’ Multi-tenancy Support
- π₯ Organization Management
- π€ User Roles and Permissions
- π Tenant Isolation
- π Resource Sharing Controls
- π Per-tenant Analytics
- π Tenant-specific Configurations
- πΌ Team Collaboration Features
- Add Oxlint coverage for unused exports
- Add an Oxlint rule to check for unused variables and imports
- Upgrade to Tailwind 4 and fix the errors and visual regressions. Already started here https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template/tree/tailwind-4-upgrade
- Update Meta SEO tags π
- Dynamic OpenGraph images πΈ
- sitemap.xml π
- robots.txt π
- Multi-language support (i18n) π
- Notifications π
- Webhooks π
pnpm installpnpx wrangler login- Login to your Cloudflare account to use Cloudflare bindings while testing locally.- Copy
.env.exampleto.envand fill in the values. pnpm db:migrate:dev- Creates a local SQLite database and applies migrationspnpm db:seed- Seeds the database with test datapnpm dev- Starts the Vinext development server- Go to http://localhost:3000/sign-in and login with the test user credentials: test@test.com / password
- Go to http://localhost:3000/admin to manage users and the CMS.
E2E tests use Vitest with Playwright-driven Chromium pages and run against the production-style local Worker preview.
After cloning the project, install the Playwright Chromium browser once on your machine:
pnpm exec playwright install chromiumThis browser binary is not downloaded automatically by pnpm install. It is kept outside the repo in Playwright's local browser cache, so you normally only need to run the install command after a fresh machine setup, a new Playwright version, or a cleared Playwright cache.
Run the E2E suite with:
pnpm run test:e2eThe E2E runner stores its temporary files under tmp/e2e, creates a fresh local Wrangler/D1 state under tmp/e2e/wrangler-state, applies all D1 migrations, runs src/db/seed.sql, builds the app, starts Wrangler preview on that isolated state, then runs the browser tests against the preview Worker. If the existing dist output matches the current build input fingerprint, the runner reuses that fresh Vinext build instead of rebuilding. The build and D1 setup run in parallel, and Vitest runs test files in parallel with isolated Playwright browser contexts. This keeps E2E data separate from your normal local .wrangler development state.
VS Code Vitest Explorer is configured through .vscode/settings.json to use vitest.e2e.config.ts. Running an individual E2E test from the editor uses Vitest global setup to create the same isolated Wrangler/D1 state and preview Worker before the selected test starts.
In CI, install Chromium before running the suite:
pnpm exec playwright install --with-deps chromium
pnpm run test:e2e| Command | Purpose |
|---|---|
pnpm dev |
Start the Vinext development server |
pnpm build |
Build the app with Vinext and Vite |
pnpm start |
Start the local Vinext production server |
pnpm preview |
Build, then preview the Worker locally with Wrangler |
pnpm run test:unit |
Run co-located Vitest unit tests |
pnpm run test:integration |
Run Cloudflare Workers Vitest integration tests with local D1/KV/Queue bindings |
pnpm run test:e2e |
Run Playwright-driven E2E tests against a clean local Wrangler/D1 preview |
pnpm deploy |
Build and deploy with vinext deploy |
pnpm deploy:dryrun |
Build and run a Wrangler deploy dry run into worker-dist |
pnpm check:vinext |
Run the Vinext compatibility checker |
pnpm run lint |
Run Oxlint |
pnpm run typecheck |
Run TypeScript without emitting files |
pnpm run cf-typegen |
Regenerate Cloudflare Worker types |
After making a change to wrangler.jsonc, run pnpm run cf-typegen to regenerate worker-configuration.d.ts.
Cloudflare bindings are defined in wrangler.jsonc and exposed to server code through cloudflare:workers or the local helper in src/utils/cloudflare-context.ts. The custom Worker entry lives in worker-entrypoint.ts and is configured as the main entry in wrangler.jsonc.
- Go to
src/constants.tsand update it with your project details - Update the
namefield inpackage.jsonto your project name so generated metrics and package metadata identify the reused template correctly - Update
AGENTS.mdwith your project specification so that AI coding agents can give you better suggestions - Update the footer in
src/components/footer.tsxwith your project details and links - Optional: Update the color palette in
src/app/globals.css - Update the metadata in
src/app/layout.tsxwith your project details - Update
cms.config.tsif necessary
The source of truth for preparing and deploying this template to production is the repo-local AI agent skill at .agents/skills/prepare-cloudflare-production-deployment/SKILL.md.
That skill covers Cloudflare resource provisioning with Cloudflare MCP, GitHub Actions secrets and variables with the GitHub CLI, wrangler.jsonc binding updates, Worker secrets, Turnstile, Email Sending, and deployment verification.