Architecture Overview
Chirp is built as a modern, full-stack application with a monorepo structure that combines React, Node.js, Electron, and PostgreSQL. This guide explains the technical architecture and design decisions that power the platform.
High-Level Architecture
graph TB
subgraph "Client Layer"
A[Web Browser] --> B[React Frontend]
C[Electron Desktop] --> B
D[Mobile Web] --> B
end
subgraph "Application Layer"
B --> E[Express.js API Server]
E --> F[Socket.IO Real-time]
end
subgraph "Business Logic"
E --> G[Authentication & AuthZ]
E --> H[File Processing]
E --> I[Message Handling]
F --> J[Presence & Events]
end
subgraph "Data Layer"
G --> K[PostgreSQL Database]
H --> L[File Storage]
I --> K
J --> K
end
Core Technologies
Frontend Stack
- React 19 - Modern UI framework with concurrent features
- Vite - Fast build tool and development server
- Tailwind CSS - Utility-first CSS framework
- Zustand - Lightweight state management
- TanStack Query - Server state management and caching
- Socket.IO Client - Real-time communication
Backend Stack
- Node.js - JavaScript runtime
- Express.js - Web framework and API server
- Socket.IO - Real-time bidirectional communication
- PostgreSQL - Primary database
- Knex.js - SQL query builder and migration tool
- JWT - Authentication tokens
- Multer - File upload handling
Desktop Platform
- Electron - Cross-platform desktop application framework
- Electron Builder - Application packaging and distribution
System Components
1. Frontend Architecture
React Application Structure
src/renderer/
├── components/ # Reusable UI components
│ ├── auth/ # Authentication components
│ ├── chat/ # Chat interface
│ ├── forum/ # Forum features
│ ├── media/ # Media browsing
│ └── common/ # Shared components
├── hooks/ # Custom React hooks
│ ├── useAuth.js # Authentication logic
│ ├── useApi.js # API calls
│ ├── useSocket.js # Socket.IO integration
│ └── usePermissions.js # Permission checks
├── lib/ # Utility libraries
│ ├── api.js # API client
│ ├── socket.js # Socket client
│ └── encryption.js # Client-side encryption
├── stores/ # Zustand state stores
│ ├── authStore.js # Authentication state
│ ├── messageStore.js # Message cache
│ └── uiStore.js # UI state
└── utils/ # Frontend utilities
├── queryGuard.js # Query error recovery
└── formatters.js # Data formatting
State Management Strategy
Zustand for Client State:
- User authentication status
- UI preferences and settings
- Real-time presence information
- Temporary UI state (modals, forms)
TanStack Query for Server State:
- API response caching
- Automatic refetching and synchronization
- Optimistic updates
- Loading and error state management
Query Guard System:
The app includes a safety system (utils/queryGuard.js) that monitors critical queries (servers, channels, messages) and auto-recovers from empty cache states to prevent UI issues.
2. Backend Architecture
Express.js Server Structure
server/
├── routes/ # API endpoints
│ ├── auth.js # Authentication routes
│ ├── users.js # User management
│ ├── servers.js # Server/guild management
│ ├── channels.js # Channel operations
│ ├── messages.js # Message handling
│ └── media.js # Media upload/download
├── middleware/ # Express middleware
│ ├── auth.js # JWT authentication
│ ├── uploads.js # File serving
│ └── errorHandler.js # Error handling
├── database/ # Database layer
│ ├── migrations/ # Schema migrations
│ └── seeds/ # Sample data
├── utils/ # Server utilities
│ ├── crypto.js # Encryption helpers
│ ├── thumbnails.js # Image processing
│ └── permissions.js # Permission logic
├── socket.js # Socket.IO configuration
└── uploads/ # File storage directory
API Design Principles
RESTful Endpoints:
- Clear resource-based URLs
- HTTP status codes for responses
- Consistent response format
- Versioning support via URL prefixes
Authentication Flow:
- JWT-based stateless authentication
- Refresh token rotation
- Two-factor authentication support
- Permission-based authorization
File Handling:
- Multer for multipart uploads
- Sharp for image processing and thumbnails
- File type validation and security scanning
- Organized storage structure
3. Real-time Architecture
Socket.IO Implementation
Server Side (server/socket.js):
// Authentication middleware
io.use((socket, next) => {
// Verify JWT token for socket connection
});
// Event handlers
socket.on('join-server', (serverId) => {
// Join server room and update presence
});
socket.on('message-typing', (data) => {
// Broadcast typing indicator
});
Client Side (hooks/useSocket.js):
// Auto-reconnect with exponential backoff
// Presence management
// Message broadcasting
// Typing indicators
// Real-time notifications
Real-time Features:
- Presence status (online/offline/away)
- Typing indicators
- Live message updates
- Notification delivery
- Server/channel member updates
4. Database Architecture
PostgreSQL Schema Design
Core Tables:
users -- User accounts and profiles
servers -- Discord-like servers/guilds
channels -- Text/media/forum channels
messages -- Channel messages
direct_messages -- Private messages
roles -- Permission roles
permissions -- Role-based permissions
reactions -- Message reactions
media_items -- Media channel content
forum_posts -- Forum channel posts
threads -- Message threading
Key Design Patterns:
Hierarchical Permissions:
- Role-based access control (RBAC)
- Server-level and channel-specific permissions
- Permission inheritance and overrides
Message Threading:
- Threaded conversations within channels
- Parent-child message relationships
- Thread-specific permissions
Audit Trail:
- User activity logging
- Message editing history
- Permission change tracking
5. Security Architecture
Authentication & Authorization
Multi-layer Security:
graph LR
A[Client Request] --> B[JWT Verification]
B --> C[Permission Check]
C --> D[Resource Access]
B --> E[Token Refresh]
C --> F[Rate Limiting]
D --> G[Audit Logging]
Security Features:
- JWT with short-lived access tokens
- Secure refresh token rotation
- Password hashing with bcrypt
- Two-factor authentication (TOTP)
- Input validation and sanitization
- SQL injection prevention via Knex.js
- File upload security scanning
Data Protection
Encryption:
- Client-side encryption for private channels
- Database encryption at rest (configurable)
- HTTPS-only in production
- Secure cookie handling
Privacy:
- User data isolation
- Read permissions enforcement
- Audit logging for administrative actions
- Data export and deletion capabilities
Development Patterns
1. Monorepo Structure
The project uses a workspace-based monorepo:
Benefits:
- Shared dependencies and configuration
- Atomic commits across frontend/backend
- Simplified development workflow
- Consistent tooling and standards
Challenges:
- Larger repository size
- Complex build processes
- Dependency management overhead
2. API-First Development
Pattern:
- Design API endpoints first
- Create frontend mockups
- Implement backend logic
- Connect frontend to real API
- Add real-time features
Benefits:
- Clear contract between frontend/backend
- Parallel development possible
- Easier testing and validation
3. Optimistic Updates
TanStack Query Pattern:
// Update UI immediately
queryClient.setQueryData(['messages', channelId], (oldData) => {
return optimisticUpdate(oldData, newMessage);
});
// Then sync with server
await sendMessage(newMessage);
Benefits:
- Instant UI feedback
- Better perceived performance
- Graceful error handling
4. Query Optimization
Anti-Pattern Prevention:
- Avoid broad
invalidateQueries()calls - Prefer targeted
setQueryData()updates - Use
refetchQuerieswithtype: 'active' - Implement query guard for critical data
Performance Considerations
Frontend Optimization
- React 19 concurrent features
- Virtual scrolling for large message lists
- Image lazy loading and thumbnails
- Code splitting and lazy loading
- Service worker for offline support
Backend Optimization
- Database indexing for common queries
- Connection pooling
- Response caching
- File compression and CDN usage
- Rate limiting and DDoS protection
Database Optimization
- Proper indexing strategy
- Query performance monitoring
- Connection pooling
- Read replicas for scaling
Scalability Architecture
Horizontal Scaling Ready
- Stateless API server design
- Database connection pooling
- File storage can be externalized
- Socket.IO adapter for multi-instance deployment
Deployment Patterns
- Docker containerization
- Environment-specific configurations
- Database migration system
- Blue-green deployment support
Technology Rationale
Why React + Node.js?
- Type consistency: JavaScript throughout the stack
- Developer productivity: Fast development cycles
- Ecosystem maturity: Rich library ecosystem
- Real-time capabilities: Socket.IO integration
Why PostgreSQL?
- ACID compliance: Data integrity guarantees
- Complex queries: Advanced SQL features
- Performance: Excellent read/write performance
- Scalability: Supports complex scaling patterns
Why Electron?
- Cross-platform: Single codebase for Windows/Mac/Linux
- Web technology: Leverage existing web codebase
- Native integration: File system, notifications, system integration
- Auto-updates: Built-in update mechanism
Future Architecture Considerations
Potential Enhancements
- Microservices: Split into specialized services
- GraphQL: More flexible API queries
- WebSocket replacement: Consider modern alternatives
- Database sharding: Horizontal data scaling
- CDN integration: Global content delivery
Migration Paths
- Cloud services: AWS/GCP managed services
- Container orchestration: Kubernetes deployment
- Database scaling: Read replicas and sharding
- File storage: S3-compatible object storage
This architecture provides a solid foundation for a scalable, maintainable social platform while keeping development complexity manageable.