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 / Capacitor] --> 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]
E --> V[Voice / WebRTC]
end
subgraph "Data Layer"
G --> K[PostgreSQL Database]
H --> L[File Storage]
I --> K
J --> K
K --> M[Redis Cache]
end
subgraph "External Services"
V --> T[Coturn TURN Server]
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
- PeerJS / WebRTC — Voice channels
Backend Stack
- Node.js — JavaScript runtime
- Express.js — Web framework and API server
- Socket.IO — Real-time bidirectional communication
- PostgreSQL — Primary database
- Redis — Caching and session management
- Knex.js — SQL query builder and migration tool
- JWT — Authentication tokens
- Multer — File upload handling
- Sharp — Image processing and thumbnails
Desktop & Mobile
- Electron — Cross-platform desktop application
- Electron Builder — Application packaging and distribution
- Capacitor — Mobile app framework (Android)
System Components
1. Frontend Architecture
React Application Structure
src/renderer/
├── components/ # React components by feature
│ ├── ai/ # AI chat integration
│ ├── auth/ # Login, register, password reset
│ ├── category/ # Channel categories
│ ├── channel/ # Channel creation/management
│ ├── chat/ # Chat UI, link previews, polls
│ ├── collaborative/ # Real-time collaborative editing
│ ├── dev/ # Developer tools (theme panel)
│ ├── dm/ # Direct messages, group DMs
│ ├── events/ # Server events
│ ├── forum/ # Forum posts, tags
│ ├── friends/ # Friends system
│ ├── invite/ # Server invites
│ ├── layout/ # App layout, title bar, nav
│ ├── media/ # Media browser, folders
│ ├── moderation/ # Kick/ban modals
│ ├── routing/ # Route components
│ ├── server/ # Server settings, roles
│ ├── settings/ # User settings pages
│ ├── threads/ # Thread system
│ ├── ui/ # Shared UI (buttons, modals, pickers)
│ ├── user/ # User profiles
│ └── voice/ # Voice channel UI
├── hooks/ # Custom React hooks
│ ├── useAuth.js # Authentication logic
│ ├── useApi.js # API calls & TanStack Query
│ ├── useSocket.js # Socket.IO integration
│ ├── usePermissions.js # Permission checks
│ ├── useVoiceConnection.js # Voice channel WebRTC
│ ├── useAI.js # AI chat hook
│ └── ... (30+ hooks)
├── lib/ # Utility libraries
│ ├── api.js # API client (Axios)
│ ├── socket.js # Socket.IO client
│ ├── encryption.js # Client-side encryption
│ ├── aiService.js # LLM HTTP client
│ ├── platform.js # Platform detection
│ └── ... (25+ libs)
├── stores/ # Zustand state stores
│ ├── userStore.js # User/auth state
│ ├── messageStore.js # Message cache
│ ├── voiceStore.js # Voice channel state
│ ├── themeStore.js # Theme preferences
│ ├── unreadStore.js # Unread counts
│ ├── aiStore.js # AI settings
│ └── ... (25+ stores)
└── utils/ # Frontend utilities
├── queryGuard.js # Query error recovery
└── ...
State Management Strategy
Zustand for Client State:
- User authentication status and profile
- UI preferences and settings (themes, sounds)
- Real-time presence information
- Voice channel state
- Unread message counts
- Draft messages
TanStack Query for Server State:
- API response caching
- Automatic refetching and synchronization
- Optimistic updates for messages
- 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 (35+ route files)
│ ├── auth.js # Authentication routes
│ ├── users.js # User management
│ ├── servers.js # Server/guild management
│ ├── messages.js # Message handling
│ ├── directMessages.js # Direct messages
│ ├── groupDMs.js # Group direct messages
│ ├── media.js # Media upload/download
│ ├── forums.js # Forum channels
│ ├── collaborative.js # Collaborative channels
│ ├── webhooks.js # Webhook system
│ ├── roles.js # Role management
│ ├── moderation.js # Kick/ban/logs
│ ├── threads.js # Thread system
│ ├── search.js # Full-text search
│ ├── friends.js # Friends system
│ ├── reactions.js # Message reactions
│ ├── pins.js # Pinned messages
│ ├── emojis.js # Custom emoji
│ ├── stickers.js # Sticker packs
│ ├── events.js # Server events
│ ├── notes.js # User notes
│ ├── badges.js # User badges
│ ├── favorites.js # Favorites
│ ├── botTokens.js # Bot token management
│ ├── twoFactor.js # 2FA setup/verification
│ ├── admin.js # Admin endpoints
│ ├── webPush.js # Web push notifications
│ ├── fcm.js # Firebase Cloud Messaging (mobile)
│ ├── linkPreview.js # Link preview / oEmbed
│ └── ...
├── middleware/ # Express middleware
│ ├── auth.js # JWT authentication
│ └── ...
├── database/ # Database layer
│ └── migrations/ # Schema migrations
├── utils/ # Server utilities
├── socket.js # Socket.IO configuration
└── uploads/ # File storage directory
API Design Principles
RESTful Endpoints:
- Clear resource-based URLs
- Consistent HTTP status codes
- Direct JSON responses (no wrapping envelope)
- Bot token authentication support
Authentication Flow:
- JWT-based stateless authentication
- Token refresh with 30-day expiration
- Two-factor authentication support (TOTP)
- Bot tokens for API/WebSocket access
- Permission-based authorization with role hierarchy
File Handling:
- Multer for multipart uploads
- Sharp for image processing and thumbnails
- Support for images, videos, documents, audio, archives
- Default 250MB upload limit
3. Real-time Architecture
Socket.IO Implementation
Server Side (server/socket.js):
// Authentication middleware verifies JWT or Bot token
io.use((socket, next) => {
// Verify token for socket connection
});
// On connection: join user rooms, server channels, group DMs
// Set user status to online
Real-time Features:
- Presence status (online/idle/dnd/invisible/offline)
- Typing indicators (channels, DMs, group DMs)
- Live message creation, editing, deletion
- Reaction updates
- Read state synchronization across devices
- Voice channel join/leave events
- Server member updates
- Poll vote events
- Thread events
4. Voice Architecture
Chirp uses WebRTC with PeerJS for peer-to-peer voice communication:
- Voice activity detection (VAD) for auto-mute
- Optional noise suppression
- Push-to-talk support
- Per-user volume controls
- Audio device selection
- Coturn TURN server for NAT traversal (included in Docker setup)
5. Database Architecture
PostgreSQL Schema Design
Core Tables:
users -- User accounts, profiles, settings
servers -- Discord-like servers/guilds
channels -- Text/voice/media/forum/collaborative channels
messages -- Channel messages with attachments
direct_messages -- Private messages
group_dm_messages -- Group DM messages
roles -- Permission roles
permissions -- Role-based permissions
reactions -- Message reactions
media_items -- Media channel content
forum_posts -- Forum channel posts
threads -- Message threading
friends -- Friend relationships
webhooks -- Channel webhooks
badges -- User badges
stickers -- Custom sticker packs
events -- Server events
notes -- User notes
pins -- Pinned messages
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 locking and auto-archiving
6. Security Architecture
Security Features:
- JWT with configurable expiration
- Password hashing with bcrypt
- Two-factor authentication (TOTP with QR codes)
- Input validation and sanitization
- SQL injection prevention via Knex.js
- Rate limiting on all endpoints
- Bot token system separate from user auth
Encryption:
- Client-side encryption for private channels
- HTTPS in production
- Secure WebSocket connections
Development Patterns
1. Optimistic Updates
TanStack Query Pattern:
// Update UI immediately
queryClient.setQueryData(['messages', channelId], (oldData) => {
return optimisticUpdate(oldData, newMessage);
});
// Then sync with server
await sendMessage(newMessage);
2. Query Optimization
Anti-Pattern Prevention:
- Avoid broad
invalidateQueries()calls (can cause empty UI) - Prefer targeted
setQueryData()updates - Use
refetchQuerieswithtype: 'active' - Query guard system monitors critical data
3. IPC Pattern (Electron)
// Main process: ipcMain.handle() for async operations
// Renderer: ipcRenderer.invoke() for requests
// Main → Renderer: webContents.send() for events
// Preload: return cleanup functions from on* methods
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 tray
- Auto-updates: Built-in update mechanism
Why Capacitor for Mobile?
- Web-first: Reuse the React codebase
- Native APIs: Access to push notifications, haptics, filesystem
- Android support: Native Android app experience