Files
gh-jezweb-claude-skills-ski…/templates/ARCHITECTURE.md
2025-11-30 08:25:20 +08:00

14 KiB

Architecture: [Project Name]

Deployment Platform: Cloudflare Workers Frontend: Vite + React + Tailwind v4 + shadcn/ui Backend: Hono (API routes on same Worker) Database: Cloudflare D1 (SQLite) Storage: Cloudflare R2 (object storage) Auth: Clerk (JWT-based) Last Updated: [Date]


System Overview

┌──────────────────────────────────────────────────────────────┐
│                         Browser                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  React App (Vite build)                                │  │
│  │  - Components (shadcn/ui + custom)                     │  │
│  │  - State (TanStack Query + Zustand)                    │  │
│  │  - Forms (React Hook Form + Zod)                       │  │
│  └───────────┬────────────────────────────────────────────┘  │
└──────────────┼───────────────────────────────────────────────┘
               │ HTTPS
               ↓
┌──────────────────────────────────────────────────────────────┐
│             Cloudflare Worker (Edge Runtime)                 │
│  ┌────────────────────────┐   ┌──────────────────────────┐  │
│  │   Static Assets        │   │    API Routes (Hono)     │  │
│  │   (Vite build output)  │   │    /api/*                │  │
│  │   Served directly      │   │                          │  │
│  │                        │   │  Middleware:             │  │
│  │   / → index.html       │   │  - CORS                  │  │
│  │   /assets/*            │   │  - Auth (JWT verify)     │  │
│  │                        │   │  - Error handling        │  │
│  └────────────────────────┘   │  - Validation (Zod)      │  │
│                                └───────┬──────────────────┘  │
│                                        │                     │
└────────────────────────────────────────┼─────────────────────┘
                                         │
          ┌──────────────────────────────┼──────────────────────────┐
          │                              │                          │
          ↓                              ↓                          ↓
┌───────────────────┐         ┌───────────────────┐    ┌──────────────────┐
│  Cloudflare D1    │         │  Cloudflare R2    │    │   Clerk Auth     │
│  (Database)       │         │  (File Storage)   │    │   (External)     │
│                   │         │                   │    │                  │
│  - users          │         │  - avatars/       │    │  - User accounts │
│  - [other tables] │         │  - uploads/       │    │  - JWT tokens    │
│                   │         │                   │    │  - Social auth   │
└───────────────────┘         └───────────────────┘    └──────────────────┘

Components Breakdown

Frontend (Browser)

Technology: React 19 + Vite + Tailwind v4

Responsibilities:

  • Render UI components
  • Handle user interactions
  • Client-side validation (Zod)
  • Optimistic updates
  • State management
  • Routing (React Router or TanStack Router)

Key Libraries:

  • @clerk/clerk-react - Authentication UI and hooks
  • @tanstack/react-query - Server state management (caching, refetching)
  • zustand - Client state management (UI state, preferences)
  • react-hook-form - Form state and validation
  • zod - Schema validation
  • shadcn/ui - UI component library (Radix UI primitives)

State Architecture:

Server State (TanStack Query)
  ↓
  Cached API responses, auto-refetch, background sync
  Examples: user data, tasks, analytics

Client State (Zustand)
  ↓
  UI state, form state, user preferences
  Examples: sidebar open/closed, theme, filters

Backend (Cloudflare Worker)

Technology: Hono web framework on Cloudflare Workers

Responsibilities:

  • Serve static assets (Vite build)
  • API request routing
  • Authentication/authorization
  • Server-side validation
  • Business logic
  • Database operations
  • Third-party API integration

Route Structure:

app.use('*', cors())
app.use('/api/*', authMiddleware)

// Static assets
app.get('/', serveStatic({ path: './dist/index.html' }))
app.get('/assets/*', serveStatic({ root: './dist' }))

// API routes
app.route('/api/auth', authRoutes)
app.route('/api/[resource]', [resource]Routes)
// ... more routes

app.onError(errorHandler)

Middleware Pipeline:

Request
  ↓
CORS Middleware (allow frontend origin)
  ↓
Auth Middleware (verify JWT for /api/* routes)
  ↓
Route Handler
  ↓
Validation Middleware (Zod schema)
  ↓
Business Logic
  ↓
Response
  ↓
Error Handler (catch unhandled errors)

Database (Cloudflare D1)

Technology: SQLite (via D1)

Access Pattern: SQL queries via Worker bindings

Schema: See DATABASE_SCHEMA.md for full details

Usage:

// In Worker
const result = await c.env.DB.prepare(
  'SELECT * FROM users WHERE id = ?'
).bind(userId).first()

Migrations: Manual SQL files in migrations/

Backups: Export via npx wrangler d1 export


Storage (Cloudflare R2)

Technology: S3-compatible object storage

Use Cases:

  • User avatars
  • File uploads
  • Generated assets

Access Pattern: Direct upload from Worker, signed URLs for browser access

Bucket Structure:

[bucket-name]/
├── avatars/
│   ├── user-1.jpg
│   └── user-2.png
├── uploads/
│   └── [user-id]/
│       └── document.pdf
└── generated/
    └── export-123.csv

Authentication (Clerk)

Technology: Clerk (external SaaS)

Flow:

1. User clicks "Sign In"
2. Clerk modal opens (handled by @clerk/clerk-react)
3. User authenticates (email/password or social)
4. Clerk returns JWT
5. Frontend includes JWT in API requests (Authorization: Bearer ...)
6. Worker verifies JWT using Clerk secret key
7. Worker extracts user email/ID from JWT
8. Worker processes request with user context

JWT Custom Template (configured in Clerk):

{
  "email": "{{user.primary_email_address}}",
  "userId": "{{user.id}}",
  "metadata": {
    "displayName": "{{user.first_name}} {{user.last_name}}"
  }
}

Verification (in Worker):

import { verifyToken } from '@clerk/backend'

const token = c.req.header('Authorization')?.replace('Bearer ', '')
const verified = await verifyToken(token, {
  secretKey: c.env.CLERK_SECRET_KEY
})

Data Flow Patterns

User Authentication Flow

1. User loads app
   → React app served from Worker static assets
   → ClerkProvider wraps app

2. User not authenticated
   → Show sign-in button
   → User clicks sign-in
   → Clerk modal opens

3. User signs in
   → Clerk handles authentication
   → Returns JWT to browser
   → React stores JWT in memory (via ClerkProvider)

4. User makes API request
   → React includes JWT in Authorization header
   → Worker middleware verifies JWT
   → Extracts user info from JWT
   → Passes to route handler via context

CRUD Operation Flow (Example: Create Task)

1. User fills out form
   ↓
2. React Hook Form validates locally (Zod schema)
   ↓
3. Validation passes → Submit to API
   ↓
4. POST /api/tasks with JWT in header
   ↓
5. Worker receives request
   ↓
6. CORS middleware allows request
   ↓
7. Auth middleware verifies JWT → extracts userId
   ↓
8. Route handler receives request
   ↓
9. Validation middleware validates body (Zod schema)
   ↓
10. Business logic creates task in D1
    INSERT INTO tasks (user_id, title, ...) VALUES (?, ?, ...)
   ↓
11. Return created task (201)
   ↓
12. TanStack Query updates cache
   ↓
13. React re-renders with new task

File Upload Flow

1. User selects file in browser
   ↓
2. React sends file to POST /api/upload
   ↓
3. Worker receives file (multipart/form-data)
   ↓
4. Worker validates file (size, type)
   ↓
5. Worker uploads to R2
   await c.env.R2_BUCKET.put(`uploads/${userId}/${filename}`, file)
   ↓
6. Worker creates DB record with R2 key
   INSERT INTO files (user_id, r2_key, filename, ...) VALUES (...)
   ↓
7. Return file metadata (200)
   ↓
8. Frontend shows uploaded file with signed URL
   GET /api/files/:id/url → Worker generates R2 signed URL

Deployment Architecture

Development Environment

localhost:5173
  ↓
Vite dev server (HMR)
  ↓
@cloudflare/vite-plugin runs Worker alongside Vite
  ↓
Worker connects to local D1 database
  ↓
All requests proxied correctly (frontend ↔ API on same port)

Start dev:

npm run dev
# Vite serves frontend on :5173
# Worker API available at :5173/api
# Uses local D1 and R2 buckets

Production Environment

https://[app-name].[account].workers.dev (or custom domain)
  ↓
Cloudflare Worker (edge locations globally)
  ↓
Static assets cached at edge
API requests hit Worker
  ↓
D1 database (regional, auto-replicated)
R2 storage (global, low latency)

Deploy:

npm run build        # Vite builds frontend → dist/
npx wrangler deploy  # Uploads Worker + assets

Security Architecture

Authentication

  • JWT verification on all protected routes
  • Clerk handles password hashing, session management, social auth
  • No passwords stored in our database

Authorization

  • User ownership checks before mutations
  • Example: Can't delete another user's task
const task = await getTask(id)
if (task.user_id !== c.get('userId')) {
  return c.json({ error: 'Forbidden' }, 403)
}

Input Validation

  • Client-side (Zod): Fast feedback, better UX
  • Server-side (Zod): Security, trust boundary
  • Same schemas used on both sides

CORS

  • Restrict origins to production domain
  • Allow credentials for JWT cookies (if used)

Secrets Management

  • Environment variables for API keys
  • Never committed to git
  • Wrangler secrets for production

Rate Limiting

[Optional: Add if implemented]

  • X requests per minute per IP
  • Higher limits for authenticated users

Scaling Considerations

Current Architecture Scales to:

  • Requests: Millions/day (Cloudflare Workers auto-scale)
  • Users: 10k-100k (D1 suitable for this range)
  • Data: Moderate (D1 max 10GB per database)

If You Need to Scale Beyond:

  • Database: Consider Hyperdrive + external Postgres for >100k users
  • Storage: R2 scales infinitely
  • Real-time: Add Durable Objects for WebSocket connections
  • Compute: Workers already global and auto-scaling

Monitoring and Observability

[Optional: Define monitoring strategy]

Metrics to Track:

  • Request volume and latency
  • Error rates (4xx, 5xx)
  • Database query performance
  • R2 upload/download volumes

Tools:

  • Cloudflare Analytics (built-in)
  • Workers Analytics Engine (custom metrics)
  • Sentry or similar for error tracking

Development Workflow

  1. Local development: npm run dev
  2. Make changes: Edit code, hot reload
  3. Test locally: Manual testing or automated tests
  4. Commit: git commit -m "feat: add feature"
  5. Deploy: npx wrangler deploy
  6. Monitor: Check Cloudflare dashboard for errors

Technology Choices Rationale

Why Cloudflare Workers?

  • Global edge deployment (low latency)
  • Auto-scaling (no server management)
  • Integrated services (D1, R2, KV)
  • Cost-effective for moderate traffic

Why Vite?

  • Fast dev server with HMR
  • Excellent React support
  • Simple config
  • @cloudflare/vite-plugin integrates perfectly with Workers

Why Hono?

  • Lightweight and fast
  • Express-like API (familiar)
  • Native TypeScript support
  • Works on any runtime (including Workers)

Why Clerk?

  • Handles complex auth flows
  • Social auth out of the box
  • Great DX
  • No need to build/maintain auth system

Why Tailwind v4?

  • Utility-first CSS
  • shadcn/ui compatibility
  • Dark mode support
  • v4 Vite plugin (no PostCSS needed)

Future Architecture Enhancements

Potential additions:

  • Durable Objects for real-time features (WebSockets)
  • Workers AI for AI-powered features
  • Queues for background jobs
  • Hyperdrive for external database connections
  • Vectorize for semantic search

Revision History

v1.0 ([Date]): Initial architecture design v1.1 ([Date]): [Changes made]