PrivacyHub uses a dual-branch strategy for optimal deployment on different platforms:
mainbranch → Vercel (Node.js runtime, full Playwright support)workerbranch → Cloudflare Workers (Edge runtime, D1 database caching)
📖 See BRANCH-STRATEGY.md for detailed branch management
| Feature | Vercel | Cloudflare Workers |
|---|---|---|
| Edge Runtime | ✅ Yes | ✅ Yes (Native) |
| Node.js Runtime | ✅ Yes (Serverless Functions) | |
| Database | Use external (PostgreSQL, etc.) | ✅ D1 (Built-in SQLite) |
| Deployment | Git-based (automatic) | CLI or Git-based |
| Free Tier | 100 GB-hours/month | 100,000 requests/day |
| Best For | Rapid deployment, GitHub integration | Global edge performance, D1 database |
Branch: main
- Click the button above
- Important: Select
mainbranch for production - Add environment variables:
OPENROUTER_APIFIRECRAWL_API_KEY(optional)
- Deploy!
Branch: worker
See detailed guide below for full D1 database integration and caching.
- Vercel account (free tier works)
- OpenRouter API key (get one here)
- Firecrawl API key (optional, get one here)
- Go to Vercel Dashboard
- Click Add New > Project
- Import your GitHub repository
Add these in Settings > Environment Variables:
OPENROUTER_API=your_primary_key_here
OPENROUTER_API_1=your_backup_key_1_here # Optional
OPENROUTER_API_2=your_backup_key_2_here # Optional
FIRECRAWL_API_KEY=your_firecrawl_key_here # OptionalVercel will automatically deploy on every push to your main branch.
npm install -g vercel
vercel login
vercel✅ Full scraping support (Firecrawl + Playwright + fetch fallback)
✅ AI-powered analysis with OpenRouter
✅ Edge Runtime for fast global responses
✅ Automatic SSL/HTTPS
Note: Vercel deployment works great but doesn't include D1 database caching. Each analysis will be fresh. For caching support, use Cloudflare Workers.
Branch: worker (optimized for Edge Runtime and D1 database)
This guide will help you deploy PrivacyHub to Cloudflare Workers with full production configuration including D1 database and edge caching.
First, switch to the worker branch:
git checkout worker- Node.js 18+ installed
- Cloudflare account (free tier works)
- Wrangler CLI installed (
npm install -g wrangler) - OpenRouter API key (get one here)
- Firecrawl API key (optional, get one here)
npm installnpm run cf:login
# or
wrangler loginThis will open a browser window to authenticate with Cloudflare.
# Create the database
wrangler d1 create an-dbCopy the database ID from the output and update wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "an-db"
database_id = "YOUR_DATABASE_ID_HERE" # Replace with actual ID# Apply the schema migration
wrangler d1 execute an-db --file=./migrations/0001_initial_schema.sql
# Or use the npm script
npm run d1:executeVerify the migration:
wrangler d1 execute an-db --command="SELECT * FROM analysis_stats;"Set your API keys as secrets in Cloudflare:
# Primary OpenRouter API key (required)
wrangler secret put OPENROUTER_API
# Additional keys for rotation (optional, recommended)
wrangler secret put OPENROUTER_API_1
wrangler secret put OPENROUTER_API_2
# Firecrawl API key (optional)
wrangler secret put FIRECRAWL_API_KEYAlternative: Set secrets via Cloudflare Dashboard:
- Go to Workers & Pages > Your Worker
- Settings > Variables and Secrets
- Add each secret with "Encrypt" enabled
Your bindings should already be configured from the screenshots:
- Binding name:
DB - Database:
an-db
- Binding name:
BROWSER - Type: Browser Rendering
- Binding name:
ASSETS - Type: Workers Assets (or R2)
- Binding name:
WORKER_SELF_REFERENCE - Service:
privacyhub - Environment:
production
# Build for Cloudflare Workers
npm run worker:buildThis will:
- Run Next.js build
- Use @cloudflare/next-on-pages to adapt for Workers
# Deploy to Cloudflare Workers
npm run deployOr manually:
wrangler deployAfter deployment, Wrangler will output your worker URL:
Published privacyhub (version xxx)
https://privacyhub.YOUR-SUBDOMAIN.workers.dev
Test the deployment:
curl https://privacyhub.YOUR-SUBDOMAIN.workers.dev/- Go to Cloudflare Dashboard > Workers & Pages > Your Worker
- Click Settings > Domains & Routes
- Click Add > Custom Domain
- Enter your domain (e.g.,
privacyhub.in) - Cloudflare will automatically configure DNS
wrangler deploy --env developmentwrangler deploy --env stagingwrangler deploy --env production
# or
npm run deploywrangler tail- Go to Cloudflare Dashboard
- Workers & Pages > Your Worker
- Click on Logs tab
wrangler d1 execute an-db --command="
SELECT
total_analyses,
unique_domains,
avg_score,
updated_at
FROM analysis_stats;
"Solution: Verify wrangler.toml has correct binding configuration:
[[d1_databases]]
binding = "DB"
database_name = "an-db"
database_id = "your-database-id"Solution: Ensure D1 database is created and migrations are applied:
wrangler d1 list
wrangler d1 execute an-db --file=./migrations/0001_initial_schema.sqlSolution: Set the secret:
wrangler secret put OPENROUTER_APIVerify in Cloudflare Dashboard > Workers & Pages > Settings > Variables and Secrets
Solution: Enable Browser Rendering in Cloudflare Dashboard:
- Workers & Pages > Your Worker
- Settings > Bindings
- Add binding > Browser Rendering
- Name:
BROWSER
Solution: The build script has been updated to use standard Next.js build (no Turbopack) for Cloudflare compatibility:
"build": "next build"Solution: Ensure you're using the Edge Runtime:
export const runtime = 'edge';The app uses D1 database for caching analysis results. Cache is automatically:
- Stored for 30 days
- Invalidated when content changes (content hash)
- Shared across all requests
Configure rate limiting per IP in the API route if needed:
// Currently disabled for MVP, but ready to enable
// See src/app/api/analyze/route.ts line 377-393Run cleanup periodically to remove old analyses (90+ days):
wrangler d1 execute an-db --command="
DELETE FROM analyses
WHERE created_at < datetime('now', '-90 days');
"Create .github/workflows/deploy.yml:
name: Deploy to Cloudflare Workers
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm ci
- run: npm run worker:build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}- Go to GitHub > Repository > Settings > Secrets
- Add:
CLOUDFLARE_API_TOKEN(get from Cloudflare Dashboard > My Profile > API Tokens)CLOUDFLARE_ACCOUNT_ID(get from Cloudflare Dashboard > Workers & Pages)
- Workers: 100,000 requests/day
- D1: 100,000 reads/day, 1 GB storage
- Browser Rendering: 2,000 sessions/month
- Total: $0/month for moderate usage
- Workers Paid: $5/month + $0.30/million requests
- D1 Paid: $5/month + $0.001/1000 reads
- Browser Rendering: $5/month + usage
- Estimated: $15-25/month for high traffic
- All API keys stored as encrypted secrets
- CORS headers configured in wrangler.toml
- Rate limiting enabled (if needed)
- Error messages don't expose sensitive data
- Database migrations applied
- Custom domain with HTTPS
If you encounter issues:
- Check Cloudflare Workers Documentation
- Review Next.js on Cloudflare
- Open an issue on GitHub
# Development
npm run dev # Local development
npm run worker:dev # Wrangler dev server
# Building
npm run build # Next.js build
npm run worker:build # Build for Workers
# Deployment
npm run deploy # Deploy to production
wrangler deploy --env staging # Deploy to staging
# Database
npm run d1:migrate # Apply migrations
npm run d1:execute # Execute schema
# Monitoring
wrangler tail # Real-time logs
wrangler d1 execute an-db --command="SELECT COUNT(*) FROM analyses;"