Desktop Application
Stack: Electron + React + Zustand + Tailwind CSS + Radix UI The desktop app runs on macOS and provides the user interface for recording meetings, viewing meeting data, and managing integrations.Main Process
The Electron main process handles:- Window management — A fixed-size (420x680) window with macOS-native vibrancy, hidden title bar, and traffic light buttons. The window hides on close instead of quitting.
- System tray — A persistent tray icon with “Open Salesgraph” and “Quit” menu items. Clicking the tray icon toggles window visibility.
- Recall SDK — Initializes and manages the Recall AI Desktop SDK for meeting detection and recording. Routes SDK events to the renderer process.
- Authentication — Browser-based login flow that opens an external browser, then polls the server for the auth result. Tokens are encrypted on disk using
safeStorage. - OAuth flows — Handles OAuth connections for third-party integrations by opening the browser and polling for connection confirmation.
- Local cache — Encrypted cache file (
cache.json) for session and meeting data, usingsafeStoragefor at-rest encryption.
Renderer Process
The React renderer handles all UI:- Login gate — Blocks the app until authenticated
- Onboarding gate — Three-step wizard for new users
- Permission gate — Ensures macOS permissions are granted
- Recording widget — Always-visible controls for meeting recording with live transcript and coaching metrics
- Meeting list — Browse all meetings with status indicators
- Meeting detail — Five-tab view (Summary, Transcript, Actions, Coaching, Chat)
- Integrations page — Manage OAuth and API key integrations
IPC Communication
The main and renderer processes communicate through 32 IPC channels exposed via Electron’scontextBridge. These are organized into namespaces:
| Namespace | Purpose |
|---|---|
recall | SDK control (init, start/stop/pause/resume recording, permission requests) and 14 event listeners |
window | Minimize, close, open external URLs, focus/blur events |
auth | Login, logout, get session, get token |
integrations | Connect OAuth providers |
cache | Read/write encrypted local cache |
Server
Stack: Deno + Effect-TS + Drizzle ORM + MySQL The server handles authentication, data storage, integration management, AI processing, and webhook ingestion.Authentication Layer
- WorkOS AuthKit — SSO, JWT verification, session management with automatic token refresh
- Multi-tenancy — Organization-based tenancy with auto-provisioning on first login
- RBAC — Role hierarchy: viewer < member < manager < admin < owner
- Auth middleware — Supports Bearer tokens (JWT), legacy API keys, and hashed API key lookup
OAuth Infrastructure
- Encrypted storage — OAuth tokens encrypted with AES-GCM using envelope encryption (master key wraps per-tenant data encryption keys)
- Token caching — In-memory cache with TTL to reduce decryption overhead
- Distributed refresh locks — Prevents concurrent token refresh operations
- Auto-retry —
withAuthRetrywrapper automatically refreshes tokens on 401/403 responses
Integration Services
Each integration has a dedicated service that handles API communication, data fetching, and ingestion:| Service | Provider | Auth |
|---|---|---|
gong.ts | Gong | OAuth |
fathom.ts | Fathom | OAuth |
fireflies.ts | Fireflies | API key |
attention.ts | Attention | API key |
granola.ts | Granola | API key |
slack*.ts | Slack | OAuth |
calendar.ts | Google Calendar | OAuth |
recall.ts | Recall.ai | Server API key |
AI Layer
- LLM service — Supports OpenAI (default: gpt-4o) and Anthropic
- Structured output — JSON-mode completions with custom parsers
- Multi-turn chat — Conversation support for the meeting chat feature
- Stub mode — Available for environments without LLM access
Data Flow
Deployment
- Server — Deployed to Fly.io via Docker, triggered on push to
mainwhenserver/**files change - Desktop — Packaged as a macOS DMG via Electron Forge
- CI/CD — GitHub Actions runs server unit/integration tests (with MySQL service container), desktop unit tests, and desktop E2E tests (Playwright on macOS runners)
