Files
chad/client/CLAUDE.md
2026-02-11 07:05:20 +06:00

5.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Chad is a voice/video chat desktop app built with Tauri 2 + Nuxt 4 (SPA) + mediasoup-client. It uses an SFU (Selective Forwarding Unit) architecture for WebRTC media — each peer sends to the server, which forwards selectively to others.

Commands

Command Description
yarn dev Start dev server (binds to all interfaces via --host)
yarn generate Generate static site to .output/public
yarn build Build for production
yarn preview Preview production build
npx eslint . Lint the project
npx eslint --fix . Lint and auto-fix

Tauri desktop build: yarn tauri build (runs yarn generate first automatically).

Package manager is Yarn 4.12.0. No test framework is configured.

Architecture

Composable-Based State (No Pinia/Vuex)

All state is managed through Vue composables using @vueuse/core's createGlobalState and createSharedComposable. Nuxt auto-imports all composables from app/composables/.

Dependency graph (arrows = "depends on"):

useAuth (foundation — user session)
  └→ useSignaling (Socket.IO connection to /webrtc namespace)
       └→ useClients (connected peer list)
            └→ useMediasoup (transports, producers, consumers)
                 ├← usePreferences (device IDs, audio effects, hotkeys)
                 │    └← useDevices (enumerates hardware via getUserMedia)
                 └← useSfx (Howler.js sound effects)

useApp (top-level orchestrator — mute/unmute, video/share toggles)
  └→ depends on useClients, useMediasoup, useSignaling, useSfx

Composable Tiers

Global state (createGlobalState — single instance, persists for app lifetime):

  • useApp — ready state, input/output mute, video/share toggles, version info
  • useAuthme ref, login/register/logout
  • useClientsclients[] array, add/remove/update peers
  • usePreferences — device selections, audio effects, hotkeys (localStorage + server sync)
  • useUpdater — Tauri app update checks
  • useFullscreenVideo — fullscreen video element control

Shared (createSharedComposable — single instance, disposed when last consumer unmounts):

  • useMediasoup — mediasoup Device, transports, producers, consumers, speaking state
  • useSignaling — Socket.IO client, connect/disconnect
  • useSfx — sound effect playback via Howler.js

Per-instance (new instance per call):

  • useClient(socketId) — per-peer volume/mute (localStorage), filtered consumers/producers
  • useAudioContext(audioTrack) — Web Audio API gain node for per-client volume
  • useDevices — media device enumeration

Initialization Flow

  1. Middleware (global, ordered by filename prefix):
    • 00.updater — Tauri update check, redirects to /updater if available
    • 01.auth — validates session via GET /me, redirects guests to /login
    • 02.user-preferences — loads server-synced preferences for authenticated users
  2. Plugins: build info logging, Tauri hotkey registration
  3. Layout (default.vue): calls useApp() which triggers useSignaling().connect()
  4. Socket authenticated → mediasoup Device created → transports created → join() → mic enabled

mediasoup Integration

Producer types (tracked in appData.source):

  • Microphone: kind='audio', source='mic-video'
  • Camera: kind='video', source='mic-video'
  • Screen share: kind='video', source='share'

Consumer filtering uses kind + appData.source to distinguish audio/video/share streams.

Transports use emitWithAck() on the Socket.IO connection for all signaling (create, connect, produce, join, pause/resume/close).

API & Networking

  • REST API: shared/chad-api.ts$fetch instance with credentials: 'include', base URL from __API_BASE_URL__ build-time define
  • WebSocket: Socket.IO to /webrtc namespace for signaling
  • Vite proxy: /api → production API server (for dev)

Shared Types

shared/types.ts defines ChadClient, Consumer, Producer, AppData, UpdatedClient — used by both composables and components.

Code Conventions

  • ESLint: @antfu/eslint-config with formatters enabled
  • Vue SFC block order: <template>, <script>, <style> (enforced by ESLint)
  • console.log allowed (no-console is off)
  • PrimeVue components are prefixed: PrimeButton, PrimeCard, etc.
  • Icons: lucide-vue-next + primeicons
  • Styling: Tailwind CSS 4 + PrimeVue Aura theme (Zinc palette, dark-first)
  • Reactivity: mediasoup objects wrapped with markRaw() to prevent deep reactivity; triggerRef() used for manual reactivity triggers on the clients array

Build-Time Defines

Set via .env or environment variables:

  • API_BASE_URL — backend API base (default: http://localhost:4000/chad)
  • COMMIT_SHA — git commit hash (default: 'local')

Tauri

  • App identifier: xyz.koptilnya.chad
  • Windows-only NSIS installer (bundle.targets: ["nsis"])
  • Plugins: global-shortcut, process, updater, single-instance, log
  • Frontend dist: .output/public (from yarn generate)
  • @tauri-apps/plugin-* packages provide JS bindings; use window.__TAURI__ check or the useTauri() composable for Tauri detection