Files
2025-11-30 08:25:20 +08:00

496 lines
14 KiB
Markdown

# 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**:
```typescript
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**:
```typescript
// 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):
```json
{
"email": "{{user.primary_email_address}}",
"userId": "{{user.id}}",
"metadata": {
"displayName": "{{user.first_name}} {{user.last_name}}"
}
}
```
**Verification** (in Worker):
```typescript
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**:
```bash
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**:
```bash
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
```typescript
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]