A production-ready template for building full-stack applications with Next.js 15 and Cloudflare's powerful edge infrastructure. Perfect for MVPs with generous free tiers and seamless scaling to enterprise-level applications.
Inspired by the Cloudflare SaaS Stack - the same stack powering Supermemory.ai, which serves 20k+ users on just $5/month. This template modernizes that approach with Cloudflare Workers (vs Pages), includes comprehensive D1 and R2 examples, and provides a complete development workflow.
You can read detail explanations and code architecture of this template from Devin AI on Deepwiki.
Don't forget to leave a star if you find this helpful βοΈ
Cloudflare's Edge Network provides unparalleled performance and reliability:
- β‘ Ultra-low latency - Deploy to 300+ locations worldwide
- π° Generous free tiers - Perfect for MVPs and side projects
- π Effortless scaling - From zero to millions of users automatically
- π Built-in security - DDoS protection, WAF, and more
- π Global by default - Your app runs close to every user
Combined with Next.js 15, you get modern React features, Server Components, and Server Actions for optimal performance and developer experience.
- βοΈ Next.js 15 - App Router with React Server Components (RSC)
- π¨ TailwindCSS 4 - Utility-first CSS framework
- π TypeScript - Full type safety throughout
- π§© Shadcn UI - Unstyled, accessible components
- π React Hook Form + Zod - Type-safe form handling
- π Cloudflare Workers - Serverless edge compute platform
- ποΈ Cloudflare D1 - Distributed SQLite database at the edge
- π¦ Cloudflare R2 - S3-compatible object storage
- π€ Cloudflare Workers AI - Edge AI inference with OpenSource models
- π Better Auth - Modern authentication with Google OAuth
- π οΈ Drizzle ORM - TypeScript-first database toolkit
- βοΈ GitHub Actions - Automated CI/CD pipeline
- π§ Wrangler - Cloudflare's CLI tool
- ποΈ Preview Deployments - Test changes before production
- π Database Migrations - Version-controlled schema changes
- πΎ Automated Backups - Production database safety
- Fetching: Server Actions + React Server Components for optimal performance
- Mutations: Server Actions with automatic revalidation
- AI Processing: Edge AI inference with Cloudflare Workers AI
- Type Safety: End-to-end TypeScript from database to UI
- Caching: Built-in Next.js caching with Cloudflare edge caching
- Cloudflare Account - Sign up for free
- Node.js 20+ and pnpm installed
- Google OAuth App - For authentication setup
Create an API token for Wrangler authentication:
- In the Cloudflare dashboard, go to the Account API tokens page
- Select Create Token > find Edit Cloudflare Workers > select Use Template
- Customize your token name (e.g., "Next.js Cloudflare Template")
- Scope your token to your account and zones (if using custom domains)
- Add additional permissions for D1 database and AI access:
- Account - D1:Edit
- Account - D1:Read
- Account - Cloudflare Workers AI:Read
Final Token Permissions:
- All permissions from "Edit Cloudflare Workers" template
- Account - D1:Edit (for database operations)
- Account - D1:Read (for database queries)
- Account - Cloudflare Workers AI:Read (for AI inference)
# Clone the repository
git clone https://github.com/ifindev/fullstack-next-cloudflare.git
cd fullstack-next-cloudflare
# Install dependencies
pnpm install
Create your environment file:
# Copy example environment file
cp .dev.vars.example .dev.vars
Edit .dev.vars
with your credentials:
# Cloudflare Configuration
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_D1_TOKEN=your-api-token
# Authentication Secrets
BETTER_AUTH_SECRET=your-random-secret-here
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Storage
CLOUDFLARE_R2_URL=your-r2-bucket-url
Better Auth Secret:
# Generate a random secret
openssl rand -base64 32
# Add to BETTER_AUTH_SECRET in .dev.vars
Google OAuth Setup: Follow the Better Auth Google documentation to:
- Create a Google OAuth 2.0 application
- Get your Client ID and Client Secret
- Add authorized redirect URIs
For Local Development:
# Create R2 bucket for local development
wrangler r2 bucket create next-cf-app-bucket-dev
# Get the bucket URL and add to .dev.vars as CLOUDFLARE_R2_URL
For Production: The GitHub Actions workflow will create the production bucket automatically. After deployment, update your production secrets with the R2 URL.
If you prefer to set everything up manually or want to understand each step in detail, follow this comprehensive guide.
Create D1 Database:
# Create a new SQLite database at the edge
wrangler d1 create your-app-name
# Output will show:
# database_name = "your-app-name"
# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Create R2 Bucket:
# Create object storage bucket
wrangler r2 bucket create your-app-bucket
# List buckets to confirm
wrangler r2 bucket list
Update wrangler.jsonc
with your resource IDs:
Generate Better Auth Secret:
# On macOS/Linux
openssl rand -base64 32
# On Windows (PowerShell)
[System.Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
# Or use online generator: https://generate-secret.vercel.app/32
Configure Google OAuth:
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URIs:
http://localhost:3000/api/auth/callback/google
(development)https://your-app.your-subdomain.workers.dev/api/auth/callback/google
(production)
Create Local Environment File:
# .dev.vars for local development
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_D1_TOKEN=your-api-token
BETTER_AUTH_SECRET=your-generated-secret
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
CLOUDFLARE_R2_URL=https://your-bucket.your-account-id.r2.cloudflarestorage.com
Set Production Secrets:
# Add each secret to Cloudflare Workers
echo "your-secret-here" | wrangler secret put BETTER_AUTH_SECRET
echo "your-client-id" | wrangler secret put GOOGLE_CLIENT_ID
echo "your-client-secret" | wrangler secret put GOOGLE_CLIENT_SECRET
echo "your-r2-url" | wrangler secret put CLOUDFLARE_R2_URL
Generate TypeScript Types:
# Generate Cloudflare bindings for TypeScript
pnpm run cf-typegen
Initialize Database:
# Generate initial migration from schema
pnpm run db:generate
# Apply migrations to local database
pnpm run db:migrate:local
# Verify database structure
pnpm run db:inspect:local
Optional: Seed Sample Data
# Create and run a seed script
wrangler d1 execute your-app-name --local --command="
INSERT INTO todos (id, title, description, completed, created_at, updated_at) VALUES
('1', 'Welcome to your app', 'This is a sample todo item', false, datetime('now'), datetime('now')),
('2', 'Set up authentication', 'Configure Google OAuth', true, datetime('now'), datetime('now'));
"
Start Development Servers:
# Terminal 1: Start Wrangler (provides D1 access)
pnpm run wrangler:dev
# Terminal 2: Start Next.js (provides HMR)
pnpm run dev
# Alternative: Single command (no HMR)
pnpm run dev:cf
Verify Everything Works:
- Open
http://localhost:3000
- Test authentication flow
- Create a todo item
- Check database:
pnpm run db:studio:local
Add Repository Secrets: Go to your GitHub repository β Settings β Secrets and add:
CLOUDFLARE_API_TOKEN
- Your API token from Step 2CLOUDFLARE_ACCOUNT_ID
- Your account IDBETTER_AUTH_SECRET
- Your auth secretGOOGLE_CLIENT_ID
- Your Google client IDGOOGLE_CLIENT_SECRET
- Your Google client secretCLOUDFLARE_R2_URL
- Your R2 bucket URL
Deploy Production Database:
# Apply migrations to production
pnpm run db:migrate:prod
# Verify production database
pnpm run db:inspect:prod
Add Custom Domain:
- Go to Cloudflare dashboard β Workers & Pages
- Select your worker β Settings β Triggers
- Click "Add Custom Domain"
- Enter your domain (must be in your Cloudflare account)
Update OAuth Redirect URLs: Add your custom domain to Google OAuth settings:
https://yourdomain.com/api/auth/callback/google
Add Indexes for Performance:
-- Create indexes for better query performance
CREATE INDEX IF NOT EXISTS idx_todos_user_id ON todos(user_id);
CREATE INDEX IF NOT EXISTS idx_todos_created_at ON todos(created_at);
CREATE INDEX IF NOT EXISTS idx_todos_completed ON todos(completed);
Monitor Database Performance:
# View database insights
wrangler d1 insights your-app-name --since 1h
# Export data for analysis
wrangler d1 export your-app-name --output backup.sql
Configure CORS for Direct Uploads:
# Create CORS policy file
echo '[
{
"AllowedOrigins": ["https://yourdomain.com", "http://localhost:3000"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]' > cors.json
# Apply CORS policy
wrangler r2 bucket cors put your-app-bucket --file cors.json
Enable Advanced Analytics:
// Add to wrangler.jsonc
{
"observability": {
"enabled": true,
"head_sampling_rate": 1
},
"analytics_engine_datasets": [
{
"binding": "ANALYTICS",
"dataset": "your-analytics-dataset"
}
]
}
# 1. Generate Cloudflare types (run after any wrangler.jsonc changes)
pnpm run cf-typegen
# 2. Apply database migrations
pnpm run db:migrate:local
# 3. Build the application for Cloudflare
pnpm run build:cf
# Terminal 1: Start Wrangler for D1 database access
pnpm run wrangler:dev
# Terminal 2: Start Next.js development server with HMR
pnpm run dev
Development URLs:
- π Next.js with HMR:
http://localhost:3000
(recommended) - βοΈ Wrangler Dev Server:
http://localhost:8787
# Single command - Cloudflare runtime (no HMR)
pnpm run dev:cf
# Test with remote Cloudflare resources
pnpm run dev:remote
Script | Description |
---|---|
pnpm dev |
Start Next.js with HMR |
pnpm run build:cf |
Build for Cloudflare Workers |
pnpm run wrangler:dev |
Start Wrangler for local D1 access |
pnpm run dev:cf |
Combined build + Cloudflare dev server |
Script | Description |
---|---|
pnpm run db:generate |
Generate new migration |
pnpm run db:generate:named "migration_name" |
Generate named migration |
pnpm run db:migrate:local |
Apply migrations to local D1 |
pnpm run db:migrate:preview |
Apply migrations to preview |
pnpm run db:migrate:prod |
Apply migrations to production |
pnpm run db:studio:local |
Open Drizzle Studio for local DB |
pnpm run db:inspect:local |
List local database tables |
pnpm run db:reset:local |
Reset local database |
Script | Description |
---|---|
pnpm run deploy |
Deploy to production |
pnpm run deploy:preview |
Deploy to preview environment |
pnpm run cf-typegen |
Generate Cloudflare TypeScript types |
pnpm run cf:secret |
Add secrets to Cloudflare Workers |
First-time setup:
pnpm run cf-typegen
- Generate typespnpm run db:migrate:local
- Setup databasepnpm run build:cf
- Build application
Daily development:
pnpm run wrangler:dev
- Start D1 access (Terminal 1)pnpm run dev
- Start Next.js with HMR (Terminal 2)
After schema changes:
pnpm run db:generate
- Generate migrationpnpm run db:migrate:local
- Apply to local DB
After wrangler.jsonc changes:
pnpm run cf-typegen
- Regenerate types
This template uses a feature-based/module-sliced architecture for better maintainability and scalability:
src/
βββ app/ # Next.js App Router
β βββ (auth)/ # Auth-related pages
β βββ api/ # API routes (for external access)
β β βββ summarize/ # AI summarization endpoint
β βββ dashboard/ # Dashboard pages
β βββ globals.css # Global styles
βββ components/ # Shared UI components
βββ constants/ # App constants
βββ db/ # Database configuration
β βββ index.ts # DB connection
β βββ schema.ts # Database schemas
βββ lib/ # Shared utilities
βββ modules/ # Feature modules
β βββ auth/ # Authentication module
β β βββ actions/ # Auth server actions
β β βββ components/ # Auth components
β β βββ hooks/ # Auth hooks
β β βββ models/ # Auth models
β β βββ schemas/ # Auth schemas
β β βββ utils/ # Auth utilities
β βββ dashboard/ # Dashboard module
β βββ todos/ # Todo module
β βββ actions/ # Todo server actions
β βββ components/ # Todo components
β βββ models/ # Todo models
β βββ schemas/ # Todo schemas
βββ services/ # Business logic services
β βββ summarizer.service.ts # AI summarization service
βββ drizzle/ # Database migrations
Key Architecture Benefits:
- π― Feature Isolation - Each module contains its own actions, components, and logic
- π Server Actions - Modern data mutations with automatic revalidation
- π React Server Components - Optimal performance with server-side rendering
- π‘οΈ Type Safety - End-to-end TypeScript from database to UI
- π§ͺ Testable - Clear separation of concerns makes testing easier
Browser Console (Easiest):
- Login at
http://localhost:3000
- Open DevTools Console (F12)
- Run:
fetch('/api/summarize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
text: "Your text to summarize here...",
config: { maxLength: 100, style: "concise" }
})
}).then(r => r.json()).then(console.log);
cURL (with session cookies):
- Login in browser first
- DevTools β Application β Cookies β Copy
better-auth.session_token
- Use cookie in cURL:
curl -X POST http://localhost:3000/api/summarize \
-H "Content-Type: application/json" \
-H "Cookie: better-auth.session_token=your-token-here" \
-d '{"text": "Your text here...", "config": {"maxLength": 100}}'
Postman:
- Login in browser, copy session cookie from DevTools
- Add header:
Cookie: better-auth.session_token=your-token-here
Unauthenticated Request Response:
{
"success": false,
"error": "Authentication required",
"data": null
}
The AI integration follows a clean service-based architecture:
- API Route (
/api/summarize
) - Handles HTTP requests, authentication, and validation - Authentication Layer - Validates user session before processing requests
- SummarizerService - Encapsulates AI business logic
- Error Handling - Comprehensive error responses with proper status codes
- Type Safety - Full TypeScript support with Zod validation
Cloudflare Workers AI supports various models:
- @cf/meta/llama-3.2-1b-instruct - Text generation (current)
- @cf/meta/llama-3.2-3b-instruct - More capable text generation
- @cf/meta/m2m100-1.2b - Translation
- @cf/baai/bge-base-en-v1.5 - Text embeddings
- @cf/microsoft/resnet-50 - Image classification
# 1. Modify schema files in src/db/schemas/
# 2. Generate migration
pnpm run db:generate:named "add_user_table"
# 3. Apply to local database
pnpm run db:migrate:local
# 4. Test your changes
# 5. Commit and deploy (migrations run automatically)
# 1. Update wrangler.jsonc with new resources
# 2. Regenerate types
pnpm run cf-typegen
# 3. Update your code to use new bindings
# Add secrets to production environment
pnpm run cf:secret BETTER_AUTH_SECRET
pnpm run cf:secret GOOGLE_CLIENT_ID
pnpm run cf:secret GOOGLE_CLIENT_SECRET
Built-in Observability:
- β Cloudflare Analytics (enabled by default)
- β Real User Monitoring (RUM)
- β Error tracking and logging
- β Performance metrics
Database Monitoring:
# Monitor database performance
wrangler d1 insights next-cf-app
# View database metrics in Cloudflare Dashboard
# Navigate to Workers & Pages β D1 β next-cf-app β Metrics
Push to main
branch triggers automatic deployment via GitHub Actions:
git add .
git commit -m "feat: add new feature"
git push origin main
Deployment Pipeline:
- β Install dependencies
- β Build application
- β Run database migrations
- β Deploy to Cloudflare Workers
# Deploy to production
pnpm run deploy
# Deploy to preview environment
pnpm run deploy:preview
- Add text translation service with
@cf/meta/m2m100-1.2b
- Implement text embeddings for semantic search with
@cf/baai/bge-base-en-v1.5
- Add image classification API with
@cf/microsoft/resnet-50
- Create chat/conversation API with conversation memory
- Add content moderation with AI classification
- Implement sentiment analysis for user feedback
- Implement email sending with Resend & Cloudflare Email Routing
- Implement international payment gateway with Polar.sh
- Implement Indonesian payment gateway either with Xendit, Midtrans, or Duitku
- Add Cloudflare Analytics integration
- Implement custom metrics tracking
- Add performance monitoring dashboard
- Create AI usage analytics and cost tracking
Contributions are welcome! Please feel free to submit issues and pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
Β© 2025 Muhammad Arifin. All rights reserved.