bhvr-cloudflare
Install
npx skills add https://github.com/hirefrank/skills --skill bhvr-cloudflare bhvr Cloudflare
Build full-stack applications with a single-origin architecture on Cloudflare Workers. The bhvr stack (Bun, Hono, Vite, React) simplifies deployment by serving both the API and frontend from one Worker.
Core Principles
Single Origin Architecture
- One Worker, one URL
app.com/api/*â Hono Workerapp.com/*â React Static Assets (Cloudflare CDN)
Zero CORS
- Client and server share an origin
- No complex preflight requests
- No authentication cookie issues
Remote-First Development
- Develop against real Cloudflare infrastructure
- Use
wrangler dev --remotefor accurate D1 and R2 behavior - Avoid local emulation discrepancies
Physical Separation
- Maintain
clientandserverworkspace separation - Prevents AI hallucinations
- Fused at deploy time via
wrangler.toml
The Stack
| Component | Choice | Details |
|---|---|---|
| Deploy Target | Cloudflare Workers | Single Worker with Assets Binding |
| Routing | Cloudflare Assets | SPA mode with automatic index.html fallback |
| Database | Cloudflare D1 | Accessed via Kysely (query builder) |
| Auth | Better-Auth | Email OTP + Kysely Adapter |
| Frontend | React + Vite | Builds to ./client/dist |
| Styling | Tailwind v4 | With shadcn/ui |
Project Setup
Initial Structure
Create this directory layout:
/
âââ client/ # React + Vite
â âââ vite.config.ts
âââ server/ # Hono Worker
â âââ src/index.ts
âââ wrangler.toml # Single Origin Config
âââ package.json # Build scripts
Configuration Files
Copy these templates from assets/:
- wrangler.toml - Single origin configuration
- package.json - Build pipeline scripts
- vite.config.ts - Client build configuration (place in
client/) - server-index.ts - Hono API starter (place in
server/src/index.ts) - auth-client.ts - Better-Auth client config (place in
client/src/lib/) - .cursorrules - AI agent rules (place in root)
Key Configuration Points
wrangler.toml must include:
assets = { directory = "./client/dist", binding = "ASSETS" }
package.json must build client before deploy:
"scripts": {
"dev": "bun run build:client && wrangler dev --remote",
"build:client": "cd client && bun run build",
"deploy": "bun run build:client && wrangler deploy"
}
vite.config.ts must output to dist:
build: {
outDir: 'dist' // Must match wrangler.toml assets directory
}
Implementation Patterns
API Routes (Hono)
Mount all API routes under /api:
import { Hono } from "hono";
const app = new Hono<{ Bindings: Env }>();
const api = new Hono<{ Bindings: Env }>();
api.get("/hello", (c) => c.json({ message: "Hello" }));
app.route("/api", api); // Critical: mount under /api
Never use serveStatic middleware - Cloudflare Assets handles static files.
Client API Calls
Always use relative paths:
// Correct
fetch('/api/user')
// Wrong - breaks single origin
fetch('http://localhost:8787/api/user')
fetch('https://api.myapp.com/user')
Better-Auth Integration
Server: Mount auth routes under /api/auth
import { createAuth } from "./auth";
const auth = createAuth(env);
app.on(["POST", "GET"], "/api/auth/*", (c) => auth.handler(c.req.raw));
Client: Use relative baseURL
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: "/api/auth" // Relative path for single origin
});
Database Access (D1 + Kysely)
Configure D1 binding in wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "prod-db"
database_id = "your-id-here"
Access in Hono routes:
api.get("/users", async (c) => {
const db = c.env.DB;
const users = await db.prepare("SELECT * FROM users").all();
return c.json(users);
});
Development Workflow
Starting Development
bun run dev
This:
- Builds the React app to
client/dist - Starts
wrangler dev --remote - Serves everything on
localhost:8787
Frontend Development with HMR
For fast frontend iteration:
cd client && bun vite
Runs Vite dev server on port 5173 with API proxy to Worker.
Backend Development
Edit server/src/index.ts - Wrangler provides instant HMR.
Deployment
Deploy to production:
bun run deploy
This automatically:
- Builds the client (
client/dist) - Uploads assets to Cloudflare
- Deploys the Worker
Critical: Never deploy without building client first. The deploy script handles this.
Architecture Review Checklist
When reviewing or auditing a bhvr project, verify:
Configuration
-
wrangler.tomlhasassets = { directory = "./client/dist", binding = "ASSETS" } -
package.jsonincludesbuild:clientin deploy script -
vite.config.tsoutputs todistdirectory - D1 bindings are correctly configured
Routing
- All API routes mounted under
/api - No
serveStaticmiddleware in Hono code - Client uses relative paths for API calls
- Better-Auth
baseURLis/api/auth
Development
- Dev script uses
wrangler dev --remote - Vite proxy configured for
/apiroutes
Deployment
- Deploy script builds client before deploying
-
BETTER_AUTH_URLset to production domain
Common Issues
For troubleshooting, see references/troubleshooting.md:
- CORS errors
- Assets not loading
- API routes 404
- D1 database issues
- Better-Auth problems
- HMR not working
- Deployment failures
- SPA routing issues
Resources
assets/
Template files for quick project setup:
wrangler.toml- Single origin Worker configurationpackage.json- Build scripts and dependenciesvite.config.ts- Vite build configurationserver-index.ts- Hono API starter templateauth-client.ts- Better-Auth client configuration.cursorrules- AI agent development rules
references/
troubleshooting.md- Common issues and solutions
Additional Resources
Using React with Cloudflare Workers - Video walkthrough of the bhvr stack