A minimal, production-ready monorepo template for building full-stack applications with:
- Frontend: React + Vite + TailwindCSS on Cloudflare Pages
- Backend: Python (FastAPI) or Rust on Cloudflare Workers
- Database: Supabase (PostgreSQL + Auth + RLS)
- Storage: Cloudflare R2
- Type Safety: Auto-generated TypeScript types from OpenAPI
Python (api/) |
Rust (api-rust/) |
|
|---|---|---|
| Best for | Rapid development, most apps | High-performance, low-latency |
| Cold start | ~50-100ms | ~5-10ms |
| Execution | Baseline | 10-100x faster |
| Binary size | ~15MB+ | ~500KB |
| Learning curve | Easy | Steeper |
| OpenAPI | Auto (FastAPI) | Manual (utoipa) |
Recommendation: Start with Python. Switch to Rust if you need extreme performance.
┌─────────────────────────────────────────────────────────────┐
│ Cloudflare Edge │
│ ┌─────────────────────┐ ┌─────────────────────────────┐ │
│ │ Pages (Frontend) │───▶│ Workers (Backend API) │ │
│ │ React + Vite │ │ Python or Rust │ │
│ │ Port 6174 │ │ Port 9990 │ │
│ └─────────────────────┘ └─────────────────────────────┘ │
│ │ │ │
│ │ Service Binding │ R2 Binding │
│ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ Supabase │
│ PostgreSQL + Auth │
│ + RLS │
└─────────────────────┘
- Node.js 20+
- pnpm (
npm install -g pnpm) - Supabase CLI (
brew install supabase/tap/supabase) - Wrangler (
pnpm install -g wrangler)
For Python backend:
- Python 3.12+
- uv (
curl -LsSf https://astral.sh/uv/install.sh | sh)
For Rust backend:
- Rust 1.76+ (
rustup update stable)
# Clone or use as template
git clone https://github.com/YOUR_ORG/supaflare myproject
cd myproject
# Run setup script (renames project, installs deps)
./setup.sh my-project-nameOr manually:
# Frontend
cd web && pnpm install && cd ..
# Backend (choose one)
cd api && uv sync && cd .. # Python
cd api-rust && cargo build && cd .. # Rustcd api # or api-rust (both share the same supabase folder)
supabase start
# Note the API URL and keys printed# Frontend
cp web/.env.example web/.env.local
# Edit with Supabase URL and anon key
# Backend (choose one)
cp api/.dev.vars.example api/.dev.vars # Python
cp api-rust/.dev.vars.example api-rust/.dev.vars # Rust
# Edit with Supabase URL and service role keyWith Python backend:
# Terminal 1: Backend (port 9990)
cd api && make dev
# Terminal 2: Frontend (port 6174)
cd web && pnpm run dev:with-bindingWith Rust backend:
# Terminal 1: Backend (port 9990)
cd api-rust && make dev
# Terminal 2: Frontend (port 6174)
cd web && pnpm run dev:with-bindingVisit http://localhost:6174
├── web/ # Frontend (Cloudflare Pages)
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── lib/ # Utilities (API client, Supabase)
│ │ ├── pages/ # Route pages
│ │ └── types/ # Generated API types
│ ├── functions/ # Pages Functions (API proxy)
│ ├── wrangler.toml # Cloudflare Pages config
│ └── package.json
│
├── api/ # Backend - Python (Cloudflare Workers)
│ ├── src/
│ │ ├── routes/ # FastAPI endpoints
│ │ ├── models/ # Pydantic models
│ │ ├── worker.py # Workers entry point
│ │ └── httpserver.py # FastAPI app
│ ├── supabase/ # Shared database config
│ │ ├── migrations/ # Database migrations
│ │ ├── seed/ # Seed data
│ │ └── config.toml # Supabase config
│ ├── wrangler.jsonc
│ ├── pyproject.toml
│ └── Makefile
│
├── api-rust/ # Backend - Rust (Cloudflare Workers)
│ ├── src/
│ │ ├── routes/ # Route handlers
│ │ ├── models/ # Data models
│ │ └── lib.rs # Worker entry + OpenAPI
│ ├── wrangler.toml
│ ├── Cargo.toml
│ └── Makefile
│
└── README.md
| Task | Python | Rust |
|---|---|---|
| Start backend | cd api && make dev |
cd api-rust && make dev |
| Start frontend | cd web && pnpm run dev:with-binding |
(same) |
| Generate types | cd web && pnpm run generate-types |
(same) |
| Run migrations | cd api && supabase db push |
(same) |
| Reset database | cd api && supabase db reset |
(same) |
| Deploy backend | cd api && make deploy |
cd api-rust && make deploy |
| Deploy frontend | cd web && pnpm run deploy |
(same) |
After changing backend API endpoints or models:
cd web && pnpm run generate-typesThis reads the OpenAPI schema from http://localhost:9990/openapi.json and generates TypeScript types in src/types/api.ts.
Both Python (FastAPI) and Rust (utoipa) backends expose the same /openapi.json endpoint.
cd api # or api-rust
# Set secrets
wrangler secret put SUPABASE_URL
wrangler secret put SUPABASE_SERVICE_ROLE_KEY
wrangler secret put SUPABASE_ANON_KEY
# Deploy
make deploycd web
# Set build environment variables in Cloudflare Dashboard:
# - VITE_SUPABASE_URL
# - VITE_SUPABASE_ANON_KEY
# Deploy
pnpm run deployThe frontend proxies /api/* requests to the backend using Cloudflare Service Bindings:
- Local: Frontend at 6174 proxies to backend at 9990
- Production: Direct Worker-to-Worker calls (no HTTP overhead)
This is configured in:
web/wrangler.toml(service binding declaration)web/functions/_middleware.ts(proxy logic)
To switch from Python to Rust (or vice versa):
- Update
web/wrangler.tomlto point to the correct worker name - Deploy the new backend
- Regenerate types:
cd web && pnpm run generate-types
Both backends expose identical APIs, so the frontend works with either.
MIT