10 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Reflector is an AI-powered audio transcription and meeting analysis platform with real-time processing capabilities. The system consists of:
- Frontend: Next.js 16 React application (
www/) with Chakra UI, real-time WebSocket integration - Backend: Python FastAPI server (
server/) with async database operations and background processing - Processing: GPU-accelerated ML pipeline for transcription, diarization, summarization via Modal.com
- Infrastructure: Redis, PostgreSQL/SQLite, Celery workers, WebRTC streaming
Development Commands
Backend (Python) - cd server/
Setup and Dependencies:
# Install dependencies
uv sync
# Database migrations (first run or schema changes)
uv run alembic upgrade head
# Start services
docker compose up -d redis
Development:
# Start FastAPI server
uv run -m reflector.app --reload
# Start Celery worker for background tasks
uv run celery -A reflector.worker.app worker --loglevel=info
# Start Celery beat scheduler (optional, for cron jobs)
uv run celery -A reflector.worker.app beat
Testing:
# Run all tests with coverage (requires Redis on localhost)
REDIS_HOST=localhost REDIS_PORT=6379 uv run pytest
# Run specific test file
REDIS_HOST=localhost REDIS_PORT=6379 uv run pytest tests/test_transcripts.py
# Run tests with verbose output
REDIS_HOST=localhost REDIS_PORT=6379 uv run pytest -v
Process Audio Files:
# Process local audio file manually
uv run python -m reflector.tools.process path/to/audio.wav
Frontend (Next.js) - cd www/
Setup:
# Install dependencies
pnpm install
# Copy configuration templates
cp .env_template .env
Development:
# Start development server
pnpm dev
# Generate TypeScript API client from OpenAPI spec
pnpm openapi
# Lint code
pnpm lint
# Format code
pnpm format
# Build for production
pnpm build
Docker Compose (Full Stack)
# Start all services
docker compose up -d
# Start specific services
docker compose up -d redis server worker
Architecture Overview
Backend Processing Pipeline
The audio processing follows a modular pipeline architecture:
- Audio Input: WebRTC streaming, file upload, or cloud recording ingestion
- Chunking: Audio split into processable segments (
AudioChunkerProcessor) - Transcription: Whisper or Modal.com GPU processing (
AudioTranscriptAutoProcessor) - Diarization: Speaker identification (
AudioDiarizationAutoProcessor) - Text Processing: Formatting, translation, topic detection
- Summarization: AI-powered summaries and title generation
- Storage: Database persistence with optional S3 backend
Database Models
Core entities:
transcript: Main table with processing results, summaries, topics, participantsmeeting: Live meeting sessions with consent managementroom: Virtual meeting spaces with configurationrecording: Audio/video file metadata and processing status
API Structure
All endpoints prefixed /v1/:
transcripts/- CRUD operations for transcriptstranscripts_audio/- Audio streaming and downloadtranscripts_webrtc/- Real-time WebRTC endpointstranscripts_websocket/- WebSocket for live updatesmeetings/- Meeting lifecycle managementrooms/- Virtual room management
Frontend Architecture
- App Router: Next.js 14 with route groups for organization
- State: React Context pattern, no Redux
- Real-time: WebSocket integration for live transcription updates
- Auth: NextAuth.js with Authentik OAuth/OIDC provider
- UI: Chakra UI components with Tailwind CSS utilities
Key Configuration
Environment Variables
Backend (server/.env):
DATABASE_URL- Database connection stringREDIS_URL- Redis broker for CeleryTRANSCRIPT_BACKEND=modal+TRANSCRIPT_MODAL_API_KEY- Modal.com transcriptionDIARIZATION_BACKEND=modal+DIARIZATION_MODAL_API_KEY- Modal.com diarizationTRANSLATION_BACKEND=modal+TRANSLATION_MODAL_API_KEY- Modal.com translationWHEREBY_API_KEY- Video platform integrationREFLECTOR_AUTH_BACKEND- Authentication method (none, jwt)
Frontend (www/.env):
NEXTAUTH_URL,NEXTAUTH_SECRET- Authentication configurationREFLECTOR_API_URL- Backend API endpointREFLECTOR_DOMAIN_CONFIG- Feature flags and domain settings
Testing Strategy
- Backend: pytest with async support, HTTP client mocking, audio processing tests
- Frontend: No current test suite - opportunities for Jest/React Testing Library
- Coverage: Backend maintains test coverage reports in
htmlcov/
Integration Tests (DO NOT run unless explicitly asked)
There are end-to-end integration tests in server/tests/integration/ that spin up the full stack (PostgreSQL, Redis, Hatchet, Garage, mock-daily, server, workers) via Docker Compose and exercise real processing pipelines. These tests are:
test_file_pipeline.py— File upload → FilePipelinetest_live_pipeline.py— WebRTC stream → LivePostPipelinetest_multitrack_pipeline.py— Multitrack → DailyMultitrackPipeline
Important:
- These tests are excluded from normal
uv run pytestruns via--ignore=tests/integrationin pyproject.toml. - Do NOT run them as part of verification, code review, or general testing unless the user explicitly asks.
- They require Docker, external LLM credentials, and HuggingFace token — they cannot run in a regular test environment.
- To run locally:
./scripts/run-integration-tests.sh(requires env vars:LLM_URL,LLM_API_KEY,HF_TOKEN). - In CI: triggered manually via the "Integration Tests" GitHub Actions workflow (
workflow_dispatch).
GPU Processing
Modal.com integration for scalable ML processing:
- Deploy changes:
modal run server/gpu/path/to/model.py - Requires Modal account with
REFLECTOR_GPU_APIKEYsecret - Fallback to local processing when Modal unavailable
Common Issues
- Permissions: Browser microphone access required in System Preferences
- Audio Routing: Use BlackHole (Mac) for merging multiple audio sources
- WebRTC: Ensure proper CORS configuration for cross-origin streaming
- Database: Run
uv run alembic upgrade headafter pulling schema changes
Pipeline/worker related info
If you need to do any worker/pipeline related work, search for "Pipeline" classes and their "create" or "build" methods to find the main processor sequence. Look for task orchestration patterns (like "chord", "group", or "chain") to identify the post-processing flow with parallel execution chains. This will give you abstract vision on how processing pipeling is organized.
Documentation
- New documentation files go in
docsv2/, not indocs/docs/. - Existing
docs/directory contains legacy Docusaurus docs.
Code Style
- Always put imports at the top of the file. Let ruff/pre-commit handle sorting and formatting of imports.
- The only imports allowed to remain inline are from
reflector.db.*modules (e.g.,reflector.db.transcripts,reflector.db.meetings,reflector.db.recordings,reflector.db.rooms). These stay as deferred/inline imports insidefresh_db_connection()blocks in Hatchet pipeline task functions — this is intentional to avoid sharing DB connections across forked processes. All other imports (utilities, services, processors, storage, third-party libs) must go at the top of the file, even in Hatchet workflows.
This project uses the Greyhaven Design System.
Rules
- ALWAYS use TypeScript (
.tsx/.ts). NEVER generate plain JavaScript (.jsx/.js). - Use the
greyhavenSKILL.md for full design system context (tokens, components, composition rules). It should be installed at.claude/skills/greyhaven-design-system.mdor accessible to your AI tool. - If the
greyhavenMCP server is available, use its tools:list_components()to find the right component for a UI needget_component(name)to get exact props, variants, and usage examplesvalidate_colors(code)to check code for off-brand colorssuggest_component(description)to get recommendations
- Import components from
components/ui/(or@/components/ui/with path alias) - Never use raw hex colors -- use semantic Tailwind classes (
bg-primary,text-foreground,border-border, etc.) - Use
font-sans(Aspekta) for UI elements: buttons, nav, labels, forms - Use
font-serif(Source Serif) for content: headings, body text - Trust the design system's default component variants for accent -- they apply orange at the right scale. Don't apply
bg-primaryto large surfaces, containers, or section backgrounds - All components are framework-agnostic React (no Next.js, no framework-specific imports)
- Dark mode is toggled via the
.darkclass -- use semantic tokens that adapt automatically
Component Summary
38 components across 8 categories: primitives (11), layout (4), overlay (5), navigation (3), data (4), feedback (4), form (1), composition (6).
For full component specs, props, and examples, refer to the SKILL.md file or use the MCP get_component(name) tool.
Key Patterns
- CVA variants: Components use
class-variance-authorityfor variant props - Slot composition: Components use
data-slot="name"attributes - Class merging: Always use
cn()from@/lib/utils(clsx + tailwind-merge) - Focus rings:
focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] - Disabled:
disabled:pointer-events-none disabled:opacity-50 - Card spacing:
gap-6between cards,p-6internal padding - Section rhythm:
py-16between major sections - Form layout: Vertical stack with
gap-4, labels above inputs
Font Setup
If fonts aren't loaded yet, add to your global CSS:
@font-face { font-family: 'Aspekta'; font-weight: 400; font-display: swap; src: url('/fonts/Aspekta-400.woff2') format('woff2'); }
@font-face { font-family: 'Aspekta'; font-weight: 500; font-display: swap; src: url('/fonts/Aspekta-500.woff2') format('woff2'); }
@font-face { font-family: 'Aspekta'; font-weight: 600; font-display: swap; src: url('/fonts/Aspekta-600.woff2') format('woff2'); }
@font-face { font-family: 'Aspekta'; font-weight: 700; font-display: swap; src: url('/fonts/Aspekta-700.woff2') format('woff2'); }