WatchStack
v0.5.0-beta — eine Watchlist für Bücher, Serien & mehr — inspiriert von MyAnimeList, aber mit eigenem Konzept.
WatchStack ist eine single-user-lokale Watchlist-App. Bücher und Serien teilen sich eine Oberfläche, ein Datenmodell und eine Such- und Filterlogik. Keine Anmeldung, kein Cloud-Zwang — läuft komplett auf deiner Maschine oder in einem Docker-Container.
✨ Features
- 📚 Bücher: Titel, Autor, Bände / Kapitel / Seiten, ISBN, Cover via Open Library
- 📺 Serien: Staffeln, Episoden, Sender / Streaming, Sendezeitraum, Cover-URL
- 🗂 Status: Plan · Laufend · Abgeschlossen · Pausiert · Abgebrochen (5 Stufen, MAL-ähnlich)
- ⭐ Bewertungen 1–10 mit Auto-Status: 0% → Plan, 100% → Done (+
end_date) - 🔎 Suche & Filter: Volltext, Status, Genre, Tag, Sortierung
- 📊 Dashboard: Verteilung pro Medium, Durchschnittsbewertung
- 🏷 Genres & Tags frei verwaltbar
- 🌙 Dark Theme Default, modernes UI mit Hero + Drawer + Modals
- 🐳 Docker-ready: Multi-stage Build, non-root, gunicorn + uvicorn-Worker, healthcheck
- 🌐 CORS offen für lokale Entwicklung; in Produktion via Reverse-Proxy einschränken
⚠️ Beta-Hinweis
v0.5.0-beta bedeutet:
- Kernfunktionalität (CRUD, Suche, Stats, Progress) ist stabil und getestet
- Datenmodell kann sich noch ändern (siehe
models.py— additive Änderungen wahrscheinlich) - Datenbank-Migrationen sind nicht enthalten — bei Major-Upgrades DB sichern
- Public-API-Pfade stabil; Sub-Ressourcen (Genres/Tags) noch in Bewegung
Bitte Issues und Wünsche im Repo melden.
🚀 Quickstart
Option A: Docker (empfohlen)
docker compose up -d
# → http://localhost:8000
# Oder direkt:
docker build -t watchstack:beta .
docker run -d --name watchstack -p 8000:8000 -v watchstack-data:/data watchstack:beta
Die SQLite-DB liegt im benannten Volume watchstack-data (Pfad /data/watchstack.db im Container). Backups: docker run --rm -v watchstack-data:/data -v $PWD:/backup alpine tar czf /backup/ws-$(date +%F).tgz /data.
Option B: Lokal (Python 3.11+)
git clone https://git.pkop.de/Vibecode/watchlist.git
cd watchlist
./run.sh # legt venv an, installiert deps, startet auf 127.0.0.1:8000
Option C: Manuell
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload
🔧 Konfiguration (Umgebungsvariablen)
| Variable | Default | Zweck |
|---|---|---|
WATCHSTACK_DATA_DIR |
./data |
Pfad für SQLite-DB (im Container: /data) |
WATCHSTACK_HOST |
127.0.0.1 |
Bind-Adresse (Docker: 0.0.0.0) |
WATCHSTACK_PORT |
8000 |
HTTP-Port |
WATCHSTACK_WORKERS |
2 |
gunicorn-Worker (nur Docker) |
WATCHSTACK_HTTP_TIMEOUT |
8 |
Timeout für Open-Library-Lookup (Sek.) |
📚 API-Übersicht
| Methode | Pfad | Zweck |
|---|---|---|
| GET | /api/health |
Service-Info + Version |
| GET | /api/media |
Liste, Filter via Query-Params |
| POST | /api/media |
Anlegen (201) |
| GET | /api/media/{id} |
Detail |
| PATCH | /api/media/{id} |
Teil-Update |
| DELETE | /api/media/{id} |
Löschen (204) |
| POST | /api/media/{id}/progress |
{"delta":1} oder {"set_to":N} |
| GET | /api/genres, /api/tags |
Taxonomien |
| GET | /api/stats |
Verteilungen + ⌀-Bewertung |
| GET | /api/lookup/book?isbn=… |
Cover via Open Library |
Beispiel — neuen Eintrag anlegen:
curl -X POST http://localhost:8000/api/media \
-H 'Content-Type: application/json' \
-d '{
"kind": "book",
"title": "Der Name des Windes",
"author": "Patrick Rothfuss",
"total_pages": 662, "pages_read": 100,
"status": "reading", "rating": 9.0,
"genres": ["Fantasy"], "tags": ["Königsmörder"]
}'
Vollständige interaktive Doku: http://localhost:8000/docs (Swagger UI, von FastAPI generiert).
🏗 Projektstruktur
watchlist/
├── app/
│ ├── __init__.py # __version__
│ ├── main.py # FastAPI-App + Routen
│ ├── database.py # Engine + Session
│ ├── models.py # SQLAlchemy-Modelle
│ ├── schemas.py # Pydantic-Schemas
│ ├── crud.py # DB-Operationen
│ ├── external.py # Open-Library-Client
│ ├── seed.py # Demo-Daten
│ └── static/ # Frontend (HTML/CSS/JS)
├── data/ # SQLite-DB (gitignored, Volume im Container)
├── .github/workflows/ # CI
├── Dockerfile # Multi-stage Build
├── docker-compose.yml
├── LICENSE # Apache-2.0 (offizieller Volltext)
├── NOTICE # Copyright + Drittanbieter
└── README.md
🛠 Entwicklung
# Tests (bisher Smoke-Tests ad-hoc; pytest-Suite ist Roadmap)
python -c "from app.main import app; print(app.title, app.version)"
# Code-Style
ruff check app/ # (optional, nicht in requirements)
📜 Lizenz
Apache License 2.0 — siehe LICENSE (vollständiger Text) und NOTICE (Drittanbieter-Hinweise).
Kurzfassung: Du darfst das Projekt privat und kommerziell nutzen, verändern, weitergeben — unter Beibehaltung des Copyright-Hinweises und der Lizenz. Es gibt keine Patent-Gewähr; Änderungen müssen markiert werden. Volltext in der LICENSE-Datei.
🤝 Contributing
PRs willkommen — am besten mit Issue vorab. Bitte:
- Coding-Style einhalten (PEP 8, KISS, DRY)
- Keine externen Tracker; Issues im Gitea-Repo
- Tests für neue Logik (pytest-Suite kommt)
🔮 Roadmap
- pytest-Suite mit Coverage-Report
- Backup-/Restore-Endpoint
- Import von MAL-XML / Trakt-Listen
- Manga als dritte Medienart (Volumes, Chapters)
- Multi-User mit OIDC-Login (optional, hinter Feature-Flag)
- Cover-Caching-Proxy
- Deutsche Übersetzungen der Status-Labels i18n-ready