# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a cloud photo and video storage service with a React frontend (SPA hosted in S3) and a Python FastAPI backend. The project uses S3 for file storage and starts with SQLite for metadata, with a migration path to PostgreSQL. **Primary Language:** Russian (comments and documentation may be in Russian) ## Tech Stack ### Backend - **Framework:** FastAPI (ASGI) - **ORM:** SQLAlchemy 2.x (async) with Alembic migrations - **Database:** SQLite (MVP) → PostgreSQL (future) - **S3 SDK:** boto3 or aioboto3 - **Authentication:** JWT (access + refresh tokens) - **Background Tasks:** Redis + RQ (recommended for thumbnail generation) - **Testing:** pytest + httpx - **Linting/Formatting:** ruff + black (or ruff format) ### Frontend - **Framework:** React - **UI Library:** Material UI (MUI) - **Build Tool:** Vite - **Deployment:** Static files in `static/` folder → S3 hosting ### Infrastructure - **File Storage:** S3 or S3-compatible (MinIO for development) - **Queue:** Redis (for background workers) ## Architecture Principles ### Layered Architecture (Clean Architecture) The backend follows strict separation of concerns: - **`api/`** - Routes, schemas, dependencies, auth middleware - **`services/`** - Business logic (upload, library, share management) - **`repositories/`** - Data access layer (CRUD operations) - **`infra/`** - S3 client, database session factory, config, background tasks - **`domain/`** - Domain models and interfaces (as needed) ### Code Quality Standards - **SOLID principles** are mandatory - **DRY (Don't Repeat Yourself)** - **Docstrings required** for all public methods/classes and main services - **Minimal code comments** - prefer self-documenting code and docstrings - **Stable API contract** - maintain OpenAPI/Swagger compatibility ### Security Requirements - Never store passwords in plaintext - use argon2id or bcrypt - All S3 access must use pre-signed URLs with short TTL - Validate all input with Pydantic - Check asset ownership in all endpoints - CORS must be strictly configured - CSRF protection for cookie-based auth ## Planned Project Structure ``` repo/ backend/ src/ app/ api/ v1/ # API routes versioned services/ # Business logic layer repositories/ # Data access layer infra/ # Infrastructure (S3, DB, config) domain/ # Domain models main.py # Application entry point alembic/ # Database migrations tests/ pyproject.toml Dockerfile frontend/ src/ public/ vite.config.js package.json static/ # Build output (deployed to S3) docker-compose.yml ``` ## Data Model ### Core Entities **users**: User accounts (id, email, password_hash, created_at, updated_at, is_active) **assets**: Media files with metadata - Type: photo | video - Status: uploading | ready | failed | deleted - Includes: original_filename, content_type, size_bytes, sha256, captured_at - S3 keys: storage_key_original, storage_key_thumb - Soft delete support via deleted_at **shares**: Public/private sharing links - Links to either a single asset or album - Supports expiration (expires_at) and revocation (revoked_at) - Optional password protection **albums** (v1): Logical grouping of assets **tags** (v1): Tagging system for assets ## S3 Storage Structure - **Bucket:** Private, access only via pre-signed URLs - **Original files:** `u/{user_id}/o/{yyyy}/{mm}/{asset_id}{ext}` - **Thumbnails:** `u/{user_id}/t/{yyyy}/{mm}/{asset_id}.jpg` - **Video posters (v1):** `u/{user_id}/p/{yyyy}/{mm}/{asset_id}.jpg` ## Upload Flow 1. Frontend requests `POST /api/v1/uploads/create` with file metadata 2. Backend returns pre-signed URL or multipart upload credentials 3. Frontend uploads file directly to S3 4. Frontend calls `POST /api/v1/uploads/{asset_id}/finalize` 5. Backend saves metadata and enqueues thumbnail generation task ## API Structure Base path: `/api/v1` ### Authentication - `POST /api/v1/auth/register` - `POST /api/v1/auth/login` - `POST /api/v1/auth/logout` - `GET /api/v1/auth/me` ### Assets (Library) - `GET /api/v1/assets` - List with cursor-based pagination - `GET /api/v1/assets/{asset_id}` - `DELETE /api/v1/assets/{asset_id}` - Soft delete - `POST /api/v1/assets/{asset_id}/restore` - `DELETE /api/v1/assets/{asset_id}/purge` - Hard delete from trash ### Upload - `POST /api/v1/uploads/create` - `POST /api/v1/uploads/{asset_id}/finalize` ### Access URLs - `GET /api/v1/assets/{asset_id}/download-url?kind=original|thumb` - `GET /api/v1/assets/{asset_id}/stream-url` - For video ### Shares - `POST /api/v1/shares` - Create share link - `GET /api/v1/shares/{token}` - `GET /api/v1/shares/{token}/download-url?asset_id=&kind=` - `POST /api/v1/shares/{token}/revoke` ## Environment Variables Key backend environment variables (see [tech_spec_cloud_media_storage.md](tech_spec_cloud_media_storage.md) section 13 for full list): - `APP_ENV=dev|prod` - `DATABASE_URL=sqlite+aiosqlite:///./app.db` (or PostgreSQL connection string) - `S3_ENDPOINT_URL` - For MinIO or custom S3-compatible storage - `S3_REGION`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY` - `MEDIA_BUCKET` - S3 bucket name - `SIGNED_URL_TTL_SECONDS=600` - `JWT_SECRET`, `JWT_ACCESS_TTL_SECONDS`, `JWT_REFRESH_TTL_SECONDS` - `MAX_UPLOAD_SIZE_BYTES` - File size limit - `CORS_ORIGINS` - Allowed frontend origins ## Database Migrations - All schema changes MUST go through Alembic migrations - No raw SQL in application code (except migrations) - Schema must be compatible with both SQLite (MVP) and PostgreSQL - UUID stored as TEXT in SQLite, native UUID in PostgreSQL ## Development Workflow (When Implemented) ### Backend Development Expected commands once backend is set up: - Start server: `uvicorn app.main:app --reload` - Run tests: `pytest` - Create migration: `alembic revision --autogenerate -m "description"` - Apply migrations: `alembic upgrade head` - Format code: `ruff format .` or `black .` - Lint: `ruff check .` ### Frontend Development Expected commands once frontend is set up: - Install dependencies: `npm install` - Dev server: `npm run dev` - Build for production: `npm run build` (outputs to `static/`) - Lint: `npm run lint` ### Docker Compose (Development) Recommended setup: `docker-compose up` to start: - Backend service - MinIO (S3-compatible storage) - Redis (for background tasks) - PostgreSQL (when migrating from SQLite) ## MVP Acceptance Criteria - User registration and authentication working - Upload photo and video files (including batch upload of 100+ files) - Library displays thumbnails for photos - Photo/video viewer works in browser - Soft delete to trash with restore capability - Public share links work without authentication - SQLite database with migration path to PostgreSQL ready ## Implementation Phases 1. **Foundation:** FastAPI skeleton, DB config, migrations, auth 2. **Assets:** CRUD for assets, library listing with pagination, trash management 3. **Frontend MVP:** Login, library grid, upload dialog, viewer, trash UI 4. **Thumbnails:** Background generation and display 5. **Shares:** Create and access share links, shared view UI ## Important Notes - This project follows **Clean Architecture** - respect layer boundaries - All file access goes through **pre-signed S3 URLs**, never direct access - Use **cursor-based pagination** for listing endpoints - **Thumbnails reduce bandwidth** - originals loaded only on demand - For large files, use **S3 multipart upload** - Background tasks via **Redis + RQ** for thumbnail/poster generation - Support both **inline** (MVP acceptable) and **background** thumbnail generation ## Reference Documentation For detailed technical requirements, see [tech_spec_cloud_media_storage.md](tech_spec_cloud_media_storage.md).