Am Gruppen-Code stand der Produktname. Innerhalb einer Gruppe hilft der aber nicht weiter: In der Gruppe "Zucker" heisst jeder Artikel irgendwie "Zucker", in "Mehl" irgendwie "…mehl". Unterscheiden laesst sich das nur ueber die Marke. Der Endpunkt liefert jetzt beides; angezeigt wird die Marke, faellt bei fehlender Marke auf den Namen zurueck und zeigt den vollen Namen im Tooltip. Nebenbei ist die Marke meist deutlich kuerzer als der Name. Abgeschnittene Tabelle: Die Spalte "verwalten" wurde gekappt. Ursache war nicht die Breite an sich, sondern dass Grid-Kinder standardmaessig nicht unter ihre Inhaltsbreite schrumpfen (min-width: auto). Dadurch lief die Tabelle aus ihrer Karte heraus und wurde beschnitten, statt dass das vorhandene overflow-x gegriffen haette. Mit min-width: 0 an den Grid-Kindern scrollt sie jetzt. Zusaetzlich hat die Tabelle eine Mindestbreite von 640px - lieber waagerecht scrollen als Spalten so weit quetschen, bis Text verschwindet. Umbruch statt Quetschen: Die feste Umbruchbreite von 820px passte nicht zur tatsaechlichen Lage - entscheidend ist, wie viel Platz die Spalten wirklich brauchen, nicht wie breit der Bildschirm ist. Jetzt auto-fit mit Mindestbreite je Spalte: Zwei Spalten, solange beide genug Platz haben, sonst automatisch untereinander. Seiten mit inhaltsreichem Seitenblock (EAN-Codes) verlangen mehr und stapeln frueher. Durchgerechnet: Bei 1920 voller Breite zwei Spalten zu je 668px, Tabelle passt. Bei halber Breite (960) eine Spalte zu 676px, Tabelle passt weiterhin. Erst bei sehr schmalen Fenstern (unter etwa 900px Gesamtbreite) scrollt die Tabelle waagerecht. In keinem Fall wird noch etwas abgeschnitten. Getestet: 58 pytest-Tests gruen, Web-Build laeuft durch. Gegen die laufende API geprueft, dass Marke und Name am Code mitkommen und die fehlende Marke sauber auf den Namen zurueckfaellt. Die Breiten sind rechnerisch geprueft, die Darstellung im Browser habe ich nicht selbst angesehen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🥫 Project-Good – Selfhostbare Lebensmittel-Lagerverwaltung
Ein selbst gehosteter Dienst zur Verwaltung deines Lebensmittelvorrats: Ein-/Auslagern per Barcode, MHD-/Ablaufverwaltung mit Chargen, Mindestbestände, automatische Einkaufsliste – mit Web-UI und (in Vorbereitung) nativer iOS-App.
Dies ist Schritt 1 (Fundament). Der komplette Fahrplan steht in docs/ROADMAP.md.
Features (Schritt 1)
- Barcode-Lookup über Open Food Facts mit lokalem Fallback (unbekannte Produkte selbst anlegen).
- Chargen mit MHD: Jedes Einlagern erzeugt eine Charge mit eigenem Mindesthaltbarkeitsdatum. Beim Auslagern wird automatisch die zuerst ablaufende Charge zuerst entnommen (FEFO – First Expired, First Out).
- Einheiten: Basiseinheit Stück / Gramm / Milliliter plus optionale Packungsgröße → Ein-/Auslagern in Packungen oder Teilmengen (z. B. 200 g).
- Mindestbestände pro Produkt → automatische Einkaufsliste.
- Ablaufwarnung für bald ablaufende Chargen (Frist konfigurierbar).
- Lagerorte (flach; Unterlagerorte folgen in Schritt 3).
- Mehrbenutzer mit Rollen:
- Admin – verwaltet Produkte, Lagerorte, Benutzer, Mindestbestände.
- Nutzer – nur ein-/auslagern und ansehen.
- Bewegungen werden protokolliert (wer hat wann was ein-/ausgelagert).
Architektur
| Teil | Technik |
|---|---|
| Backend | Python · FastAPI · SQLAlchemy |
| DB | PostgreSQL |
| Web-UI | React · Vite (via nginx ausgeliefert) |
| iOS | SwiftUI (Schritt 2) |
| Deploy | Docker Compose · install.sh |
backend/ FastAPI-App + Tests
web/ React/Vite SPA
deploy/ docker-compose.yml, install.sh, .env.example
docs/ Roadmap
Installation (selfhosted, Linux)
Voraussetzung: eine Linux-Maschine (Server, NAS, Raspberry Pi …). Docker wird bei Bedarf automatisch installiert.
git clone https://git.scarriffle.com/Scarriffle/project-good.git
cd project-good/deploy
chmod +x install.sh
./install.sh # interaktiv – fragt Port & Admin-Passwort
# oder vollautomatisch mit generiertem Admin-Passwort:
# ./install.sh --yes
Ist das Gitea-Repo privat, fragt
git clonenach Benutzername + Access-Token. Fallsgitfehlt:apt update && apt install -y git.
Nach dem Start:
- Web-UI:
http://<server-ip>:8080(Port konfigurierbar) - Anmeldung mit dem im Installer angezeigten Admin-Benutzer/Passwort.
Aktualisieren
cd project-good/deploy
./update.sh # holt den neuesten Stand aus Git und baut neu
./update.sh --prune # zusätzlich alte Images aufräumen
./update.sh --no-pull # nur neu bauen, ohne git pull
Das Skript ist von überall aufrufbar, nutzt die vorhandene deploy/.env und
prüft am Ende, ob das Backend wieder erreichbar ist.
Verwaltung:
cd deploy
docker compose logs -f # Logs ansehen
docker compose down # stoppen
docker compose up -d # starten
Die Konfiguration liegt in deploy/.env (Passwörter, Port, JWT-Secret). Für den
Produktivbetrieb bitte hinter einen HTTPS-Reverse-Proxy (z. B. Caddy/Traefik) stellen.
Entwicklung (ohne Docker)
Backend:
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# lokale SQLite-DB nutzen:
export DATABASE_URL="sqlite:///./project_good.db"
uvicorn app.main:app --reload
API-Doku dann unter http://localhost:8000/docs.
Web:
cd web
npm install
npm run dev # http://localhost:5173, proxyt /api → localhost:8000
Tests:
cd backend
pip install -r requirements.txt
pytest # prüft FEFO-Abbuchung und Einheiten-Umrechnung
Nächste Schritte
Native iOS-App (Schritt 2) und fortgeschrittene Features (Gruppen-Intelligenz, Unterlagerorte, Push-Benachrichtigungen …) – siehe docs/ROADMAP.md.