# App Core (app/) ## OVERVIEW FastAPI application core — config, auth, download management, providers, and business logic. Routes are in `routers/`, scrapers in `downloaders/`, models in `models/`. ## STRUCTURE ``` app/ ├── config.py # Pydantic Settings (loads .env) ├── database.py # SQLModel engine (created at import time) ├── download_manager.py # Async download queue (semaphore-based) ├── auth.py # JWT + bcrypt, JSON-backed UserManager ├── providers.py # ANIME_PROVIDERS, FILE_HOSTS registries ├── utils.py # sanitize_filename(), is_safe_filename() ├── watchlist.py # WatchlistManager (JSON + SQLModel hybrid) ├── episode_checker.py # New episode detection for watchlist ├── auto_download_scheduler.py # APScheduler periodic checks ├── sonarr_handler.py # Sonarr webhook processing ├── favorites.py # FavoritesManager (JSON-backed) ├── recommendation_engine.py # Download history analysis ├── recommendations.py # Latest releases fetcher └── kitsu_api.py # Kitsu anime metadata API ``` ## WHERE TO LOOK | Need | File | Notes | |------|------|-------| | Add env var | `config.py` | Add to Settings class, update `.env.example` | | Add provider domain | `providers.py` | ANIME_PROVIDERS or FILE_HOSTS dict | | Download queue logic | `download_manager.py` | Semaphore-limited parallel downloads | | Auth/token logic | `auth.py` | UserManager, JWT create/verify | | Filename safety | `utils.py` | ALWAYS use sanitize_filename() | ## CONVENTIONS **Circular import avoidance**: `episode_checker.py` uses lazy init (`set_download_manager()`) — called from `main.py:47` after both modules loaded. **Dual storage**: Some features use JSON files (favorites, users) + SQLModel tables (watchlist, sonarr mappings). JSON is legacy, SQLModel is newer. **Module-level side effects**: `database.py` creates engine on import. `main.py` creates `download_manager` on import (line 44). `restore_completed_downloads()` runs at module level (line 108). ## ANTI-PATTERNS - Do NOT import `download_manager` from `main.py` in other app/ modules — causes circular imports - Do NOT use `requests` — always `httpx.AsyncClient` - Do NOT store secrets in `config/*.json` — use `.env`