This document outlines the strategy for making Cloudflare deployment intuitive and user-friendly for a public repository, allowing users to deploy without modifying hardcoded values.
- Hardcoded Worker Name:
"name": "signal-range"inwrangler.jsonc - Hardcoded Routes: Domain-specific routes that require manual editing
- Hardcoded R2 Bucket Names:
signal-range-assetshardcoded in multiple places - Manual Configuration Required: Users must edit config files to customize
Use a multi-layered approach:
- Environment Variables for user-specific configuration
- Default Values that work out-of-the-box (workers.dev)
- CLI Flags for one-off deployments
- Optional Config Files for advanced users
Current: Hardcoded in wrangler.jsonc
Proposed: Support multiple methods (priority order):
# .env.production or environment
CLOUDFLARE_WORKER_NAME=my-signal-range-appnpm run deploy -- --name my-signal-range-appUse package.json name as default, but allow override
Implementation:
- Wrangler automatically uses
--nameflag if provided - Can read from
process.env.CLOUDFLARE_WORKER_NAME - Default to
package.jsonname or "signal-range"
Current: Hardcoded routes that break if domain not configured
"routes": ["app.signalrange.space/*"]Proposed: Make routes completely optional
- No routes in config = Deploys to
https://YOUR_WORKER_NAME.YOUR_SUBDOMAIN.workers.dev - Works immediately, no domain setup required
- Cloudflare automatically provides the URL
# .env.production
CLOUDFLARE_ROUTES=app.mydomain.com/*
# Or multiple routes
CLOUDFLARE_ROUTES=app.mydomain.com/*,www.mydomain.com/*Implementation Strategy:
- Remove routes from
wrangler.jsonc(or make them conditional) - Use wrangler CLI
--routesflag if env var is set - Document that routes are optional
Current: Hardcoded in wrangler.jsonc and sync-r2-assets.js
"bucket_name": "signal-range-assets"Proposed: Environment-based naming with defaults
# .env.production
CLOUDFLARE_R2_BUCKET=my-signal-range-assets
CLOUDFLARE_R2_BUCKET_PREVIEW=my-signal-range-assets-previewImplementation:
- Default to
${WORKER_NAME}-assetspattern - Allow override via environment variables
- Update sync script to read from env or use pattern
Option 1: Keep wrangler.jsonc with Smart Defaults (Recommended)
- Remove hardcoded values
- Use environment variable substitution where possible
- Document environment variables in comments
Option 2: Use wrangler.toml with Environments
name = "signal-range" # Can be overridden
[env.production]
routes = [] # Empty = use workers.dev
[env.production.vars]
# Environment variables hereOption 3: Generate Config Dynamically
- Create a setup script that generates
wrangler.jsoncfrom templates - Use
.wrangler.jsonc.exampleas template
-
Remove Routes from
wrangler.jsonc- Default to workers.dev (no routes needed)
- Document how to add custom domain later
-
Make Worker Name Configurable via CLI
// package.json "scripts": { "deploy": "npm run build && wrangler deploy --name ${CLOUDFLARE_WORKER_NAME:-signal-range}" }
-
Update R2 Sync Script
- Read bucket name from env:
process.env.CLOUDFLARE_R2_BUCKET || 'signal-range-assets' - Use worker name pattern:
${workerName}-assets
- Read bucket name from env:
-
Create Setup Script (
scripts/setup-cloudflare.js)// Interactive setup that: // - Asks for worker name // - Asks for R2 bucket name (suggests default) // - Optionally asks for custom domain // - Generates .env.production with values // - Creates wrangler.jsonc from template
-
Environment Variable Support
.env.production.examplewith all options documented- Scripts read from environment variables
- Fallback to sensible defaults
-
Documentation
- Clear setup guide in README
- Quick start: "Just run
npm run deploy" - Advanced: Custom domain setup guide
SignalRange/
├── wrangler.jsonc # Base config (no hardcoded user values)
├── wrangler.jsonc.example # Example with comments
├── .env.production.example # All configurable variables
├── scripts/
│ ├── setup-cloudflare.js # Interactive setup (optional)
│ ├── sync-r2-assets.js # Updated to use env vars
│ └── deploy.js # Enhanced deploy script
└── README.md # Updated with setup instructions
CLOUDFLARE_WORKER_NAME→ Default:signal-rangeor package.json nameCLOUDFLARE_R2_BUCKET→ Default:${WORKER_NAME}-assets
CLOUDFLARE_ROUTES→ Default: empty (use workers.dev)CLOUDFLARE_R2_BUCKET_PREVIEW→ Default:${BUCKET}-previewCLOUDFLARE_ACCOUNT_ID→ Auto-detected by wranglerCLOUDFLARE_ZONE_ID→ Only needed for custom domain routes
PUBLIC_SUPABASE_URLPUBLIC_SUPABASE_ANON_KEYPUBLIC_USER_API_URLPUBLIC_ASSETS_BASE_URL
-
Clone repository
git clone <repo> cd SignalRange npm install
-
Set application environment variables
cp .env.production.example .env.production # Edit .env.production with Supabase credentials -
Deploy (uses defaults)
npm run deploy # Deploys to: https://signal-range.YOUR_SUBDOMAIN.workers.dev -
Get deployment URL
- Wrangler outputs the URL after deployment
- Or check Cloudflare Dashboard
-
Set Cloudflare-specific variables
# .env.production CLOUDFLARE_WORKER_NAME=my-custom-name CLOUDFLARE_R2_BUCKET=my-custom-assets CLOUDFLARE_ROUTES=app.mydomain.com/*
-
Deploy with custom config
npm run deploy
# Deploy with custom name without editing files
npm run deploy -- --name my-temp-deployment{
// Base configuration - no user-specific values
"compatibility_date": "2025-11-01",
// R2 buckets - names can be overridden via env vars
// Default pattern: ${WORKER_NAME}-assets
"r2_buckets": [
{
"binding": "ASSETS",
"bucket_name": "${CLOUDFLARE_R2_BUCKET:-signal-range-assets}",
"preview_bucket_name": "${CLOUDFLARE_R2_BUCKET_PREVIEW:-signal-range-assets-preview}"
}
],
// Static assets
"assets": {
"directory": "./dist",
"html_handling": "force-trailing-slash",
"not_found_handling": "single-page-application"
}
// Routes: Omit entirely for workers.dev
// Add via CLI: wrangler deploy --routes "domain.com/*"
// Or env var: CLOUDFLARE_ROUTES
}Note: Wrangler doesn't support env var substitution in JSONC directly, so we need a different approach:
Alternative: Use wrangler CLI flags or a wrapper script
Create scripts/deploy.js:
#!/usr/bin/env node
const { execSync } = require('child_process');
const fs = require('fs');
require('dotenv').config({ path: '.env.production' });
const workerName = process.env.CLOUDFLARE_WORKER_NAME || 'signal-range';
const routes = process.env.CLOUDFLARE_ROUTES;
let deployCmd = `wrangler deploy --name ${workerName}`;
if (routes) {
deployCmd += ` --routes ${routes}`;
}
execSync(deployCmd, { stdio: 'inherit' });Update package.json:
"deploy": "npm run build && node scripts/deploy.js"Modify scripts/sync-r2-assets.js:
// At top of file
require('dotenv').config({ path: '.env.production' });
// Configuration - read from env or use defaults
const WORKER_NAME = process.env.CLOUDFLARE_WORKER_NAME || 'signal-range';
const BUCKET_NAME = process.env.CLOUDFLARE_R2_BUCKET || `${WORKER_NAME}-assets`;Create .env.production.example:
# Application Configuration (Required)
PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
PUBLIC_USER_API_URL=https://user.keeptrack.space
PUBLIC_ASSETS_BASE_URL=
# Cloudflare Configuration (Optional - defaults provided)
# Worker name (default: signal-range)
CLOUDFLARE_WORKER_NAME=signal-range
# R2 bucket name (default: ${CLOUDFLARE_WORKER_NAME}-assets)
CLOUDFLARE_R2_BUCKET=signal-range-assets
CLOUDFLARE_R2_BUCKET_PREVIEW=signal-range-assets-preview
# Custom domain routes (optional - omit for workers.dev)
# Format: domain.com/* or multiple: domain1.com/*,domain2.com/*
# CLOUDFLARE_ROUTES=app.mydomain.com/*- No breaking changes - defaults maintain current behavior
- Optional migration - users can set env vars if they want customization
- Documentation update - explain new options
- Zero configuration - works with defaults
- Progressive enhancement - add custom config as needed
✅ No Hardcoded Values: Users don't need to edit config files
✅ Works Out-of-the-Box: Defaults to workers.dev (no domain setup)
✅ Flexible: Environment variables for customization
✅ CLI Override: One-off deployments with flags
✅ Clear Documentation: .example files show all options
✅ Backward Compatible: Existing deployments continue working
If JSONC limitations are an issue, consider wrangler.toml:
name = "signal-range" # Can be overridden via --name flag
compatibility_date = "2025-11-01"
[[r2_buckets]]
binding = "ASSETS"
bucket_name = "signal-range-assets" # Can be overridden
[assets]
directory = "./dist"
html_handling = "force-trailing-slash"
not_found_handling = "single-page-application"
# No routes = defaults to workers.dev
# Routes can be added via CLI: --routes "domain.com/*"Advantages:
- More flexible than JSONC
- Better environment support
- Can use TOML variable substitution
Disadvantages:
- Need to migrate from JSONC
- Slightly different syntax
-
Immediate (Low Risk):
- Remove routes from
wrangler.jsonc(already done) - Update deploy script to support
--nameflag - Create
.env.production.example
- Remove routes from
-
Short Term:
- Update R2 sync script to read from env vars
- Create enhanced deploy script
- Update documentation
-
Long Term:
- Consider interactive setup script
- Add validation for configuration
- Create deployment wizard/CLI tool
# 1. Clone and install
git clone https://github.com/user/SignalRange.git
cd SignalRange
npm install
# 2. Copy environment template
cp .env.production.example .env.production
# 3. Edit only application variables (Supabase)
nano .env.production
# Add: PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY
# 4. Deploy (uses all defaults)
npm run deploy
# Output:
# ✨ Deployed to: https://signal-range.username.workers.dev
# ✅ Your app is live!No Cloudflare-specific configuration needed!
# Option 1: Environment variable
echo "CLOUDFLARE_WORKER_NAME=my-app" >> .env.production
npm run deploy
# Option 2: CLI flag (one-time)
npm run deploy -- --name my-app# 1. Set up domain in Cloudflare Dashboard
# 2. Add route to .env.production
echo "CLOUDFLARE_ROUTES=app.mydomain.com/*" >> .env.production
npm run deployThis approach provides:
- Zero-configuration deployment for most users
- Flexible customization for advanced users
- No hardcoded values that users must edit
- Clear documentation via example files
- Backward compatibility with existing setups
The key is using environment variables with sensible defaults and removing routes entirely to default to workers.dev, which requires no domain setup.