dbio.ai — System Architecture

Cloudflare Architecture Diagram: Domains → Workers → D1 / KV / R2

① Overview
② Request Flow
③ Data Layer
④ Multi-Domain
⑤ Growth Flywheel
DOMAINS (INTERNET) CLOUDFLARE EDGE WORKERS (COMPUTE) STORAGE LAYER sapatrails.com Satellite Domain ridehagiang.com Satellite Domain sungapao.com Custom Domain (Premium) dbio.ai Platform / Hub ☁ Cloudflare for SaaS 1 Zone: dbio.ai — Custom Hostnames for all domains Auto SSL • DNS routing • Edge caching ⚙ dbio-frontend Angular 21 SSR Worker 1 deployment → N domains ⚙ dbio-api Hono REST API Worker Auth • CRUD • AI Builder ⚙ dbio-router hostname → store_id Middleware / Service Binding 🗄 D1 Database stores, bios, users bookings, orders, settings ⚡ KV Store store_config, SSR cache rendered HTML, sessions 📦 R2 Storage images, avatars, media static assets per store 🤖 Workers AI AI Bio Builder Content generation
Domains
Cloudflare for SaaS
Workers (Compute)
D1 Database
KV Store
R2 Object Storage
Workers AI

// Key Highlights

Core Principle
1 codebase, 1 deployment, N domains. All domains go through the same Cloudflare zone (dbio.ai) and are routed to the same Workers.
Adding a New Domain
Just 1 API call to Cloudflare (create Custom Hostname) + 1 row INSERT into D1. No redeployment needed.
Estimated Cost
CF Workers $5/mo, D1/KV/R2 free tier is very generous. Total under $50/mo for early stage.
👤 User visits sapatrails.com/bio/guide/sung-a-pao ① DNS: sapatrails.com CNAME → custom.dbio.ai Cloudflare for SaaS handles SSL automatically ② dbio-router Worker hostname = "sapatrails.com" → lookup KV → store_id = 1 path = "/bio/guide/sung-a-pao" → bio_type = "guide", slug = "sung-a-pao" ③ Check KV Cache Key: "rendered:sapatrails.com:/bio/guide/sung-a-pao:v12" ✅ Cache HIT Serve HTML < 5ms ❌ Cache MISS ④ dbio-frontend Worker — SSR Load store_config + bio data → Angular SSR → HTML 🗄 D1: Query Bio Data WHERE store_id=1 AND slug='sung-a-pao' ⚡ KV: Store Config theme, logo, colors, template ⑤ Render HTML + Store in KV Cache TTL 30 min • Invalidate on bio update ⑥ Response → User HTML + <link rel="canonical" href="sapatrails.com/..."> + "Powered by dbio.ai" badge (FREE tier)

// Request Flow Details

Response Time
Cache HIT: < 5ms at the edge. Cache MISS (first request): 200-500ms due to SSR. Then cached for 30 minutes.
Store Isolation
Every query includes WHERE store_id = ?. Never cross-store except for the marketplace on dbio.ai.
Canonical SEO
Satellite domain is always canonical. dbio.ai always points canonical back to the satellite. Avoids duplicate content penalty.
🗄 D1 Database — Source of Truth SQLite at the edge, each query < 5ms, auto-replicate globally stores id TEXT PK name TEXT domain TEXT UNIQUE store_type TEXT theme_id TEXT settings JSON e.g.: sapatrails, ridehagiang plan: free | starter | pro | business bios id TEXT PK store_id TEXT FK → stores bio_type TEXT (guide|stay|...) slug TEXT global_slug TEXT UNIQUE content JSON status TEXT visibility TEXT UNIQUE(store_id, slug) → slug scoped per store users id TEXT PK store_id TEXT FK email TEXT role TEXT bio_id TEXT FK → bios admin | editor | viewer ⚡ KV Store — Edge Cache Key-Value at the edge, reads < 1ms, writes eventually consistent Store Config Cache store:{domain} → JSON "store:sapatrails.com" → {id, theme, logo, ...} Updated when admin changes settings SSR Rendered Cache rendered:{host}:{path}:{ver} Full HTML output, TTL 30 min Invalidate on bio or theme update Session / Auth session:{token} → JSON User session data, TTL 24h JWT refresh tokens 📦 R2 Object Storage — Media Files /{store_id}/avatars/*, /{store_id}/media/*, /{store_id}/static/* Isolated by store_id, served via CDN

// Data Strategy

D1 — Source of Truth
All critical data (bios, users, bookings) stored in D1. SQLite at the edge, query < 5ms. Supports transactions.
KV — Read-heavy Cache
Store config, rendered HTML, sessions. Reads < 1ms at the edge. Eventually consistent — ideal for cache, not for frequently changing data.
R2 — Binary Storage
Images, videos, file uploads. S3-compatible, 0 egress fee. Served directly via custom domain CDN.
Same Bio — 3 Different Entry Points 🌐 Satellite Domain sapatrails.com/bio/guide/sung-a-pao ✅ Canonical URL Branded • SEO indexed • Niche travel 🏪 Platform Hub dbio.ai/guide/sung-a-pao-sapa ↗ canonical → sapatrails.com Marketplace • Discovery • Preview card 👤 Custom Domain sungapao.com ✅ Highest priority canonical Premium • Personal brand ⚙ SAME WORKER — dbio-frontend hostname → store_id → render correct theme 🗄 SAME BIO DATA in D1 bios WHERE id = 'sung-a-pao-bio-id' Adding a New Domain — Just 2 Steps Step 1: Cloudflare API Call POST /zones/{zone}/custom_hostnames { "hostname": "ridehagiang.com" } → Cloudflare auto-provisions SSL, routes traffic Step 2: Insert DB Row INSERT INTO stores (id, domain, name, store_type) VALUES ('rh', 'ridehagiang.com', ...)

// Comparison: Old vs New

❌ Old Way (1 repo per domain)
Clone repo → config → deploy separately. Adding a domain = adding a deployment. Update UI = deploy N times. Maintain N codebases.
✅ dbio.ai (1 codebase)
Adding a domain = 1 API call + 1 DB row. Update UI = deploy once. Maintain 1 codebase. Cost: 1 Worker deployment.
Growth Flywheel — Satellite → Hub → Growth ① Satellite Creates SEO Content sapatrails.com indexed by Google for "Sapa guide", "Sapa trek"... ② User Searches Google → Lands on Satellite sapatrails.com/bio/guide/sung-a-pao ③ Sees "Powered by dbio.ai" Badge ⚡ Create your page for free → ④ Click → dbio.ai → Sign Up → AI Builder Create new bio with AI → Publish ⑤ New Bio → More Content → Better SEO Bio appears on satellite OR user.dbio.ai → Google indexes → More traffic → Back to ① FLYWHEEL 🔄 4 Mechanisms to Drive Satellite → dbio.ai Traffic ⚡ Powered by Badge FREE tier: required to display STARTER+: can be hidden Proven model: Linktree, Carrd 🔗 Cross-linking "See more guides →" → sapatrails.com/guides "Explore all of Vietnam →" dbio.ai/explore 🏪 Marketplace dbio.ai/explore/guides dbio.ai/explore/stays "Traveloka for individual guides" 📎 Embed Widget dbio.ai/card/sung-a-pao Beautiful OG card → click → satellite domain