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

7.0 KiB

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_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

# 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.