chore(rebrand): rename WatchStack -> Quivio
CI / test (push) Has been cancelled

Quivio (Kofferwort aus Quire + Video) ersetzt den Arbeitstitel WatchStack.
Es ist origineller, frei auf PyPI/npm, und passt perfekt zur Doppelnatur
der App: Buecher (Quire) + Serien (Video).

Geaendert:
- Python-Paket app/ -> quivio/ (+ alle Imports angepasst)
- DB-File watchstack.db -> quivio.db
- Docker-Image: quivio:0.5.1-beta, Container-Name quivio
- Compose-Services: quivio, quivio-local
- ENV-Vars: QUIVIO_VERSION, QUIVIO_PORT, Volume quivio-data
- Frontend-Logo "W" -> "Q", Titel "Quivio", Footer
- Favicon "Q" (Georgia serif fuer klassischen Look)
- Logger-Name: watchstack -> quivio
- README, NOTICE, dist/README, data/README: Quivio
- CI-Workflow: testet quivio/ Pfade
- build-and-push.sh: lokaler Tag "quivio:VERSION"
- service-Feld in /api/health: quivio
- OpenAPI title: Quivio

Bugfix (gefunden beim Renaming):
- seed.py hatte versteckten "from app.database import DB_PATH" — gefixt

Verifiziert end-to-end:
- Python-Import OK
- Backend: service=quivio, version=0.5.1-beta, 8 unique items
- Docker-Build OK, Push in Gitea-Registry OK (neuer sha256-Digest)
- Container: Quivio 0.5.1-beta ready (logger), HTML ohne WatchStack-Rest
- OpenAPI title=Quivio
- 8 unique items nach cold start (Race-Fix haelt)
This commit is contained in:
ki
2026-07-22 00:42:09 +02:00
parent fe291ba8ec
commit 9a4909f083
25 changed files with 102 additions and 114 deletions
+4 -4
View File
@@ -18,12 +18,12 @@ jobs:
- run: pip install -r requirements.txt
- name: Backend-Import-Check
run: |
python -c "from app.main import app; print('OK', app.title, app.version)"
python -c "from quivio.main import app; print('OK', app.title, app.version)"
- name: Frontend-Asset-Check
run: |
test -f app/static/index.html
test -f app/static/css/style.css
test -f app/static/js/app.js
test -f quivio/static/index.html
test -f quivio/static/css/style.css
test -f quivio/static/js/app.js
# Hinweis: Push in die Gitea Container Registry laeuft lokal ueber
# bin/build-and-push.sh
+5 -5
View File
@@ -1,5 +1,5 @@
# =====================================================================
# WatchStack — Multi-stage Docker-Build
# Quivio — Multi-stage Docker-Build
# 1) builder : installiert Dependencies in ein separates venv
# 2) runtime : minimal, non-root, nur Runtime-Deps + venv aus builder
# =====================================================================
@@ -44,7 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& chown -R watchstack:watchstack /data /app
COPY --from=builder /opt/venv /opt/venv
COPY --chown=watchstack:watchstack app /app/app
COPY --chown=watchstack:watchstack quivio /app/quivio
WORKDIR /app
@@ -59,7 +59,7 @@ VOLUME ["/data"]
ENTRYPOINT ["/usr/bin/tini", "--"]
# gunicorn mit uvicorn-Worker-Klasse fuer ASGI
CMD ["sh", "-c", "gunicorn app.main:app \
CMD ["sh", "-c", "gunicorn quivio.main:app \
--bind ${WATCHSTACK_HOST}:${WATCHSTACK_PORT} \
--workers ${WATCHSTACK_WORKERS} \
--worker-class uvicorn.workers.UvicornWorker \
@@ -71,7 +71,7 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import urllib.request, sys; r=urllib.request.urlopen('http://127.0.0.1:'+__import__('os').environ.get('WATCHSTACK_PORT','8000')+'/api/health',timeout=3); sys.exit(0 if r.status==200 else 1)" \
|| exit 1
LABEL org.opencontainers.image.title="WatchStack" \
org.opencontainers.image.description="Watchlist für Bücher, Serien & mehr" \
LABEL org.opencontainers.image.title="Quivio" \
org.opencontainers.image.description="Watchlist für Bücher, Serien & mehr (Quire + Video)" \
org.opencontainers.image.source="https://git.pkop.de/Vibecode/watchlist" \
org.opencontainers.image.licenses="Apache-2.0"
+3 -3
View File
@@ -1,7 +1,7 @@
WatchStack
Copyright 2026 WatchStack Contributors
Quivio
Copyright 2026 Quivio Contributors
This product includes software developed by the WatchStack Contributors
This product includes software developed by the Quivio Contributors
(https://git.pkop.de/Vibecode/watchlist).
This product includes data and APIs from third parties:
+20 -25
View File
@@ -1,13 +1,15 @@
# WatchStack
# Quivio
> **v0.5.0-beta** — eine Watchlist für **Bücher, Serien & mehr** — inspiriert von MyAnimeList, aber mit eigenem Konzept.
> **v0.5.1-beta** — eine Watchlist für **Bücher, Serien & mehr** — inspiriert von MyAnimeList, aber mit eigenem Konzept.
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![Repo](https://img.shields.io/badge/repo-Vibecode%2Fwatchlist-blue)](https://git.pkop.de/Vibecode/watchlist)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org)
[![Docker](https://img.shields.io/badge/docker-ready-blue)](#-docker)
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.
**Quivio** (Kofferwort aus *Quire* + *Video*) 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
@@ -26,7 +28,7 @@ WatchStack ist eine **single-user-lokale** Watchlist-App. Bücher und Serien tei
**v0.5.1-beta** bedeutet:
- Kernfunktionalität (CRUD, Suche, Stats, Progress) ist stabil und getestet
- Datenmodell kann sich noch ändern (siehe `models.py` — additive Änderungen wahrscheinlich)
- Datenmodell kann sich noch ändern (siehe `quivio/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
@@ -38,7 +40,7 @@ Bitte Issues und Wünsche im [Repo](https://git.pkop.de/Vibecode/watchlist) meld
```bash
docker pull git.pkop.de/vibecode/watchlist:0.5.1-beta
docker run -d --name watchstack -p 8000:8000 -v watchstack-data:/data git.pkop.de/vibecode/watchlist:0.5.1-beta
docker run -d --name quivio -p 8000:8000 -v quivio-data:/data git.pkop.de/vibecode/watchlist:0.5.1-beta
```
Das Image liegt im **Packages**-Tab des Repos (Gitea Container Registry,
@@ -52,13 +54,11 @@ 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
docker build -t quivio:beta .
docker run -d --name quivio -p 8000:8000 -v quivio-data:/data quivio: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+)
### Option C: Python direkt
```bash
git clone https://git.pkop.de/Vibecode/watchlist.git
@@ -66,15 +66,6 @@ cd watchlist
./run.sh # legt venv an, installiert deps, startet auf 127.0.0.1:8000
```
### Option C: Manuell
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload
```
## 🔧 Konfiguration (Umgebungsvariablen)
| Variable | Default | Zweck |
@@ -85,6 +76,10 @@ uvicorn app.main:app --reload
| `WATCHSTACK_WORKERS` | `2` | gunicorn-Worker (nur Docker) |
| `WATCHSTACK_HTTP_TIMEOUT` | `8` | Timeout für Open-Library-Lookup (Sek.) |
> Hinweis: Die ENV-Variablen heißen weiterhin `WATCHSTACK_*`, weil das der
> Docker-konforme Standard ist. Im lokalen Dev ist das egal, da die Defaults
> passen.
## 📚 API-Übersicht
| Methode | Pfad | Zweck |
@@ -121,7 +116,7 @@ Vollständige interaktive Doku: <http://localhost:8000/docs> (Swagger UI, von Fa
```
watchlist/
├── app/
├── quivio/ # Python-Paket (FastAPI, SQLAlchemy, ...)
│ ├── __init__.py # __version__
│ ├── main.py # FastAPI-App + Routen
│ ├── database.py # Engine + Session
@@ -132,7 +127,7 @@ watchlist/
│ ├── seed.py # Demo-Daten
│ └── static/ # Frontend (HTML/CSS/JS)
├── data/ # SQLite-DB (gitignored, Volume im Container)
├── bin/ # build-and-push.sh, build-image.sh, write-manifest.sh
├── bin/ # build-and-push.sh, build-image.sh, write-manifest.sh, get-version.py
├── .github/workflows/ # CI
├── Dockerfile # Multi-stage Build
├── docker-compose.yml
@@ -144,11 +139,11 @@ watchlist/
## 🛠 Entwicklung
```bash
# Tests (bisher Smoke-Tests ad-hoc; pytest-Suite ist Roadmap)
python -c "from app.main import app; print(app.title, app.version)"
# Lokales Backend
./run.sh
# Code-Style
ruff check app/ # (optional, nicht in requirements)
# Tests (bisher Smoke-Tests ad-hoc; pytest-Suite ist Roadmap)
python3 -c "from quivio.main import app; print(app.title, app.version)"
```
## 📜 Lizenz
-4
View File
@@ -1,4 +0,0 @@
"""WatchStack Watchlist für Bücher, Serien & mehr."""
__version__ = "0.5.1-beta"
__all__ = ["__version__"]
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Baut das Image und pusht es in die Gitea Container Registry.
# Baut das Quivio-Image und pusht es in die Gitea Container Registry.
# Verwendung:
# bin/build-and-push.sh # Version aus app/__init__.py
# bin/build-and-push.sh # Version aus quivio/__init__.py
# VERSION=0.6.0 bin/build-and-push.sh # explizite Version
# bin/build-and-push.sh --load # baut + laedt nur (kein Push)
set -euo pipefail
@@ -16,7 +16,7 @@ fi
REGISTRY="${REGISTRY:-git.pkop.de}"
OWNER_LC=$(echo "${OWNER:-Vibecode}" | tr '[:upper:]' '[:lower:]')
REPO_LC=$(echo "${REPO:-watchlist}" | tr '[:upper:]' '[:lower:]')
LOCAL_TAG="watchstack:${VERSION}"
LOCAL_TAG="quivio:${VERSION}"
REMOTE_TAG="${REGISTRY}/${OWNER_LC}/${REPO_LC}:${VERSION}"
echo ">> Building ${LOCAL_TAG}"
@@ -35,4 +35,4 @@ docker push "${REMOTE_TAG}"
echo ">> Done."
echo " Pull with: docker pull ${REMOTE_TAG}"
echo " Run with: docker run -d --name watchstack -p 8000:8000 -v watchstack-data:/data ${REMOTE_TAG}"
echo " Run with: docker run -d --name quivio -p 8000:8000 -v quivio-data:/data ${REMOTE_TAG}"
+4 -13
View File
@@ -1,28 +1,19 @@
#!/usr/bin/env bash
# Baut das Docker-Image und legt es als versionierten Tar in dist/ ab.
# Verwendung:
# bin/build-image.sh # baut mit Version aus app/__init__.py
# bin/build-image.sh --load # baut + laedt direkt in lokales Docker
# VERSION=0.6.0 bin/build-image.sh # baut mit expliziter Version
# Baut das Quivio-Image und speichert es als Tar (Fallback, nicht mehr im Standard-Workflow).
# Normalerweise: bin/build-and-push.sh -> Image in Gitea-Registry.
set -euo pipefail
cd "$(dirname "$0")/.."
# Version aus app/__init__.py lesen, falls nicht via env ueberschrieben
if [ -z "${VERSION:-}" ]; then
VERSION=$(python3 bin/get-version.py)
fi
IMAGE="watchstack:${VERSION}"
TAR="dist/watchstack-${VERSION}.docker.tar"
IMAGE="quivio:${VERSION}"
TAR="dist/quivio-${VERSION}.docker.tar"
mkdir -p dist
echo ">> Building ${IMAGE}"
docker build -t "${IMAGE}" .
if [ "${1:-}" = "--load" ]; then
echo ">> Loaded into local Docker as ${IMAGE}"
exit 0
fi
echo ">> Saving to ${TAR}"
docker save -o "${TAR}" "${IMAGE}"
+2 -2
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env python3
"""Liest die Version aus app/__init__.py (single source of truth).
"""Liest die Version aus quivio/__init__.py (single source of truth).
Verwendung: VERSION=$(python3 bin/get-version.py)
"""
import re
import sys
from pathlib import Path
text = (Path(__file__).parent.parent / "app" / "__init__.py").read_text()
text = (Path(__file__).parent.parent / "quivio" / "__init__.py").read_text()
m = re.search(r'__version__\s*=\s*["\'](.+?)["\']', text)
if not m:
sys.exit("__version__ nicht gefunden")
+3 -4
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env bash
# Schreibt dist/manifest.json mit Build-Metadaten.
# Wird von bin/build-image.sh aufgerufen; kann auch solo laufen.
set -euo pipefail
cd "$(dirname "$0")/.."
@@ -14,13 +13,13 @@ BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
mkdir -p dist
cat > dist/manifest.json <<EOF
{
"name": "watchstack",
"name": "quivio",
"version": "${VERSION}",
"git_sha": "${GIT_SHA}",
"git_tag": "${GIT_TAG}",
"build_date": "${BUILD_DATE}",
"image": "watchstack:${VERSION}",
"tarball": "dist/watchstack-${VERSION}.docker.tar",
"image": "quivio:${VERSION}",
"tarball": "dist/quivio-${VERSION}.docker.tar",
"license": "Apache-2.0",
"source": "https://git.pkop.de/Vibecode/watchlist"
}
+1 -1
View File
@@ -1,5 +1,5 @@
# Lokale Daten
Hier landet die SQLite-DB `watchstack.db` (wird automatisch angelegt).
Hier landet die SQLite-DB `quivio.db` (wird automatisch angelegt).
Dieser Ordner ist in `.gitignore`.
+3 -3
View File
@@ -1,20 +1,20 @@
# dist/ — leeres Build-Ausgabeverzeichnis
Docker-Images werden **nicht** als Tar im Repo committed, sondern in die
Quivio-Images werden **nicht** als Tar im Repo committed, sondern in die
Gitea Container Registry gepusht (siehe *Packages*-Tab im Repo-UI).
## Verwendung der Registry-Images
```bash
docker pull git.pkop.de/vibecode/watchlist:0.5.1-beta
docker run -d --name watchstack -p 8000:8000 -v watchstack-data:/data \
docker run -d --name quivio -p 8000:8000 -v quivio-data:/data \
git.pkop.de/vibecode/watchlist:0.5.1-beta
```
## Build + Push lokal
```bash
bin/build-and-push.sh # baut + pusht mit Version aus app/__init__.py
bin/build-and-push.sh # baut + pusht mit Version aus quivio/__init__.py
VERSION=0.6.0 bin/build-and-push.sh # baut + pusht mit expliziter Version
```
+16 -16
View File
@@ -1,8 +1,8 @@
# Komponiert WatchStack.
# Komponiert Quivio.
#
# Standard (empfohlen, Beta):
# Image wird aus der Gitea Container Registry gezogen — kein lokaler
# Build noetig. Version liegt in app/__init__.py (single source of truth).
# Build noetig. Version liegt in quivio/__init__.py (single source of truth).
#
# docker compose up -d
# -> http://localhost:8000
@@ -12,24 +12,24 @@
# => baut aus dem Dockerfile statt aus der Registry
#
# Andere Version ziehen:
# WATCHSTACK_VERSION=0.6.0 docker compose pull && docker compose up -d
# QUIVIO_VERSION=0.6.0 docker compose pull && docker compose up -d
#
# Optional: Reverse-Proxy (caddy/traefik) davorschalten.
# Wird vom .env oder der Umgebung ueberschrieben, wenn vorhanden.
# Hinweis: Gitea-Pfad ist LOWERCASE (Vibecode/watchlist -> vibecode/watchlist),
# weil Docker-Repository-Namen kleingeschrieben sein muessen.
x-watchstack-version: &watchstack_version ${WATCHSTACK_VERSION:-0.5.1-beta}
x-gitea-image: &gitea_image git.pkop.de/vibecode/watchlist:${WATCHSTACK_VERSION:-0.5.1-beta}
x-quivio-version: &quivio_version ${QUIVIO_VERSION:-0.5.1-beta}
x-gitea-image: &gitea_image git.pkop.de/vibecode/watchlist:${QUIVIO_VERSION:-0.5.1-beta}
services:
watchstack:
quivio:
# Standard: Image aus der Gitea Container Registry.
image: *gitea_image
container_name: watchstack
container_name: quivio
restart: unless-stopped
ports:
- "${WATCHSTACK_PORT:-8000}:8000"
- "${QUIVIO_PORT:-8000}:8000"
environment:
WATCHSTACK_HOST: "0.0.0.0"
WATCHSTACK_PORT: "8000"
@@ -37,7 +37,7 @@ services:
WATCHSTACK_DATA_DIR: "/data"
# TZ: "Europe/Berlin"
volumes:
- watchstack-data:/data
- quivio-data:/data
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request,sys,os; r=urllib.request.urlopen('http://127.0.0.1:8000/api/health',timeout=3); sys.exit(0 if r.status==200 else 1)"]
interval: 30s
@@ -47,23 +47,23 @@ services:
# Lokaler Build (Development) — ueber opt-in Profile aktivierbar:
# docker compose --profile local up -d --build
watchstack-local:
quivio-local:
profiles: ["local"]
build:
context: .
dockerfile: Dockerfile
image: watchstack:local
container_name: watchstack-local
image: quivio:local
container_name: quivio-local
restart: unless-stopped
ports:
- "${WATCHSTACK_PORT:-8001}:8000" # anderer Port, damit Registry-Variante parallel laufen kann
- "${QUIVIO_PORT:-8001}:8000" # anderer Port, damit Registry-Variante parallel laufen kann
environment:
WATCHSTACK_HOST: "0.0.0.0"
WATCHSTACK_PORT: "8000"
WATCHSTACK_WORKERS: "2"
WATCHSTACK_DATA_DIR: "/data"
volumes:
- watchstack-data:/data
- quivio-data:/data
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request,sys,os; r=urllib.request.urlopen('http://127.0.0.1:8000/api/health',timeout=3); sys.exit(0 if r.status==200 else 1)"]
interval: 30s
@@ -72,5 +72,5 @@ services:
start_period: 10s
volumes:
watchstack-data:
name: watchstack-data
quivio-data:
name: quivio-data
+7
View File
@@ -0,0 +1,7 @@
"""Quivio Watchlist für Bücher, Serien & mehr.
Name: Quivio (Kofferwort aus Quire + Video).
"""
__version__ = "0.5.1-beta"
__all__ = ["__version__"]
+2 -2
View File
@@ -1,4 +1,4 @@
"""Datenbank-Operationen (CRUD) für WatchStack."""
"""Datenbank-Operationen (CRUD) für Quivio."""
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
@@ -7,7 +7,7 @@ from typing import Iterable, Optional, Sequence
from sqlalchemy import and_, func, or_, select
from sqlalchemy.orm import Session, selectinload
from app import models, schemas
from quivio import models, schemas
# ---------- Hilfsfunktionen --------------------------------------------------
+2 -2
View File
@@ -12,7 +12,7 @@ from sqlalchemy.orm import DeclarativeBase, sessionmaker
_BASE_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = Path(os.environ.get("WATCHSTACK_DATA_DIR", _BASE_DIR / "data"))
DATA_DIR.mkdir(parents=True, exist_ok=True)
DB_PATH = DATA_DIR / "watchstack.db"
DB_PATH = DATA_DIR / "quivio.db"
DATABASE_URL = f"sqlite:///{DB_PATH}"
@@ -41,6 +41,6 @@ def get_db():
def init_db() -> None:
"""Erstellt alle Tabellen, falls noch nicht vorhanden."""
from app import models # noqa: F401 registriert Modelle bei Base.metadata
from quivio import models # noqa: F401 registriert Modelle bei Base.metadata
Base.metadata.create_all(bind=engine)
+10 -10
View File
@@ -13,16 +13,16 @@ from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from sqlalchemy.orm import Session
from app import __version__, crud, schemas
from app.database import get_db, init_db
from app.external import lookup_book_by_isbn, lookup_book_by_title
from app.seed import seed_if_empty
from quivio import __version__, crud, schemas
from quivio.database import get_db, init_db
from quivio.external import lookup_book_by_isbn, lookup_book_by_title
from quivio.seed import seed_if_empty
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
log = logging.getLogger("watchstack")
log = logging.getLogger("quivio")
BASE_DIR = Path(__file__).resolve().parent
STATIC_DIR = BASE_DIR / "static"
@@ -37,16 +37,16 @@ async def lifespan(_: FastAPI):
init_db()
with next(get_db()) as db:
seed_if_empty(db)
log.info("WatchStack %s ready", __version__)
log.info("Quivio %s ready", __version__)
yield
app = FastAPI(
title="WatchStack",
description="Watchlist für Bücher, Serien & mehr.",
title="Quivio",
description="Watchlist für Bücher, Serien & mehr. Quire + Video — dein Lese- und Schau-Tracker.",
version=__version__,
lifespan=lifespan,
contact={"name": "WatchStack", "url": "https://git.pkop.de/Vibecode/watchlist"},
contact={"name": "Quivio", "url": "https://git.pkop.de/Vibecode/watchlist"},
license_info={"name": "Apache-2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0"},
)
@@ -72,7 +72,7 @@ def root() -> HTMLResponse:
@app.get("/api/health", tags=["meta"])
def health() -> dict[str, str]:
return {"status": "ok", "service": "watchstack", "version": __version__}
return {"status": "ok", "service": "quivio", "version": __version__}
# ---------- Lookups ----------------------------------------------------------
+2 -2
View File
@@ -1,4 +1,4 @@
"""SQLAlchemy-Modelle für WatchStack.
"""SQLAlchemy-Modelle für Quivio.
Zentrale Idee: ein polymorphes ``Media``-Objekt mit ``kind`` (book/series), das
optionale, mediumspezifische Felder als NULL-sparende Spalten mitführt. So
@@ -25,7 +25,7 @@ from sqlalchemy import (
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
from quivio.database import Base
def _utcnow() -> datetime:
+2 -2
View File
@@ -9,7 +9,7 @@ from pathlib import Path
from filelock import FileLock
from sqlalchemy.orm import Session
from app import crud, models, schemas
from quivio import crud, models, schemas
log = logging.getLogger(__name__)
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
# File-Lock gegen Race-Conditions bei mehreren Workern (gunicorn).
# Pro Datenbank-Pfad ein Lock, damit parallele Worker nicht doppelt seeden.
def _lock_path() -> Path:
from app.database import DB_PATH
from quivio.database import DB_PATH
return DB_PATH.with_suffix(DB_PATH.suffix + ".seed.lock")
DEMO_BOOKS = [
@@ -1,6 +1,6 @@
/* ========================================================================
WatchStack Theme
- Dark default (wie MAL's moderner Look)
Quivio Theme
- Dark default
- Eine Akzentfarbe (cyan-violett), warme Status-Farben
======================================================================== */
@@ -6,5 +6,5 @@
</linearGradient>
</defs>
<rect width="64" height="64" rx="14" fill="url(#g)"/>
<text x="32" y="44" font-family="Arial, sans-serif" font-size="38" font-weight="800" fill="white" text-anchor="middle">W</text>
<text x="32" y="44" font-family="Georgia, serif" font-size="38" font-weight="700" fill="white" text-anchor="middle">Q</text>
</svg>

Before

Width:  |  Height:  |  Size: 447 B

After

Width:  |  Height:  |  Size: 444 B

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WatchStack Watchlist für Bücher & Serien</title>
<title>Quivio Watchlist für Bücher & Serien</title>
<link rel="icon" type="image/svg+xml" href="/static/img/favicon.svg">
<link rel="stylesheet" href="/static/css/style.css">
</head>
@@ -13,9 +13,9 @@
<div class="hero-bg"></div>
<div class="hero-inner">
<div class="brand">
<div class="logo">W</div>
<div class="logo">Q</div>
<div class="brand-text">
<h1>WatchStack <span class="version-badge">beta</span></h1>
<h1>Quivio <span class="version-badge">beta</span></h1>
<p>Deine Watchlist für <strong>Bücher</strong>, <strong>Serien</strong> & mehr.</p>
</div>
</div>
@@ -223,8 +223,8 @@
</div>
<footer class="footer">
<span>WatchStack <span id="version"></span> · Apache 2.0</span>
<span>Made for readers &amp; binge-watchers</span>
<span>Quivio <span id="version"></span> · Apache 2.0</span>
<span>Quire + Video — made for readers &amp; binge-watchers</span>
</footer>
<!-- ===================== Toast ===================== -->
@@ -1,5 +1,5 @@
/* ========================================================================
WatchStack Client App
Quivio Client App
======================================================================== */
(() => {
'use strict';
+3 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# WatchStack-Schnellstart
# Quivio-Schnellstart
# Legt venv an (falls fehlt), installiert deps, startet uvicorn.
set -e
cd "$(dirname "$0")"
@@ -18,5 +18,5 @@ pip install -q -r requirements.txt
HOST="${HOST:-127.0.0.1}"
PORT="${PORT:-8000}"
echo "→ Starte WatchStack auf http://${HOST}:${PORT}"
exec uvicorn app.main:app --reload --host "${HOST}" --port "${PORT}"
echo "→ Starte Quivio auf http://${HOST}:${PORT}"
exec uvicorn quivio.main:app --reload --host "${HOST}" --port "${PORT}"