Files
DiscordClone/CLAUDE.md
Bryan1029384756 b7a4cf4ce8
All checks were successful
Build and Release / build-and-release (push) Successful in 13m12s
feat(ui): add Button, Modal, Spinner, Toast, and Tooltip components with styles
- Implemented Button component with various props for customization.
- Created Modal component with header, content, and footer subcomponents.
- Added Spinner component for loading indicators.
- Developed Toast component for displaying notifications.
- Introduced Tooltip component for contextual hints with keyboard shortcuts.
- Added corresponding CSS modules for styling each component.
- Updated index file to export new components.
- Configured TypeScript settings for the UI package.
2026-04-14 09:02:14 -05:00

136 lines
7.0 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
**Update this file when making significant changes.**
See also: [CONVEX_RULES.md](./CONVEX_RULES.md) | [CONVEX_EXAMPLES.md](./CONVEX_EXAMPLES.md)
## Architecture
- **Monorepo**: npm workspaces (`packages/*`, `apps/*`)
- **Backend**: Convex (reactive database + serverless functions)
- **Frontend**: React + Vite, shared codebase in `packages/shared/`
- **Platforms**: Electron (`apps/electron/`), Web (`apps/web/`), Android via Capacitor (`apps/android/`)
- **Platform Abstraction**: `usePlatform()` hook provides crypto, session, settings, idle, links, screenCapture, windowControls, updates APIs
- **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**: Platform-specific crypto (Electron: Node crypto via IPC, Web: Web Crypto API)
- **File Storage**: Convex built-in storage (`generateUploadUrl` + `getUrl`)
## Development Commands
```bash
# Install
npm install # Installs all workspaces
# Backend
npx convex dev # Start Convex dev server (creates .env.local)
# Frontend (run alongside backend)
npm run dev:web # Web app at localhost:5173
npm run dev:electron # Electron app (Vite + Electron concurrently)
# Production builds
npm run build:web # Web production build -> apps/web/dist
npm run build:electron # Electron build with electron-builder
npm run build:android # Web build + Capacitor sync
# Android
cd apps/android && npx cap sync && npx cap open android
# Preview
cd apps/web && npx vite preview # Preview web production build
```
**No test framework or linter is configured in this project.**
## Project Structure
```
Discord Clone/
├── convex/ # Backend (Convex functions + schema)
├── packages/
│ ├── shared/ # Shared React app (all components, pages, contexts, styles)
│ │ └── src/
│ │ ├── components/ # All UI components
│ │ ├── pages/ # Login, Register, Chat
│ │ ├── contexts/ # VoiceContext, ThemeContext, PresenceContext
│ │ ├── platform/ # PlatformProvider + usePlatform hook
│ │ ├── styles/ # themes.css
│ │ ├── utils/ # userPreferences.js, streamUtils.jsx
│ │ ├── assets/ # sounds, icons, emojis, fonts
│ │ ├── App.jsx # Router + AuthGuard
│ │ └── index.css # Global styles
│ └── platform-web/ # Web/Capacitor platform implementations
│ └── src/ # Web Crypto API, localStorage session/settings, Page Visibility idle
├── apps/
│ ├── electron/ # Electron desktop app (main.cjs, preload.cjs, updater.cjs)
│ │ └── src/main.jsx # Entry: PlatformProvider + HashRouter
│ ├── web/ # Web browser app (PWA enabled via VitePWA)
│ │ └── src/main.jsx # Entry: PlatformProvider + BrowserRouter
│ └── android/ # Capacitor Android wrapper
├── package.json # Root workspace config
├── .env.local # Convex + LiveKit + Klipy keys
└── CLAUDE.md
```
## Vite & Import Aliases
All Vite configs use `envDir: '../../'` to pick up root `.env.local`.
| Alias | Resolves to |
|-------|-------------|
| `@discord-clone/shared` | `packages/shared/src/` |
| `@discord-clone/platform-web` | `packages/platform-web/src/` |
| `@shared` | `packages/shared/src/` |
Convex imports from shared components use relative path `../../../../convex/_generated/api` (4 levels up from shared src subdirs).
## Platform Abstraction (usePlatform())
All platform-specific APIs are accessed via the `usePlatform()` hook:
- `crypto` - generateKeys, randomBytes, sha256, signMessage, verifySignature, deriveAuthKeys, encryptData, decryptData, decryptBatch, verifyBatch, publicEncrypt, privateDecrypt
- `session` - save, load, clear
- `settings` - get, set
- `idle` - getSystemIdleTime, onIdleStateChanged, removeIdleStateListener
- `links` - openExternal, fetchMetadata
- `screenCapture` - getScreenSources
- `windowControls` - minimize, maximize, close (Electron only, null on web)
- `updates` - checkUpdate (Electron only, null on web)
- `features` - hasWindowControls, hasScreenCapture, hasNativeUpdates
## 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
- 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 grouped by `categoryId` with collapsible headers and @dnd-kit drag-and-drop
- Members list groups by hoisted roles (isHoist) then Online/Offline
- Unread tracking: `channelReadState` table per user/channel. ChatArea shows red "NEW" divider, Sidebar shows white dot
- Server name from `serverSettings` singleton, editable via Server Settings (requires `manage_channels`)
- AFK voice channel: VoiceContext polls idle time, auto-moves idle users
- Custom join sounds: stored as `joinSoundStorageId` on `userProfiles`
- Server icon: `serverSettings` stores `iconStorageId`, resolved to `iconUrl`
- `userPreferences.js` `setUserPref` takes optional `settings` param for disk persistence via platform
- Module-scope functions needing crypto accept it as parameter (e.g., `encryptKeyForUsers(users, channelId, keyHex, crypto)`)
- `randomBytes(size)` returns hex string on both platforms
- Keys exchanged as PEM strings (SPKI public, PKCS8 private) for cross-platform interop
- TitleBar/UpdateBanner render conditionally based on `platform.features.*`
## 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)
- `KLIPY_API_KEY` - Klipy GIF API customer id (used in `convex/gifs.ts`). Replaces the old `TENOR_API_KEY` after Tenor's shutdown — the legacy var name is still read as a fallback so existing deployments only need to swap the value.