Initial commit
This commit is contained in:
495
templates/ARCHITECTURE.md
Normal file
495
templates/ARCHITECTURE.md
Normal file
@@ -0,0 +1,495 @@
|
||||
# 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]
|
||||
Reference in New Issue
Block a user