Development Guide
Project Structure
mediatree/
├── backend/ # Python 3.12 + FastAPI
│ ├── app/
│ │ ├── main.py # FastAPI app and route handlers
│ │ ├── scanner.py # scanning and scraping engine
│ │ ├── database.py # SQLite CRUD
│ │ ├── config.py # pydantic-settings + JSON persistence
│ │ ├── stream.py # video stream, Range, transcoding
│ │ ├── subtitles.py # subtitle detection and conversion
│ │ └── scrapers/ # scraper plugin system
│ └── tests/
├── frontend/ # React 18 + TypeScript + Vite
├── docs-site/ # VitePress documentation site
└── DockerfileLocal Development
Production serves the built frontend from the backend. Development usually runs two processes:
# Backend
cd backend
pip install -r requirements.txt -c constraints.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 80
# Frontend
cd frontend
npm install
npm run devThe Vite dev server proxies /api/* to localhost:80.
Docs Site Development
cd docs-site
npm ci
npm run devBuild:
cd docs-site
npm run buildThe docs site deploys to GitHub Pages at /mediatree/. Keep the docs deployment workflow separate from app-package release publishing.
Tests and Builds
cd backend && PYTHONPATH=. python3.11 -m unittest discover -s tests -p 'test_*.py'
python3.11 -m compileall -q backend/app
cd frontend && npm run buildOn macOS, local python3 may point to an older version. Prefer Python 3.11+. The production image uses Python 3.12.
Adding APIs
- Add the route in
backend/app/main.py. - Add CRUD in
backend/app/database.pywhen persistence is needed. - Add a typed frontend client method in
frontend/src/api.ts. - Use it from pages or components and add tests.
Adding Scrapers
User-installable scrapers should be packaged as .zip plugins with plugin.json and a Python entry class that inherits BaseScraper. The full plugin package structure, manifest fields, install/enable flow, and test checklist are currently documented in the Chinese Scraper Plugin Guide.
When maintaining built-in scrapers, use backend/app/builtin_plugins/scrapers/<name>/plugin.json and plugin.py to connect them to the manifest-driven registry. Shared core logic can still live under backend/app/scrapers/. Built-in scrapers also appear in Settings plugin management, where users can disable or hide them.
