86 lines
4.9 KiB
Markdown
86 lines
4.9 KiB
Markdown
**Update this file when making significant changes.**
|
|
|
|
See also: [CONVEX_RULES.md](./CONVEX_RULES.md) | [CONVEX_EXAMPLES.md](./CONVEX_EXAMPLES.md)
|
|
|
|
## Architecture
|
|
|
|
- **Backend**: Convex (reactive database + serverless functions)
|
|
- **Frontend**: React + Vite (Electron app)
|
|
- **Auth**: Zero-knowledge custom auth via Convex mutations (getSalt, verifyUser, createUserWithProfile)
|
|
- **Real-time**: Convex reactive queries (`useQuery` auto-updates all connected clients)
|
|
- **Voice/Video**: LiveKit (token generation via Convex Node action)
|
|
- **E2E Encryption**: Client-side via Electron IPC (`window.cryptoAPI`)
|
|
- **File Storage**: Convex built-in storage (`generateUploadUrl` + `getUrl`)
|
|
|
|
## Key Convex Files (convex/)
|
|
|
|
- `schema.ts` - Full schema: userProfiles (with avatarStorageId, aboutMe, customStatus), channels (with category, topic, position), messages, messageReactions, channelKeys, roles, userRoles, invites, dmParticipants, typingIndicators, voiceStates
|
|
- `auth.ts` - getSalt, verifyUser, createUserWithProfile, getPublicKeys (includes avatarUrl, aboutMe, customStatus), updateProfile, updateStatus
|
|
- `channels.ts` - list, get, create (with category/topic/position), rename, remove (cascade), updateTopic
|
|
- `members.ts` - getChannelMembers (includes isHoist on roles, avatarUrl, aboutMe, customStatus)
|
|
- `channelKeys.ts` - uploadKeys, getKeysForUser
|
|
- `messages.ts` - list (with reactions + username), send, remove
|
|
- `reactions.ts` - add, remove
|
|
- `typing.ts` - startTyping, stopTyping, getTyping, cleanExpired (scheduled)
|
|
- `dms.ts` - openDM, listDMs
|
|
- `invites.ts` - create, use, revoke
|
|
- `roles.ts` - list, create, update, remove, listMembers, assign, unassign, getMyPermissions
|
|
- `voiceState.ts` - join, leave, updateState, getAll
|
|
- `voice.ts` - getToken (Node action, livekit-server-sdk)
|
|
- `files.ts` - generateUploadUrl, getFileUrl
|
|
- `gifs.ts` - search, categories (Node actions, Tenor API)
|
|
|
|
## Frontend Structure (Frontend/Electron/src/)
|
|
|
|
- `main.jsx` - ConvexProvider + VoiceProvider + HashRouter
|
|
- `pages/Login.jsx` - Convex auth (getSalt + verifyUser)
|
|
- `pages/Register.jsx` - Convex auth (createUserWithProfile + invite flow)
|
|
- `pages/Chat.jsx` - useQuery for channels, channelKeys, DMs
|
|
- `components/ChatArea.jsx` - Messages, typing, reactions via Convex queries/mutations
|
|
- `components/Sidebar.jsx` - Channel creation, key distribution, invites via Convex
|
|
- `contexts/VoiceContext.jsx` - Voice state via Convex + LiveKit room management
|
|
- `components/ChannelSettingsModal.jsx` - Channel rename/delete via Convex mutations
|
|
- `components/ServerSettingsModal.jsx` - Role management via Convex queries/mutations
|
|
- `components/Avatar.jsx` - Reusable avatar component (image or colored-initial fallback)
|
|
- `components/FriendsView.jsx` - User list via Convex query
|
|
- `components/DMList.jsx` - DM user picker via Convex query
|
|
- `components/GifPicker.jsx` - GIF search via Convex action
|
|
- `components/VoiceRoom.jsx` - LiveKit token via Convex action
|
|
|
|
## Important Patterns
|
|
|
|
- Channel IDs use Convex `_id` (not `id`) - all references use `channel._id`
|
|
- Auth: client hashes DAK -> HAK before sending, server does string comparison
|
|
- First user bootstrap: createUserWithProfile creates Owner + @everyone roles
|
|
- Vite config uses `envDir: '../../'` to pick up root `.env.local`
|
|
- `socket.io-client` fully removed, all socket refs replaced with Convex
|
|
- No Express backend needed - `Backend/` directory is legacy and can be deleted
|
|
- Convex queries are reactive - no need for manual refresh or socket listeners
|
|
- File uploads use Convex storage: `generateUploadUrl` -> POST blob -> `getFileUrl`
|
|
- Typing indicators use scheduled functions for TTL cleanup
|
|
- CSS uses Discord dark theme colors via `:root` variables (`--bg-primary: #313338`, `--bg-secondary: #2b2d31`, `--bg-tertiary: #1e1f22`)
|
|
- Sidebar width is 312px (72px server strip + 240px channel panel)
|
|
- Channels are grouped by `category` field with collapsible headers
|
|
- Members list groups by hoisted roles (isHoist) then Online/Offline
|
|
- Avatar component supports both image URLs and colored-initial fallback
|
|
- Title bar has back/forward navigation arrows
|
|
- Chat header includes thread, pin, members, notification icons + channel topic
|
|
- Voice connected panel includes elapsed time timer
|
|
- Keyboard shortcuts: Ctrl+K (quick switcher), Ctrl+Shift+M (mute toggle)
|
|
|
|
## Environment Variables
|
|
|
|
In `.env.local` at project root:
|
|
- `CONVEX_DEPLOYMENT` - Convex deployment URL (set by `npx convex dev`)
|
|
- `VITE_CONVEX_URL` - Convex URL for frontend (set by `npx convex dev`)
|
|
- `VITE_LIVEKIT_URL` - LiveKit server URL
|
|
- `LIVEKIT_API_KEY` - LiveKit API key (used in Convex Node action)
|
|
- `LIVEKIT_API_SECRET` - LiveKit API secret (used in Convex Node action)
|
|
- `TENOR_API_KEY` - Tenor GIF API key (used in Convex Node action)
|
|
|
|
## Running the App
|
|
|
|
1. `npm install && npm run install:frontend`
|
|
2. `npx convex dev` (starts Convex backend, creates `.env.local`)
|
|
3. In another terminal: `cd Frontend/Electron && npm run dev` (or `npm run electron:dev`)
|