System Overview
Core Components
Cap Web (Next.js Application)
Technology Stack:- Next.js 14 (App Router)
- React Server Components
- TypeScript
- Drizzle ORM
- NextAuth.js for authentication
- Effect for functional programming
- User authentication and session management
- Video metadata management
- Web-based video player
- Share page generation
- API endpoints for Cap Desktop
- File upload handling
- User dashboard and settings
Media Server (FFmpeg Processing)
Technology Stack:- Node.js with Bun runtime
- FFmpeg for video processing
- Express-like HTTP server
- Video transcoding and optimization
- Thumbnail generation
- Format conversion
- Video compression
- Webhook callbacks to Cap Web
- Receives video processing request from Cap Web
- Downloads source video from S3
- Processes with FFmpeg:
- Transcodes to H.264 (web compatible)
- Generates multiple resolutions (if configured)
- Extracts thumbnail images
- Uploads processed files to S3
- Sends webhook to Cap Web with results
MySQL Database
Version: MySQL 8.0 Schema Management: Drizzle ORM with migrations Key Tables:- Character set: utf8mb4 (full Unicode support)
- Collation: utf8mb4_unicode_ci
- Max connections: 1000
- Authentication: mysql_native_password
S3 Storage (MinIO or AWS S3)
Bucket Structure:- Public read access for videos and thumbnails
- Authenticated write access only
- CORS enabled for browser uploads
Request Flow
Video Upload Flow
Desktop App Initiates Upload
- User records video in Cap Desktop
- Desktop app requests upload URL from Cap Web API
- Cap Web generates presigned S3 URL
Direct Upload to S3
- Desktop app uploads video directly to S3
- Upload bypasses Cap Web server (efficient)
Metadata Creation
- After upload completes, Desktop app notifies Cap Web
- Cap Web creates database record with status: “processing”
Processing Request
- Cap Web sends processing request to Media Server
- Media Server downloads video from S3
Video Playback Flow
User Opens Share Link
- Browser requests
https://cap.yourdomain.com/s/{share-code} - Cap Web looks up video by share code
Page Render
- Cap Web returns HTML with video player
- Video source points to S3:
https://s3.yourdomain.com/cap/videos/processed/{video-id}.mp4
Direct Playback
- Browser fetches video directly from S3
- No Cap Web server involvement in streaming
- Efficient bandwidth usage
Authentication Architecture
Passwordless Email Login
- User enters email on login page
- Cap Web generates magic link token
- Token stored in database with expiration (10 minutes)
- Email sent via Resend with login link
- User clicks link
- Cap Web validates token
- Creates session cookie
- User redirected to dashboard
Session Management
NextAuth.js handles sessions:- Strategy: Database sessions (stored in MySQL)
- Cookie:
next-auth.session-token - Lifetime: 30 days
- Refresh: Automatic on page load
API Authentication
Cap Desktop uses API keys:- Generated per user in database
- Sent as
Authorization: Bearer {token}header - Validated on each API request
- Can be revoked in user settings
Database Schema
Entity Relationships
Key Relationships
- One user can have many videos
- One user can have many API keys
- One video can have many comments
- One video can have many share links
- Comments belong to both a user and a video
Networking
Docker Compose Networking
All services run on a bridge network:cap-network
Internal DNS:
cap-web- Accessible atcap-web:3000within networkmysql- Accessible atmysql:3306minio- Accessible atminio:9000media-server- Accessible atmedia-server:3456
- Only Cap Web (port 3000) and MinIO (ports 9000, 9001) are exposed to host
Production Networking
Data Flow
Write Operations
- User Action → Cap Web API
- Cap Web → MySQL (metadata)
- Cap Web/Desktop → S3 (files)
- Media Server → S3 (processed files)
Read Operations
- Browser → Cap Web (page HTML)
- Browser → S3 (video streaming)
- Cap Web → MySQL (metadata)
Scalability Considerations
Bottlenecks
- Cap Web: Single instance, can’t handle high concurrent requests
- MySQL: Single instance, no read replicas
- Media Server: Synchronous processing, one video at a time
- S3 (MinIO): Limited to server disk I/O
Scaling Strategies
See Scaling Guide for:- Horizontal scaling of Cap Web
- Database read replicas
- Distributed media processing
- CDN for S3 delivery
Security Architecture
Secrets Management
Sensitive data protection:- Environment Variables: Secrets loaded from
.env, never committed to git - Database Encryption:
DATABASE_ENCRYPTION_KEYencrypts sensitive fields (AWS keys, OAuth tokens) - Session Secrets:
NEXTAUTH_SECRETsigns session cookies - Webhook Auth:
MEDIA_SERVER_WEBHOOK_SECRETvalidates media server callbacks
Network Security
- TLS/SSL: All external communication over HTTPS
- Internal Network: Services communicate over Docker network (encrypted in production)
- Firewall: Only ports 80, 443 exposed (reverse proxy)
Data Security
- SQL Injection: Prevented by Drizzle ORM (parameterized queries)
- XSS: React escapes output by default
- CSRF: NextAuth includes CSRF tokens
- File Upload: Validated file types, size limits
Monitoring Points
Application Logs
Health Checks
Each service has health check endpoints:- Cap Web:
http://localhost:3000/(returns 200 if healthy) - Media Server:
http://localhost:3456/health - MySQL:
mysqladmin ping - MinIO:
mc ready local
Metrics (Optional)
With Tinybird configured:- Page views
- Video plays
- User signups
- API usage
Technology Choices
Why Next.js?
- Server-side rendering for share pages (SEO)
- API routes for backend logic
- React for interactive UI
- Excellent TypeScript support
- Vercel deployment option
Why MySQL?
- Mature, reliable relational database
- Excellent JSON support (for metadata)
- Great ORM support (Drizzle)
- Wide hosting availability
- PlanetScale compatibility (serverless option)
Why S3 (MinIO)?
- Industry standard object storage
- Excellent SDKs and tools
- Easy migration between providers
- Built-in CDN support (AWS S3 + CloudFront)
- Cost-effective at scale
Why FFmpeg?
- Industry standard for video processing
- Supports all video formats
- Fast, efficient encoding
- Extensive codec support
- Battle-tested and reliable
Development vs Production
Development
- Default docker-compose.yml with placeholder secrets
- MinIO for local S3 storage
- No reverse proxy needed
- Hot reload enabled
- Detailed logging
Production
- Custom
.envwith secure secrets - External S3 (AWS, Cloudflare R2, etc.)
- Reverse proxy with SSL
- Optimized builds
- Structured logging
- Health checks and monitoring
Next Steps
Scaling
Scale Cap for production workloads
Environment Variables
Configure all components
Troubleshooting
Debug architecture issues
Docker Compose
Deploy the architecture