Files
2026-03-17 18:11:23 +03:00

3.0 KiB

CLAUDE.md — Coffee Project Backend

See also the monorepo-level ../CLAUDE.md for full architecture overview.

Commands

uv sync                                          # Install dependencies
uv run uvicorn cpv3.main:app --reload            # Dev server (localhost:8000)
uv run pytest                                    # Run all tests
uv run pytest tests/integration/<file>.py        # Single test file
uv run alembic revision --autogenerate -m "msg"  # Create migration
uv run alembic upgrade head                      # Apply migrations
uv run dramatiq cpv3.modules.tasks.service       # Start background worker
uv run ruff check cpv3/                          # Lint
uv run ruff format cpv3/                         # Auto-format
docker-compose up                                # Full stack (DB, Redis, MinIO, API, Worker)

Architecture

Layered module pattern. Each module has exactly 5-6 files (__init__.py, models.py, schemas.py, repository.py, service.py, router.py). No subdirectories within modules. When in doubt, put logic in service.py.

cpv3/
├── main.py              # FastAPI app, CORS, router registration
├── api/v1/router.py     # Aggregates all module routers
├── common/schemas.py    # Base Schema class (Pydantic, from_attributes=True)
├── db/                  # Base, session, model imports
├── infrastructure/      # Auth, security, settings, storage
└── modules/             # Feature modules (users, projects, media, files, etc.)

Key Patterns

  • Database: PostgreSQL 16, async SQLAlchemy (AsyncSession), all models inherit Base + BaseModelMixin.
  • Soft deletes: is_deleted flag — repositories filter by default.
  • Auth: JWT access + refresh tokens in HTTP-only cookies. Use get_current_user dependency.
  • Config: get_settings() from cpv3/infrastructure/settings.py (cached with @lru_cache).
  • Background tasks: Dramatiq with Redis broker. Actors live in cpv3/modules/tasks/service.py.
  • Package manager: uv only — uv sync, uv add <pkg>, uv run <cmd>.
  • Linting: Ruff (line length 100, config in pyproject.toml).

Common Gotchas

  • Async sessions: Never mix sync and async DB operations. Use await on all session calls.
  • Module structure: Do not create extra files or subdirectories. Standard files only: models.py, schemas.py, repository.py, service.py, router.py.
  • Schemas: Always inherit from cpv3.common.schemas.Schema, not raw Pydantic BaseModel.
  • Imports: Use absolute paths (from cpv3.modules.media.schemas import ...), not relative.
  • Error messages: Store as module-level constants with ERROR_ prefix, not inline strings.
  • CPU-bound work: Use anyio.to_thread.run_sync() to avoid blocking the event loop.

Docker Services

postgres  → localhost:5332    minio   → localhost:9000 (console: 9001)
redis     → localhost:6379    api     → localhost:8000 (OpenAPI at /api/schema/)