Run the Next.js SaaS starter on Cloudflare Workers using OpenNext with Cloudflare D1 as the database. The template keeps the Stripe-powered subscription flow, auth, RBAC, and dashboard from the original Vercel project, but is tuned for the Cloudflare platform.
- Marketing landing page (
/) with animated Terminal element - Pricing page (
/pricing) which connects to Stripe Checkout - Dashboard pages with CRUD operations on users/teams
- Basic RBAC with Owner and Member roles
- Subscription management with Stripe Customer Portal
- Email/password authentication with JWTs stored to cookies
- Global middleware to protect logged-in routes
- Local middleware to protect Server Actions or validate Zod schemas
- Activity logging system for any user events
- Runtime: Cloudflare Workers via OpenNext
- Framework: Next.js 15
- Database: Cloudflare D1
- ORM: Drizzle
- Payments: Stripe
- UI Library: shadcn/ui
git clone https://github.com/<your-org>/cf-saas-starter
cd cf-saas-starter
pnpm installpnpm- Wrangler CLI authenticated (
wrangler login) - Cloudflare account with D1 enabled
- Stripe account + Stripe CLI for local testing (optional but recommended)
Install and log in to your Stripe account (optional, only required for local webhooks/payments):
stripe loginAuthenticate Wrangler so the script can provision D1 resources:
wrangler loginUse the included setup script to create your .env file and (optionally) create a D1 database:
pnpm db:setupRun the database migrations (via the D1 HTTP driver) and seed the database with the default user/team:
pnpm db:migrate
pnpm db:seedThis will create the following user and team:
- User:
test@test.com - Password:
admin123
You can also create new users through the /sign-up route.
Finally, run the Next.js development server for the modern dev workflow:
pnpm devOpen http://localhost:3000 in your browser to see the app in action.
You can listen for Stripe webhooks locally through their CLI to handle subscription change events:
stripe listen --forward-to localhost:3000/api/stripe/webhookIf you prefer to exercise the full Worker runtime locally you can also use:
pnpm preview # Builds with OpenNext, then runs wrangler devTo test Stripe payments, use the following test card details:
- Card Number:
4242 4242 4242 4242 - Expiration: Any future date
- CVC: Any 3-digit number
When you're ready to deploy your SaaS application to production, follow these steps:
-
Build the OpenNext output and deploy with the included CLI script:
pnpm deploy
This wraps
opennextjs-cloudflareand publishes to Cloudflare Workers/Pages. -
Alternatively, you can push the
.open-nextartifacts to your own deployment pipeline and runwrangler deploy.
Set the following in the Cloudflare dashboard (Workers > your deployment > Settings > Variables) or via wrangler secret put:
BASE_URL: e.g.https://yourdomain.comSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETAUTH_SECRET
And ensure your Worker has the D1 binding created during setup (defaults to DB). If you created the database manually, update wrangler.jsonc accordingly and redeploy.
- Go to the Stripe Dashboard and create a new webhook for your production environment.
- Set the endpoint URL to your production API route (e.g.,
https://yourdomain.com/api/stripe/webhook). - Select the events you want to listen for (e.g.,
checkout.session.completed,customer.subscription.updated).
While this template is intentionally minimal and to be used as a learning resource, there are other paid versions in the community which are more full-featured: