Files
chat/CLAUDE.md
T
2026-06-15 21:21:20 +08:00

5.4 KiB

CLAUDE.md

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

Project Overview

青叶 (QingYe) — a social chat application with teal-green theme (#009688 primary). Monorepo with frontend/ (Vue 3) and backend/ (Python FastAPI), all orchestrated via Docker Compose.

Development Commands

All services run in Docker. No host dependencies needed.

docker compose up --build       # Start all 4 services
docker compose up -d            # Start detached
docker compose down             # Stop
docker compose logs -f backend  # View logs
docker compose restart backend  # Restart a service

Backend runs on localhost:8000, Frontend on localhost:5173. Both have hot-reload via volume mounts. Database changes requiring new columns need manual ALTER TABLE or docker compose restart backend (which triggers Base.metadata.create_all).

Production (dev/prod separation)

Two independent, self-contained Compose files:

  • docker-compose.ymldev (hot-reload, docker compose up). Leave untouched for local dev.
  • docker-compose.prod.ymlprod. Run with:
    docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --build
    
    Secrets come from .env.prod (gitignored; copy from .env.prod.example). Never run bare docker compose up on the server.

CRITICAL prod invariant: the backend must run single-process. The WebSocket ConnectionManager (backend/app/websocket/manager.py) is an in-memory singleton — --workers N / gunicorn multi-worker splits connections and silently breaks real-time messaging. backend/Dockerfile.prod is pinned to single-process; do not change. The frontend prod build is domain-agnostic (same-origin /api/v1, auto wss://). See DEPLOYMENT.md for the full VPS (Ubuntu 20.04 + host Nginx + certbot) walkthrough.

Architecture

Backend (FastAPI + SQLAlchemy 2.0 async)

Pattern: Router → Service → Model, with Pydantic v2 schemas for request/response.

  • backend/app/main.py — App entry, lifespan (creates DB tables, seeds config), router registration at /api/v1/{module}
  • backend/app/config.py — Pydantic Settings from env vars
  • backend/app/database.py — Async engine + session factory + declarative Base
  • backend/app/dependencies.pyget_db(), get_current_user(), get_admin_user()
  • backend/app/utils/security.py — JWT (HS256, 30min access / 7day refresh), bcrypt hashing

API routes: auth, users, conversations, messages, friends, admin, uploads, moments (friend circle)

Models (7 + 3 new): User, Conversation, ConversationMember, Message, Friend, FriendRequest, SystemConfig, Moment, MomentLike, MomentComment

Key convention: All IDs are str(uuid.uuid4()), not auto-increment. Services return dicts, not ORM objects. Timestamps use datetime.utcnow() (NOT timezone-aware — PostgreSQL columns are TIMESTAMP WITHOUT TIME ZONE).

Frontend (Vue 3 + Vite + Naive UI)

Pattern: Composition API with <script setup>, Pinia stores, Axios API modules.

  • frontend/src/main.ts — App entry, globally registers Naive UI components (MUST use N-prefixed names: NButton not Button)
  • frontend/src/layouts/UnifiedLayout.vue — Main authenticated layout: 64px icon sidebar + 300px secondary panel + main content
  • frontend/src/router/index.ts — All auth routes under UnifiedLayout, uses named secondary + default router-views
  • frontend/src/api/client.ts — Axios with JWT interceptors and auto-refresh on 401
  • frontend/src/composables/useWebSocket.ts — WebSocket client with exponential backoff reconnect

CRITICAL: Naive UI components must be registered with N-prefixed names (e.g., app.component('NButton', NButton)) because Vue resolves <n-button> to NButton. The component.name property returns "Button" (no prefix) — do NOT use component.name for registration.

Database

PostgreSQL 16 with tables auto-created on startup. No Alembic migrations set up yet. Adding columns to existing tables requires:

  1. Manual SQL: docker compose exec postgres psql -U qingye -d qingye -c "ALTER TABLE ..."
  2. Then the model update will work

Key Files

File Purpose
docker-compose.yml 4 services: postgres, redis, backend, frontend
frontend/src/layouts/UnifiedLayout.vue Main layout with fixed left icon sidebar
frontend/src/views/chat/ConversationListPanel.vue Reusable conversation list with 3 display modes
frontend/src/views/chat/GroupInfoPanel.vue Group management (members, roles)
frontend/src/views/chat/CreateGroupModal.vue Create group with friend selection
frontend/src/views/moments/MomentsFeedView.vue Friend circle / moments feed
frontend/src/views/moments/MomentCard.vue Single moment card with like/comment
frontend/src/views/settings/ Settings pages: profile, account (password+email), notifications, about
backend/app/services/moment_service.py Moments business logic (feed, like, comment, visibility)
backend/app/services/conversation_service.py Chat + group management (create, update, add/remove members)
backend/app/services/friend_service.py Friend system (request, direct-add, remark)

Environment Variables

Defined in .env.example: DATABASE_URL, REDIS_URL, JWT_SECRET_KEY, JWT_REFRESH_SECRET_KEY, CORS_ORIGINS, ADMIN_PASSWORD, VITE_API_BASE_URL, VITE_WS_BASE_URL.