- v0.52.0Aktuell live
OCR-Parser: Lidl-Fix + Prefix-Loop
Kassenbon-Parser deutlich verbessert: Phantom-Items durch mehrfachen OCR-Rauschpräfix ("TSK X", "X A ...") werden eliminiert. Lidl-Store-Erkennung auch bei zerstörtem Logo. Debug-Panel jetzt direkt sichtbar über der Artikelliste.
Bugfix- cleanName Loop: Prefix-Bereinigung läuft jetzt in Schleife — entfernt "odd TSK X" → "X" → DROP statt Phantom-Item
- cleanName [A-Z]{1,4}: einzelne Großbuchstaben ("X", "A", "B") als OCR-Rausch-Prefix erkannt — "X A Bananen" → "Bananen"
- Lidl Store-Heuristik: "Preisvorteil" im OCR-Text → Store = "Lidl", auch wenn Logo zu "ASSLT" zerstört wurde
- SKIP_RE: \bpreisvorteil statt ^preisvorteil — Preisvorteil-Zeilen mit OCR-Prefix-Noise werden jetzt korrekt übersprungen
- OCR Debug-Panel über Artikelliste verschoben — sofort sichtbar ohne Scrollen
- rawText (normalisierte OCR-Zeile) unter jedem Artikel angezeigt — hilft beim Identifizieren von OCR-Fehlern
- v0.51.0
Kassenbon-OCR Debug-Panel
Temporäres Debug-Panel für die Kassenbon-OCR-Qualitätsprüfung: Zeilen-Trace mit ITEM/SKIP/BUFFER/DROP-Entscheidungen, Preprocessing-Info und Kopier-Button für einfaches Feedback.
Neu- OcrDebugPanel: neues zeilenweises Parsing-Trace-Panel auf der Scan-Seite
- Jede OCR-Zeile wird annotiert: ITEM (grün), SKIP (rot), BUFFER (amber), DROP (grau), TOTAL_UPDATE (blau), SPECIAL (violett)
- Header zeigt Preprocessing-Info: Bilddimension, PSM-Modus, Konfidenz, erkannter Store/Datum/Total
- Tab 'Zeilen-Trace': normalisierte Zeile, raw-Zeile (wenn abweichend), Preis bei ITEM-Zeilen
- Tab 'OCR-Rohtext': vollständiger OCR-Text scrollbar
- Kopieren-Button: vollständigen Debug-Report in die Zwischenablage für Feedback-Loop
- getSkipReason(): 40+ spezifische Muster für SKIP_RE-Erklärungen
- parseReceiptTextCore(): interner Parser mit optionaler OcrDebugLine[]-Trace-Sammlung
- parseReceiptTextDebug(): neue Funktion für Trace-Ausgabe ohne Änderung der öffentlichen API
- OcrDebugTrace: neue Typen in receipt-types.ts (temporär bis OCR-Freigabe)
- v0.50.0
Marketplace Detail + In-App-Chat
Detailseiten für Marketplace-Listings, SWAP-Tausch-Angebote, In-App-Chat mit SSE-Echtzeit, Nachrichten-Posteingang und Ungelesen-Badge in der Navigation.
Neu- Marketplace-Detailseite: Produktbild, Beschreibung, SWAP-Angebot, Kontakt-Button
- swapFor-Feld im Create-Form: Nutzer können Tauschwünsche angeben
- In-App-Chat: SSE-Echtzeit-Nachrichten zwischen Nutzern (Conversation + Message)
- Nachrichten-Posteingang /app/messages: alle Konversationen auf einen Blick
- Chat-View /app/messages/[id]: Gesprächsverlauf mit Echtzeit-Aktualisierung
- Neue Konversation starten via /app/messages/new?listingId=... mit Redirect
- Ungelesen-Badge in der Navigation: zeigt Anzahl ungelesener Nachrichten
Bugfix- OCR-Datumserkennung: 4-Dezimal-Normalisierung zerstörte Datum-Formate (DD.MM.YYYY) — Datum-Extraktion läuft jetzt auf Raw-Zeilen vor normalizeOcrLine
- Shopping-List SSE: connectSSE-Selbstreferenz via Ref aufgelöst (react-hooks/immutability)
- FeedbackButton: setState-in-Effect durch openDialog-Handler ersetzt
- NotificationSettings: Push-State-Erkennung in async-Funktion verschoben
- v0.49.5
OCR v0.49.5 — Total-Fallback + PFAND-EURO-Filter + PLZ-Filter
Drei Parser-Verbesserungen: (1) Total-Fallback: OCR-zerbrochene Summen-Zeilen (Sings. statt Summe) werden anhand Position+Preishoehe erkannt — total wird gesetzt und der falsche Artikel entfernt. (2) PFAND-EURO-Filter: Famila-PFAND-Zeilen mit EURO-Schluesselwort ('y FAM) 0,15 EURO 18364') werden gefiltert. (3) PLZ-Filter: Adresszeilen mit Preis+PLZ-Muster ('4,26 19904 UM') werden gefiltert. (4) normalizeOcrLine: 4-Dezimal-Fix auch fuer Punkt-Dezimaltrenner.
Bugfix- Total-Fallback: letzte 50% der OCR-Zeilen nach kurzem Text (<=12 Zeichen) + Preis >5 EUR durchsuchen — hoechster Treffer = Summe; aus lineItems entfernt wenn dort gelandet
- SKIP_RE: \d[,.]\d+\s+euro\b — Famila-PFAND-Zeilen ('0,15 EURO') gefiltert
- SKIP_RE: \b\d{1,4}[,.]\d{2}\s+\d{5}\b — Adress/PLZ-Zeilen ('4,26 19904') gefiltert
- normalizeOcrLine: 4-Dezimal-DOT-Fix ('4.2680' -> '4,26') erweiternd zum bestehenden Komma-Fix
- v0.49.4
OCR v0.49.4 — PSM 6 wiederhergestellt + Fallback-Kette PSM4->PSM3
Regression-Fix: PSM 4 (SINGLE_COLUMN) hat die Artikel-Erkennung von 21 auf 2 Artikel reduziert. PSM 6 (SINGLE_BLOCK) ist der stabilere Primaer-Modus fuer reale Kassenbons. Neu: Dreistufige Fallback-Kette PSM 6 -> PSM 4 -> PSM 3 (AUTO) mit Schwelle 5 Artikel statt 2.
Bugfix- PSM 6 (SINGLE_BLOCK) als primaerer OCR-Modus wiederhergestellt — PSM 4 reduzierte Famila-Bon von 21 auf 2 Artikel
- Auto-Rotations-Tests (90deg/270deg) ebenfalls auf PSM 6 umgestellt
- Fallback-Schwelle von < 2 auf < 5 Artikel angehoben
- Dreistufige Fallback-Kette: PSM 6 -> PSM 4 -> PSM 3 (AUTO) — immer der Modus mit den meisten Artikeln gewinnt
- v0.49.3
OCR v0.49.3 — PSM 4 + DPG-Filter + pendingName-Qualitaet
Vier weitere Verbesserungen: (1) OCR-Modus von PSM 6 (Einzelblock) auf PSM 4 (Einzelspalte) umgestellt — Kassenbons sind Einzelspalten, PSM 4 erkennt die vertikale Zeilenstruktur besser. (2) DPG-SYSTEM (Pfand-Rueckgabe) wird jetzt als SKIP_RE-Eintrag gefiltert. (3) Preisreduzierung-Zeilen werden gefiltert. (4) pendingName-Qualitaetsfilter: Zwischengespeicherte Produktnamen werden nur verwendet wenn mindestens 40% der Woerter 3+ Buchstaben haben — verhindert OCR-Muelll als Produktname.
Bugfix- PSM 4 (SINGLE_COLUMN) statt PSM 6 (SINGLE_BLOCK) als primaerer OCR-Modus — besser fuer Kassenbons (Einzelspalten-Dokumente)
- PSM 4 auch in Auto-Rotations-Tests (90deg/270deg) einheitlich verwendet
- SKIP_RE: dpg.?system / opg.?system — DPG-Pfand-System-Zeilen werden jetzt gefiltert (nicht mehr als Produkt 'DPG-SYSTEM 3,99' gespeichert)
- SKIP_RE: preisreduzier* — Preisreduzierung-Zeilen gefiltert
- pendingName-Qualitaetsfilter: nur verwenden wenn mindestens 40% der Woerter 3+ echte Buchstaben haben — verhindert OCR-Muell-Zeilen als Produktname
- cleanName: schliessende Klammer ')' zu Anfang/Ende-Bereinigung hinzugefuegt
- v0.49.2
OCR v0.49.2 — CLAHE-Preprocessing + Unicode-Quotes + Summen-Erkennung
Vier weitere Verbesserungen nach Analyse des Famila-Bon-JSON: (1) Preprocessing: CLAHE verbessert lokalen Kontrast bei Plastikfolien-Reflexionen. Aggressivere Schaerfung nach CLAHE. (2) cleanName: Unicode-Anfuehrungszeichen (geschwungene Quotes, U+201A-201F, Guillemets) werden aus Produktnamen entfernt — Tesseract OCR gibt statt ASCII-Komma haeufig U+201A aus. (3) 4-stellige Dezimalstellen (5,6768 → 5,67) werden normalisiert. (4) OCR-verzerrte Gesamtbetragszeilen ('Soe 174.32' statt 'Summe 17,43') werden als Gesamtbetrag erkannt.
Bugfix- Preprocessing: CLAHE (Kachel 32x32, maxSlope 3) nach normalize() — verbessert lokalen Kontrast bei Plastikfolien-Beleuchtungsproblemen
- Preprocessing: sharpen aggressiver (sigma 1.5→1.2, m1 1.5→2.0, m2 3→5) — mehr Textschaerfe nach verbessertem CLAHE-Kontrast
- cleanName: Unicode-Anfuehrungszeichen (U+201A-201F, Guillemets) aus Anfang/Ende entfernt — Tesseract liest Komma-aehnliche Zeichen oft als U+201A (Single Low-9 Quotation Mark)
- normalizeOcrLine: 4-Dezimalstellen-Artefakt behoben: '5,6768' → '5,67' (bisher nur 3-stellige Variante behandelt)
- OCR-Prefix-Regex: max. Länge von 5 auf 4 Zeichen reduziert — verhindert irrtümliches Entfernen legitimer 5-Buchstaben-Markennamen (HARRY, AVITA, REGIO etc.)
- Parser: price > 150 bei priceMatch.index ≤ 5 → Gesamtbetrag statt Produkt — fängt OCR-verzerrte Summen-Zeilen ('Soe 174.32 €') korrekt ab
- v0.49.1
OCR v0.49.1 — Parser-Qualität: FAND, (2x-Zeilen, Gesamtbetrag, Namen
Sechs gezielte Parser-Fixes nach Analyse des Famila-Bons: (1) PFAND-Zeilen werden auch als 'FAND' (OCR-Drop des P) erkannt und gefiltert. (2) Famila-Format: Mengen-Annotation-Zeilen '(2 x 0,59 €/05)' werden übersprungen, der Produktname aus der Vorzeile bleibt erhalten. (3) Gesamtbetrag-Erkennung robuster: 'Summe', 'Gesamt' und 'Betrag' werden auch mit OCR-Prefix-Noise erkannt (^ -Anker entfernt). (4) cleanName: '(' zählt jetzt als führendes Rauschzeichen. (5) Zusatz-Pass in cleanName entfernt 1–3 Kleinbuchstaben vor Großbuchstaben ('cn Pip' → 'Pip'). (6) 1–2-Zeichen ALL-CAPS-Namen ('LA', 'HL') werden als OCR-Artefakte gefiltert.
Bugfix- SKIP_RE \bp?fand\b: P optional — 'FAND 0,16 EUR' (OCR-Drop) wird jetzt korrekt als Pfand-Zeile erkannt und gefiltert
- SKIP_RE \bsumme\b / \bgesamt\b / \bbetrag\b: ^ -Anker entfernt — Gesamtbetrag-Zeilen mit OCR-Prefix-Noise ('AB Summe 14,93') werden jetzt erkannt
- Total-Extraktion: 'betrag' und 'endbetrag' ergänzt (summe|gesamt|zu zahlen|betrag|endbetrag) — 'Betrag EUR 14,93' wird als Gesamtbetrag übernommen
- Famila-Format: Mengen-Annotations-Zeilen '(2 x 0,59 €/05)' werden inline erkannt (nameRaw ~ /^\(?\d+[xX×]$/), übersprungen ohne pendingName zu löschen — Produktname aus Vorzeile wird für die Folge-Preiszeile erhalten
- cleanName: '(' zu führenden Sonderzeichen hinzugefügt — '(2 x' → '2 x' als weiterer Schutz
- cleanName: Zusatz-Pass ^[a-z]{1–3}\s+(?=[A-Z]) — greift wenn Haupt-OCR-Prefix-Regex nicht matched ('cn Pip' → 'Pip')
- Qualitätsfilter: Namen aus 1–2 reinen Großbuchstaben ('LA', 'HL', 'AB') werden nicht als Produkt gespeichert
- v0.49.0
OCR v0.49.0 — Auto-Orientierung + kritischer VPS-Bugfix
Zwei wichtige Fixes: (1) Kassenbon-Fotos die quer aufgenommen wurden (Bon auf Tisch liegend, Gerät hochkant gehalten) führten zu 0-3 garbled Artikeln statt allen Positionen — der Adapter erkennt jetzt Querformat-Preprocessing-Output und testet automatisch 90°- und 270°-Rotationen, wählt die Richtung mit mehr Artikeln (Early-Exit bei ≥ 5 Artikeln). (2) Kritischer Produktionsfehler behoben: receipt-parsing.service.ts auf dem VPS war vom 26. Mai ohne case "tesseract" — der Provider-Switch fiel auf default (Mock) zurück, egal welchen Wert RECEIPT_PARSER_PROVIDER hatte. Tesseract OCR war de facto nie aktiv. Außerdem: parseAndCreateReceiptAction hat jetzt try-catch um parseReceipt(), sodass OCR-Fehler als lesbare Fehlermeldung im UI erscheinen statt den Spinner einzufrieren.
Bugfix- KRITISCH: receipt-parsing.service.ts auf VPS war vom 26.05. ohne case "tesseract" → Mock-Adapter lief immer, REWE-Beispieldaten für alle Uploads
- parseAndCreateReceiptAction: try-catch um parseReceipt() — OCR-Fehler erscheinen als UI-Fehlermeldung statt eingefrorener Spinner
Neu- Auto-Orientierung: Querformat-Preprocessing-Output (Breite > 1,2× Höhe) → 90°- und 270°-Rotationen werden automatisch getestet, beste Richtung gewinnt
- Early-Exit: 90°-Rotation mit ≥ 5 Artikeln stoppt weitere Tests (RAM- und Zeitersparnis auf VPS)
- Behebt: Famila-Bon auf dunklem Tisch quer fotografiert → war 3 garbled Items, jetzt alle Artikel erkannt
- v0.48.10
OCR v0.48.10 — EUR/kg-Filter + OCR-Prefix-Noise in Produktnamen
Zwei weitere Parser-Verbesserungen: (1) Gewichts-Rate-Zeilen ('0,654 kg x 2,39 EUR/kg') werden jetzt per SKIP_RE herausgefiltert, bevor PRICE_RE fälschlich '2,39' als Produktpreis matcht — funktioniert auch mit OCR-Prefix-Noise am Zeilenanfang; (2) cleanName() erkennt jetzt breitere OCR-Rausch-Prefixe vor Produktnamen: ALL-CAPS (BERR, SE), Ziffernblöcke (2505, 83), Kleinbuchstaben-Müll (za, Sn) und Sonderzeichen-Sequenzen.
Bugfix- SKIP_RE: '(?:EUR|€)\\s*/\\s*(?:kg|g|ml|l|cl)\\b' — Gewichts-Rate-Zeilen werden gefiltert, auch mit OCR-Prefix-Noise ('an Bi 0,654 kg x 2,39 EUR/kg N')
- cleanName: führende OCR-Rausch-Tokens breiter abgedeckt — ALL-CAPS (BERR, SE, SEM), Ziffernblöcke (2505, 83)), Kleinbuchstaben-Müll (za, Sn), Sonderzeichen-Prefixe werden vor echtem Großbuchstaben gestripped
- cleanName: trailing Garbage-Zeichen am Namensende entfernt
- 9 neue Regressionstests (3 × EUR/kg-Filter, 6 × Prefix-Noise)
- v0.48.9
OCR v0.48.9 — Blacklist-Trailing-Noise + Pfand-Prefix-Filter
Zwei weitere Robustheitsverbesserungen nach Analyse des dritten Lidl-OCR-Outputs: (1) PRICE_RE-Trailing-Gruppe wechselt von ASCII-Whitelist auf Komma-Blacklist ([^,\n\r]) — erfasst jetzt beliebige Unicode-Rauschzeichen (©, », \, €, }, {, [09 }) aus dem Bonhintergrund ohne manuelle Enumeration; (2) SKIP_RE ^pfand-Anker entfernt — Pfand-Zeilen mit 2-3-char OCR-Prefix-Noise ('5 Pfand', 'Aa Pfand') werden korrekt gefiltert.
Bugfix- PRICE_RE: Trailing-Noise-Klasse von ASCII-Whitelist [A-Za-z\d...] auf [^,\n\r] (Blacklist) umgestellt; {0,2} → {0,3} Reps — ©, », \\, €, }, { und beliebige andere Unicode-Artefakte werden jetzt korrekt als Noise ignoriert
- SKIP_RE: ^pfand\\b-Anker entfernt → \\bpfand\\b matcht auch bei 2-3-char OCR-Prefix-Noise am Zeilenanfang ('5 Pfand ...', 'Aa Pfand ...')
- 6 neue Regressionstests (Unicode-Trailing + Pfand-Prefix-Noise)
- v0.48.8
OCR v0.48.8 — Lidl-Preisnoise (Trailing-Digits + %-Verwechslung)
Drei weitere Artefakt-Muster aus realen Lidl-Bon-Fotos beseitigt: (1) PRICE_RE akzeptiert jetzt bis zu zwei Trailing-Noise-Token nach dem Preis (z.B. '1,565 3' → 1,56), (2) normalizeOcrLine normalisiert 3-Dezimalstellen mit Komma-Separator — angehängte Digit-Artefakte ('1,565'→'1,56', '0,508'→'0,50'), (3) Tesseract liest '%' statt '6' bei kleinen Schriften ('5,9% A'→'5,96 A').
Bugfix- PRICE_RE: trailing-Noise-Gruppe von einmaliger Whitelist auf bis zu 2 beliebige \S{1,4}-Token erweitert — '[Re', '@&', 'ghd' und multi-Token '5 3' werden korrekt ignoriert
- normalizeOcrLine: neue Regel für Komma-Separator + 3 Dezimalstellen — letztes (OCR-angehängtes) Digit entfernen: '1,565'→'1,56', '0,508'→'0,50', '5,988'→'5,98', '1,094'→'1,09'
- normalizeOcrLine: bestehende Punkt-3-Dezimal-Regel auf '.' -Separator beschränkt (war '[.,]') um Komma-Preise nicht falsch umzuschreiben
- normalizeOcrLine: Prozentzeichen-zu-6-Ersetzung — Tesseract liest Druck-'6' als '%' bei kleiner Schrift: '5,9% A'→'5,96 A'
- v0.48.7
OCR v0.48.7 — Lidl-Ziffernerkennung + adaptives Thresholding
Drei Parser-Bugs behoben, die nach der Bon-Erkennung aus v0.48.6 noch sichtbar waren: (1) PRICE_RE schlug fehl wenn MwSt-Kürzel 'B' als '3', '8' oder ')' gelesen wurde, (2) 3-Dezimalstellen-Artefakt '0.499' blockierte Preis-Matching, (3) 'Kreditkarte'-Zeilen wurden nicht gefiltert. Dazu Preprocessing-Verbesserung: hartes .threshold(128) durch adaptives Tesseract-Otsu-Binarisierung ersetzt (nur noch .sharpen() vorbereitet die Kanten), Mindestbreite 1 200→1 600 px.
Bugfix- PRICE_RE: Trailing-Noise-Gruppe erlaubt Ziffern + Satzzeichen — OCR liest 'B' als '3', '8', ')'
- normalizeOcrLine: 3-Dezimalstellen-Artefakt '0.499' → '0,99' (strip erstes Dezimaldigit)
- SKIP_RE: kreditkarte, debitkarte, girocard als Zahlungszeilen-Filter ergänzt
- Preprocessing: .threshold(128) entfernt → Tesseract nutzt internen adaptiven Otsu-Algorithmus
- Preprocessing: .sharpen({ sigma:1.5, m1:1.5, m2:3 }) für schärfere Textkanten
- Preprocessing: Mindestbreite 1200→1600 px für bessere Ziffernerkennung bei schmalen Bons
- Tests: 16 Parser-Regressionstests (Jawoll + Lidl OCR-Artefakte, PRICE_RE-Fälle)
- v0.48.6
OCR: Bon-Erkennung im Foto + Jawoll-Format
Das Preprocessing lokalisiert jetzt den hellen Bon im Foto (Otsu-Schwellwert + Projektion) und schneidet den Hintergrund weg, bevor Tesseract liest — Fotos auf Stoff, Teppich oder Holz erzeugten bisher massives Pseudotext-Rauschen, in dem die echten Bon-Zeilen untergingen. Zusätzlich Median-Despeckle und Jawoll/Norma-Parser-Support (Artikelnummer-Zeilen, Mengenzeilen wie '4 * 3,33').
Bugfix- Preprocessing: detectPaperRegion() — Bon wird per Otsu-Schwellwert aus dem Foto ausgeschnitten, strukturierter Hintergrund erzeugt kein OCR-Rauschen mehr
- Preprocessing: 3×3-Median-Filter vor der Binarisierung entfernt Restpixel-Rauschen
- Parser: Jawoll/Norma-Mengenzeilen '4 * 3,33 13,32 2' — Menge × EP auf eigener Zeile, Produktname aus der Vorzeile
- SKIP_RE: 'Artikel <Nr>'-Zeilen, 'Betrag', 'Bezahlung', 'Visa', 'Kundenbeleg', 'Kartennr', 'kontaktlos', Öffnungszeiten ('9.00-19.00Uhr')
- KNOWN_STORES: Jawoll
- v0.48.5
OCR-Parser: Lidl kg-Varianten + Rabattzeilen-Filter
Robustere Gewichtserkennung: OCR liest 'kg' häufig als 'kn', 'ky' oder 'ko' — alle Varianten werden jetzt als Gewichtszeilen erkannt. PendingName-Buffer prüft jetzt SKIP_RE vor dem Puffern, verhindert so dass Preisvorteil-Fragmente ('svorteil', 'svorte') als Produktnamen gepuffert werden. 'gespart'-Zeilen werden gefiltert.
Bugfix- WEIGHT_INLINE_RE: 'kn', 'ky', 'ko', 'k[0-9]' als OCR-Varianten von 'kg' erkannt
- pendingName: SKIP_RE-Check vor Pufferung — verhindert Rausch-Tokens als Produktnamen
- pendingName: mindestens 3 aufeinanderfolgende Buchstaben erforderlich
- SKIP_RE: 'svorteil', 'svorte' (OCR-Fragmente), 'gespart' (Rabatt-Zusammenfassung)
- v0.48.4
OCR-Parser: Lidl-Support (EP×Qty, 2-Zeilen, Rabattzeilen)
Drei Lidl-spezifische Parser-Verbesserungen: Inline EP×Menge-Format ('0,99 × 2'), 2-Zeilen-Produktformat (Name ohne Preis + Gewichtszeile) und Filterung von Rabatt-/Aktionszeilen. Fuzzy Lidl-Store-Erkennung für OCR-Varianten wie 'L1DL'.
Bugfix- LIDL_QTY_RE: 'Espresso Macchiato 0,99 × 2 1,98' → qty=2, EP=0,99 korrekt erkannt
- pendingName-Buffer: Lidl-Produktname auf Zeile 1 (ohne Preis) wird für Gewichtszeile auf Zeile 2 gepuffert
- SKIP_RE: 'Preisvorteil' und 'Aktion'-Rabattzeilen werden gefiltert
- KNOWN_STORES: Fuzzy-Pattern /l[i1][d][l]/ erkennt OCR-Varianten wie 'L1DL', 'L!DL'
- v0.48.3
OCR-Parser: EP-Mengenkorrektur + Steuer-Tabellen-Filter
Menge wird jetzt aus EP und Gesamt-Preis zurückgerechnet statt aus OCR-Ziffernerkennung (z.B. OCR liest 2 als 7 → 6,00 / 3,00 = 2 korrekt). Steuer-Aufschlüsselungszeilen mit 3 Preisspalten werden zuverlässig gefiltert.
Bugfix- EP-basierte Mengenkorrektur: qty = round(Gesamt / EP) — robuster als OCR-Ziffernerkennung
- SKIP_RE: 3-Preise-Muster fängt OCR-verzerrte Steuer-Tabellen-Zeilen ab
- v0.48.1
OCR-Fix: EXIF-Rotation + Binarisierung
Kritischer Fix: Phone-Kamera-Fotos werden von sharp ohne .rotate() im Querformat verarbeitet — Tesseract bekommt 90°-gedrehten Text und produziert kompletten Müll. Fix: .rotate() als erste Operation im Preprocessing-Pipeline. Zusätzlich: threshold(128) statt aggressivem Sharpen für sauberere Binarisierung.
Bugfix- KRITISCH: .rotate() in sharp-Pipeline — EXIF-Orientation von Phone-Fotos wird jetzt korrekt angewandt
- threshold(128) ersetzt sharpen(m1:2.5) — Binarisierung statt Ringing-Artefakte
- Beide Änderungen zusammen: OCR auf echten Kassenbons sollte jetzt lesbare Ergebnisse liefern
- v0.48.0
OCR-Fix: jsDelivr-Tessdata (.gz) + Preflight-Logging
Kritischer Fix: deploy.sh lädt jetzt deu.traineddata.gz + eng.traineddata.gz von jsDelivr (cdn.jsdelivr.net/npm/@tesseract.js-data/…/4.0.0_best_int) — exakt dieselbe Quelle, die Tesseract.js v7 nativ nutzt. Adapter: gzip: true statt gzip: false. Preflight-Logging zeigt beim OCR-Aufruf ob die Dateien im Container vorhanden sind (docker logs).
Bugfix- KRITISCH: Tessdata von jsDelivr CDN (.gz) statt GitHub raw — garantiert kompatibles Format
- Adapter: gzip: true (passend zu .gz-Dateien) statt gzip: false
- Preflight-Check: loggt Dateigröße von deu/eng.traineddata.gz vor jedem OCR-Aufruf
- errorHandler in createWorker fängt stille Init-Fehler ab und loggt sie
- deploy.sh: löscht alte unkomprimierte Tessdata-Dateien vor dem Docker-Build
- v0.47.0
Kassenbon-OCR v3 — Verbesserte Texterkennung
Der Tesseract.js OCR-Adapter wurde grundlegend überarbeitet. Kritischste Änderung: PSM 6 (SINGLE_BLOCK) statt PSM 4 (SINGLE_COLUMN) — PSM 4 hat die zwei Spalten des Kassenbons (Produktname + Preis) fälschlicherweise getrennt und lieferte 0 Artikel. Zusätzlich: OCR-Artefakt-Normalisierung (Leerzeichen innerhalb Preisen wie '1 ,29'), robustere SKIP_RE (‹netto›/‹bonus› nicht mehr global geblockt), Regex-basierte Supermarkt-Erkennung, automatischer PSM-3-Fallback. Der Roh-OCR-Text wird jetzt im UI als aufklappbares Debug-Panel angezeigt.
Bugfix- KRITISCH: PSM 4 → PSM 6 — PSM 4 trennte Name-Spalte/Preis-Spalte → 0 Artikel erkannt
- OCR-Zeilennormalisierung: '1 ,29' → '1,29', 'l,29' → '1,29' (häufige Tesseract-Artefakte)
- SKIP_RE überarbeitet: 'netto', 'bonus', 'total' nicht mehr global geblockt
- Automatischer Fallback auf PSM 3 (AUTO) wenn PSM 6 < 2 Artikel liefert
- Store-Erkennung: reguläre Ausdrücke statt String-Includes — trifft OCR-Variationen besser
- Erweiterte Supermarkt-Liste: 50+ Ketten inkl. Vollcorner, K+K, Hagebau, DM-Drogerie
- Preprocessing: Mindestskalierung auf 1 200 px (auch Hochskalierung kleiner Bilder)
- rawOcrText in ParseJob — für Diagnose im Debug-Panel der UI
Neu- OCR-Debug-Panel im Kassenbon-Review: zeigt Roh-Text wenn 0 Artikel erkannt
- OCR-Ergebnis wird via AppLog in DB geschrieben (Admin → Logs → System-Events)
- Gewichtete Artikel (0,350 kg × 17,99/kg) werden korrekt herausgefiltert
- v0.46.0
Redis-Caching für häufige DB-Queries
Fünf zuvor ungecachte Hot-Paths wurden mit Redis-Caching ausgestattet: Health-Inventory-Query (300s), Community- und User-Rezeptlisten (120–300s), Produkt-Barcode-Lookups (1h) und Admin-KPI-Dashboard (60s). Cache-Invalidierungen greifen präzise bei Mutations — Rezepte beim Erstellen/Bearbeiten/Löschen/Sperren, Inventory-Items bereits seit Phase 31. Der Admin-Dashboard zeigt jetzt den Redis-Verbindungsstatus live an.
Neu- Health-Service: getInventoryForHealth() jetzt Redis-cached (300s TTL, invalidiert bei Inventory-Änderungen)
- Rezept-Listen: getCommunityRecipes() (300s) und getUserRecipes() (120s) Redis-cached
- Rezept-Mutations invalidieren präzise user- und community-Cache (create/update/delete/photo/block/unblock)
- Produkt-Barcode-Lookup: getProductByBarcode() mit 1h TTL — schnellere Scan-Antwortzeiten
- Admin-KPI: getPlatformStats() mit 60s TTL — 7 COUNT-Queries pro Seitenladen entfallen
- Admin-Dashboard zeigt Redis-Verbindungsstatus und TTL-Übersicht als Status-Strip
- Neues TTL-Profil und CacheKey-Einträge: USER_RECIPES, COMMUNITY_RECIPES, PRODUCT, ADMIN_KPI
- pingRedis() Hilfsfunktion für Status-Checks
- v0.45.0
Rezept-Kochmodus, Admin-Rezeptverwaltung & System-Logs
Nutzer können Rezepte jetzt im interaktiven Kochmodus zubereiten: Der Bildschirm bleibt per Wake Lock API dauerhaft an, Schritte können einzeln abgehakt werden und der Kochvorgang wird nach Abschluss in der Datenbank gespeichert. Administratoren verwalten alle Nutzerrezepte über eine neue filterbare Listenansicht und Detailseite mit Sperr- und Löschfunktion. Das Audit-Log wurde um Rezept-Aktionen erweitert, und die Admin-Log-Seite zeigt jetzt zusätzlich alle System-Events (AppLog) in einem separaten Tab.
Neu- Kochmodus für Nutzerrezepte: Wake Lock API hält Bildschirm an, Auto-Scroll zur Zubereitung
- Einzelne Zubereitungsschritte abhakbar (ausgegraut/durchgestrichen wenn erledigt)
- "Fertig mit Kochen"-Button speichert Kochereignis in der DB (RecipeCook-Tabelle)
- Community-Rezepte werden nach Kochhäufigkeit (cookCount) sortiert
- Admin-Rezeptverwaltung: filterbare Liste mit Status-Tabs (Alle/Öffentlich/Gesperrt/Privat)
- Admin-Rezeptdetail: Sperren (mit Sperrgrund), Entsperren und Löschen
- Nutzer sehen gesperrte eigene Rezepte mit Admin-Hinweisbanner
- Admin-Logs: Neuer Tab "System-Events" zeigt AppLog-Tabelle mit Level/Quelle-Filter
- Audit-Log um Rezept-Aktionen erweitert (recipe.block, recipe.unblock, recipe.delete)
Infrastruktur- RecipeCook- und AppLog-Tabellenmodelle in Prisma-Schema, Prisma-Client regeneriert
- blockedByAdmin, blockedAt, blockedReason, cookCount-Felder auf UserRecipe
- v0.44.0
Kassenbon-OCR — deutlich verbesserte Erkennungsqualität
Tesseract.js OCR für Kassenbons wurde grundlegend überarbeitet. Smartphone-Fotos werden jetzt vor der Texterkennung automatisch aufbereitet (Graustufen, Kontrast-Normalisierung, Schärfen via sharp). Die OCR-Engine wurde auf LSTM-Only umgestellt und der Seitenanalyse-Modus auf Einspaltig — beides deutlich besser für schmale Kassenbons mit zwei Spalten (Produktname / Preis). Der Text-Parser wurde neu geschrieben: flexiblere Preis-Erkennung, zuverlässige Supermarkt-Erkennung (30+ bekannte Ketten) und ein verbessertes Konfidenz-Scoring.
Neu- Bild-Vorverarbeitung via sharp: Resize auf max. 1200 px, Graustufen, Kontrast-Normalisierung, Schärfen — verbessert OCR-Qualität bei Handy-Fotos um 30–50 %
- OCR-Engine auf OEM.LSTM_ONLY umgestellt (neuronales Netz statt Legacy-Engine)
- Seitenanalyse-Modus PSM.SINGLE_COLUMN statt SINGLE_BLOCK — korrekte Behandlung der Kassenbonspalten
- 30+ bekannte Supermarkt- und Drogeriemarkt-Namen für zuverlässige Filialerkennung (REWE, Edeka, Aldi, Lidl, Kaufland, DM, Rossmann, Müller, Netto, Penny, Tegut, …)
- Flexiblere Preis-Regex: erkennt jetzt auch ‹1,19A› ohne Leerzeichen vor dem Steuer-Code
- Verbessertes Konfidenz-Scoring: berücksichtigt Buchstaben-Anteil, Namenslänge und Preis-Position in der rechten Zeilenhälfte
- Graceful Fallback: wenn sharp-Binaries nicht verfügbar (lokale Dev-Umgebung), wird das Bild unverarbeitet an Tesseract übergeben
Infrastruktur- sharp als Produktions-Dependency in package.json aufgenommen (^0.34.5)
- Dockerfile: COPY node_modules/sharp ergänzt — native Binaries werden sonst vom Next.js-Standalone-File-Tracing nicht erfasst
- v0.43.0
Rezept-Wizard — Zutaten-Schritt komplett überarbeitet
Schritt 2 beim Erstellen oder Bearbeiten eines Rezepts wurde von Grund auf neu gebaut. Statt drei simplen Textfeldern gibt es jetzt einen vollständig kontextbewussten Zutatereditor: Der Name kommt zuerst, ein Autosuggest schlägt über 150 bekannte Zutaten vor, die Einheit wechselt automatisch je nach Zutat (z.B. 'Milch → l', 'Knoblauch → Zehe', 'Ei → Stück'), und das Einheitenfeld ist ein Select-Feld mit allen gängigen deutschen Kocheinheiten — Tippfehler werden damit verhindert.
Neu- Zutatename kommt jetzt zuerst — intuitiver UX-Fluss (Name → Menge → Einheit statt Menge → Einheit → Name)
- Autosuggest mit 150+ deutschen Zutaten — filtert ab dem 1. Zeichen, sortiert Prefix-Matches zuerst, zeigt Default-Einheit als Badge
- Einheit als Select-Feld mit 23 gängigen deutschen Maßeinheiten (g, kg, ml, l, EL, TL, Stück, Bund, Zehe, Dose, Packung, Prise, …)
- Auto-Einheit: beim Auswählen einer Zutat aus dem Autosuggest wird die Einheit automatisch gesetzt (Milch → l, Ei → Stück, Petersilie → Bund, Olivenöl → EL, …)
- Jede Zutat ist jetzt eine Karte mit klarer visueller Trennung und Beschriftungen — kein unstrukturiertes Inputfeld mehr
- Bestehende Rezepte mit angepassten Einheiten (z.B. aus dem Fork-Flow) werden korrekt angezeigt — auch wenn die Einheit nicht in der Standardliste ist
- v0.42.0
Google OAuth fix, Admin-Logs, Dark Mode & UI-Korrekturen
Google-OAuth-Anmeldung funktioniert nun zuverlässig (Root Cause: Sentry/Next.js 15-Kompatibilitätsbug der bei jedem Request einen uncaughtException-Fehler warf und dabei die OAuth-Callback-Pipeline unterbrach). Neues Admin-Audit-Log mit Filterung nach Aktion, Admin-E-Mail und Datumsbereich. Dark Mode überarbeitet: Brand-Farbtokens werden jetzt korrekt invertiert, Text ist auf dunklem Hintergrund gut lesbar. Permanente Dark-Mode-Umschalter im Sidebar-Footer und im mobilen Header. Feedback-Button nach links verschoben — kein Overlap mehr mit dem FAB auf der Vorrats-Seite. Facebook-Login als «Demnächst» markiert.
Bugfix- Google OAuth: Sentry-Logger-Bug (TypeError: logger is not a function) in instrumentation.ts unterdrückt — OAuth-Callbacks funktionierten zuvor nicht
- lib/auth/auth.ts: Toten Code-Branch entfernt (else if (!dbUser) war unerreichbar); explizites console.error bei OAuth-Fehlern für besseres Debugging
- Dark Mode: Brand-CSS-Tokens (#brand-50 bis #brand-900) in .dark korrekt invertiert — Text-brand-900 von #14532d (unsichtbar) auf #f0fdf4 (lesbar) korrigiert
- Feedback-Button: von rechts nach links verschoben (bottom-20 right-4 → left-4) — kein Overlap mehr mit Inventory-FAB
Neu- Admin-Logs (/admin/logs): Vollständiger Audit-Trail mit Filter nach Aktion, Admin-E-Mail und Datumsbereich — paginierte Tabelle mit farbigen Action-Badges
- Dark-Mode-Toggle: Permanenter Sun/Moon-Schalter im Desktop-Sidebar-Footer UND im mobilen Header — sichtbar von jeder Seite ohne Dropdown
- Facebook-Login deaktiviert: Schaltfläche wird als 'Demnächst verfügbar' angezeigt statt silent failing
Infrastruktur- lib/audit/log.ts: getFilteredAuditEntries() mit action/adminEmail/dateRange/pagination-Parametern ergänzt; AUDIT_ACTIONS-Konstante für UI-Dropdowns exportiert
- components/layout/app-shell.tsx: 'Logs'-Eintrag in Admin-Navigation hinzugefügt; DarkModeToggle-Subkomponente in sidebar- und header-Variante
- v0.41.0
Phase 51 + 52 — Stripe Upgrade-Flow & Kampagnen-Freigabe mit E-Mail
Phase 51 bestätigt live: In-App-Upgrade Free → Plus → Family über Stripe Checkout mit Success/Cancel-Seiten, Webhook-Verarbeitung und Feature-Gate-Enforcement. Phase 52 vervollständigt: Admins können Kampagnen freigeben oder ablehnen, der Partner erhält jetzt automatisch eine E-Mail-Benachrichtigung — bei Freigabe eine Bestätigung, bei Ablehnung inklusive der eingetragenen Begründung. Zusätzlich: Hostinger-SMTP aktiv (Phase 53), Feedback-System (Phase 50).
Neu- Phase 51: Stripe Checkout-Session für Plus & Family Upgrade (createCheckoutSessionAction)
- Phase 51: Stripe Customer Portal für Abo-Verwaltung & Kündigung (createPortalSessionAction)
- Phase 51: Webhook verarbeitet customer.subscription.created/updated/deleted + checkout.session.completed
- Phase 51: Feature-Gates enforced — Inventory-Limit, Receipt-Scan-Limit plan-basiert
- Phase 52: E-Mail-Benachrichtigung an Partner bei Kampagnen-Freigabe (Bestätigungs-E-Mail mit Dashboard-Link)
- Phase 52: E-Mail-Benachrichtigung an Partner bei Kampagnen-Ablehnung (inkl. Begründung und Überarbeitungslink)
- Phase 52: Audit-Log-Eintrag mit dbUpdated-Flag für Legacy-Mock-Kampagnen
Infrastruktur- nodemailer@7 im Dockerfile explizit kopiert (standalone file-tracing miss fix)
- deploy.sh: --legacy-peer-deps für nodemailer@7/next-auth Peer-Konflikt
- deploy.sh: CRLF-Handling beim source .env.production (tr -d '\r')
- react-is als explizite Dependency für recharts v3 Kompatibilität
- v0.40.0
Phase 50 — Feedback & Support System
Nutzer können über einen fixierten Floating-Button unten rechts jederzeit Feedback einreichen (Fehler, Idee, Feedback, Support). Neben der Nachricht werden automatisch Seiten-URL, Browser, Gerät, Auflösung, Plan und App-Version gespeichert. Admins sehen alle Einträge in einer neuen Inbox mit KPIs, Filter nach Status und Typ, können Einträge als 'Wichtig', 'Offen' oder 'Erledigt' markieren (Wichtig erscheint immer ganz oben), und können interne Admin-Notizen oder öffentliche Antworten per E-Mail senden.
Neu- Floating Feedback-Button (fixiert, unten rechts) auf allen App-Seiten
- Modal mit Typ-Auswahl (Fehler/Idee/Feedback/Support) und Textnachricht
- Auto-Capture: URL, UserAgent, Auflösung, Viewport, DPR, Sprache, Plattform, PWA-Status, App-Version, Plan
- POST /api/feedback — anonyme und authentifizierte Einreichung
- Admin /admin/feedback — Inbox mit KPIs (Offen/Wichtig/Erledigt/Gesamt)
- Filter nach Status (Offen/Wichtig/Erledigt/Alle) und Typ
- Wichtig-Einträge immer oben in der Listenansicht
- Admin /admin/feedback/[id] — Vollansicht mit Metadaten (UserAgent, Gerät, Seite, Plan)
- Status-Buttons: direkt auf Wichtig/Offen/Erledigt setzen
- Kommentarsystem: Intern (Admin-only) oder Öffentlich
- Öffentliche Kommentare optional per E-Mail an Nutzer senden
- E-Mail-Checkbox nur sichtbar wenn Nutzer-E-Mail bekannt und Kommentar öffentlich
- Prisma-Modelle: FeedbackEntry + FeedbackComment (Migration 20260606120000)
- FeedbackEntry: userId nullable (bleibt bei Konto-Löschung erhalten)
- Admin-Navigation: 'Feedback'-Link ergänzt
- NEXT_PUBLIC_APP_VERSION in next.config.ts aus package.json (Feedback trägt App-Version)
Infrastruktur- Prisma-Migration 20260606120000_add_feedback — FeedbackEntry, FeedbackComment, Enums, Indizes
- domains/feedback/feedback.service.ts — listFeedback, getFeedbackById, setFeedbackStatus, addFeedbackComment, getFeedbackStats
- app/admin/feedback/actions.ts — Server Actions mit Admin-Guard
- v0.39.0
Phase 47 + 49 — SSE Echtzeit-Einkaufsliste & Push-Test-Button
Phase 47 ersetzt das 10s-Polling der Einkaufsliste durch Server-Sent Events via Redis pub/sub. Jede Mutation (Hinzufügen, Abhaken, Löschen, Bulk-Aktionen) publiziert ein Redis-Signal; alle verbundenen Browser-Tabs des Haushalts erhalten sofort ein 'update'-Event und rufen router.refresh() auf. Fallback: 30s-Polling wenn SSE nicht verfügbar. Phase 49 ergänzt den Subscription-State-Check auf Mount (zeigt direkt 'Aktiv' statt 'Aktivieren'), fügt einen 'Test senden'-Button hinzu und stellt einen POST /api/notifications/test-push Endpoint bereit.
Neu- SSE-Endpoint GET /api/shopping-list/stream?householdId= mit Redis pub/sub und Heartbeat (25s)
- Redis-Kanal sp:sl:{householdId} — publish nach jeder Einkaufslisten-Mutation
- publishListUpdate() nach addItem, toggle, delete, clearChecked, alle Bulk-Aktionen
- ShoppingListClient: EventSource ersetzt setInterval-Polling (30s Fallback bleibt)
- Sync-Indikator zeigt 'Live-Verbindung aktiv' bei SSE, Fallback bei Disconnect
- Retry-Logik: EventSource-Reconnect nach 8s bei Verbindungsabbruch
- Push: Subscription-State wird bei Mount per pushManager.getSubscription() geprüft
- Push: 'Test senden'-Button im Browser-Push-Bereich der Einstellungen
- POST /api/notifications/test-push — sendet Test-Push an letzte aktive Subscription
- Push: Abgelaufene Subscriptions werden automatisch gelöscht (410/404 Handling)
Infrastruktur- X-Accel-Buffering: no Header am SSE-Endpoint (Nginx-Buffer-Disable)
- Dedizierte ioredis-Verbindung pro SSE-Client (pub/sub kann nicht geteilt werden)
- RedisLike.publish() Stub — App startet ohne Redis ohne Fehler
- v0.38.0
Phase 45 + 48 — PWA-Verbesserungen und Revenue-Zeitreihen
Phase 45 verbessert die PWA-Installation: das Manifest erhält volle Icon-Größen, 4 App-Shortcuts und display_override. Der Install-Banner persistiert jetzt 7 Tage via localStorage und zeigt iOS-Safari-Nutzern eine schrittweise 'Zum Startbildschirm'-Anleitung. Phase 48 führt RevenueSnapshot in der DB ein: ein monatlicher Cron-Job sichert MRR, Plan-Verteilung und Partner-Ausgaben als Zeitreihe. Der Admin-Chart zeigt sofort Näherungswerte aus Nutzer-Beitrittsdaten und wechselt automatisch auf 'Live'-Badge sobald echte Snapshots vorhanden sind.
Neu- PWA: manifest.json — display_override, prefer_related_applications:false, scope, 4 App-Shortcuts (Vorrat/Scan/Einkauf/Rezepte)
- PWA: Install-Banner dismissed-State wird 7 Tage in localStorage gespeichert (kein Reset bei Seitenneuladen)
- PWA: iOS Safari Flow — schrittweise 'Teilen → Zum Startbildschirm'-Anleitung mit Icons
- PWA: mobile-web-app-capable Meta-Tag für direkte PWA-Link-Öffnung
- PWA: Service-Worker Cache-Version auf v2 (erzwingt Cache-Invalidierung auf Clients)
- Revenue-Zeitreihen: RevenueSnapshot-Tabelle in PostgreSQL (Prisma-Migration 20260606000000)
- Revenue-Zeitreihen: POST /api/cron/revenue-snapshot — monatlicher Snapshot (CRON_SECRET gesichert)
- Revenue-Zeitreihen: Sofortiger Fallback — Näherungswerte aus user.createdAt nach Plan
- Revenue-Chart: Gestrichelte Linie = Näherung, durchgezogen = DB-Snapshot, Badge wechselt automatisch
- Admin-Dashboard KPI: MRR jetzt aus echten DB-Daten (statt Demo-Wert)
- Admin-Billing-Tabelle: Monatliche Zeilen jetzt aus realen Daten
Infrastruktur- VPS Cron ergänzen: 30 6 1 * * POST /api/cron/revenue-snapshot (1. jeden Monats)
- Prisma-Client regeneriert für RevenueSnapshot-Modell
- RevenueChartRow-Typ ersetzt AdminRevenueRow in allen Admin-Seiten
- v0.37.0
Phase 44 — Admin Analytics: Echte DB-Daten + VPS-Cron (MHD-Check)
Die Admin-Analytics-Seite zeigt jetzt echte Daten aus der PostgreSQL-Datenbank: Plan-Verteilung (Free/Plus/Family), geschätzter MRR (2,99 € / 5,99 €), bezahlende Nutzer, Conversion Rate sowie live Partner-Performance-Kennzahlen aus der Campaign-Tabelle. Zusätzlich wurde ein täglicher VPS-Cron-Job eingerichtet, der automatisch MHD-Warnungen für alle Haushalte versendet.
Neu- Admin Analytics: Plan-Verteilung (Free/Plus/Family) live aus DB per groupBy
- Admin Analytics: Geschätzter MRR berechnet aus Plan-Preisen (Plus 2,99 €, Family 5,99 €)
- Admin Analytics: Conversion Rate (Paid / Gesamt) live
- Admin Analytics: Partner-Performance (Impressionen, Klicks, CTR, Conversions, Ausgaben) aus Campaign-Tabelle
- Admin Analytics: Visueller Plan-Distribution-Balken mit Farbkodierung
- VPS Cron-Job: täglicher MHD-Check um 07:00 Uhr via POST /api/cron/mhd-check
- Revenue-Chart weiterhin als Demo-Daten (klar gekennzeichnet) — Zeitreihen-Tracking kommt in Phase 48
Infrastruktur- CRON_SECRET in .env.production gesetzt und sp-app-Container neu gestartet
- getAdminBillingStats() nutzt prisma.user.groupBy für plan-spezifische MRR-Berechnung
- getRealPartnerStats() nutzt prisma.campaign.aggregate über alle Kampagnen
- Fallback-Werte (alle 0) bei DB-Fehlern für Produktions-Resilienz
- v0.36.0
Phase 40–43 — Echtzeit-Einkaufsliste, Prisma Migrations, Open Food Facts, Resend
Vier Plattform-Upgrades in einer Version: die Einkaufsliste synchronisiert sich alle 10 Sekunden automatisch für Mehrpersonenhaushalte, Prisma wechselt von db push auf versionierte Migration-Dateien, Open Food Facts liefert echte Produktdaten ohne API-Key, und Resend ermöglicht transaktionale E-Mails (Willkommen, Passwort-Reset) in Produktionsqualität.
Neu- Phase 40 — Einkaufsliste: useEffect-Polling alle 10 s via router.refresh() — alle Haushaltsmitglieder sehen Änderungen in Echtzeit
- Sync-Indikator in der Einkaufsliste zeigt 'Zuletzt aktualisiert HH:MM:SS' nach erstem Poll
- Polling pausiert während ausstehender Transitions (isPending) — kein race condition
- Phase 41 — Open Food Facts: PRODUCT_DATA_ADAPTER=open-food-facts aktiviert echte Produktdaten (Barcode-Lookup + Textsuche)
- OFF-Adapter mit Allergen-Mapping (14 Einträge DE), Kategorie-Mapping, E-Nummern, NutriScore, Nova, EcoScore, Nährwerte
- Graceful fallback auf Mock-Adapter wenn OFF offline oder Produkt unbekannt
- Phase 42 — Resend E-Mail: EMAIL_PROVIDER=resend + RESEND_API_KEY aktiviert transaktionale E-Mails
- Willkommens-Mail, E-Mail-Verifikation, Passwort-Reset — alle mit HTML-Vorlage und Text-Fallback
Infrastruktur- Phase 43 — Prisma Migrate: initiale Migration 20260605000000_init generiert aus Schema (816 Zeilen DDL)
- prisma/migrations/migration_lock.toml: Lock-Datei für Provider-Konsistenz
- deploy.sh: automatische Baseline-Erkennung — bei erster Migration auf vorhandenem DB-Push-Schema wird init als 'already applied' markiert
- deploy.sh: prisma migrate deploy statt db push — sicher, auditierbar, rollback-fähig
- package.json: db:deploy Skript für manuelle Migration in Staging/Prod
- .env.production.template: AUTH_URL, GOOGLE_CLIENT_ID/SECRET, tesseract als RECEIPT_PARSER_PROVIDER-Default dokumentiert
- v0.35.0
Phase 38 — E2E Tests mit Playwright
Playwright-Testsuite für die drei kritischen User-Flows: Registrierung+Onboarding, Vorrat hinzufügen, Rezept kochen. Auth-Setup speichert Session-State für schnelle, wiederverwendbare Tests. TypeScript-Fix im Tesseract-Adapter (PSM-Enum).
Neu- playwright.config.ts: 4 Projekte (setup, public, registration, authenticated), webServer auto-start
- e2e/setup/auth.setup.ts: einmaliges Login / Registrierung, speichert Auth-State in playwright/.auth/user.json
- e2e/tests/01-landing.spec.ts: Landingpage, Navigation, Impressum, Datenschutz, Changelog (7 Tests)
- e2e/tests/02-registration.spec.ts: Vollständiger Registrierungs-Flow + Onboarding-Wizard (4 Tests)
- e2e/tests/03-inventory.spec.ts: Produkt manuell hinzufügen + in Liste finden (3 Tests)
- e2e/tests/04-recipe-cook.spec.ts: Rezept öffnen, Jetzt-kochen, Einkaufsliste (4 Tests)
Bugfix- tesseract-js.adapter.ts: PSM.SINGLE_BLOCK statt String '6' — TypeScript strict mode fix
Infrastruktur- package.json: @playwright/test ^1.60, Skripte test:e2e / test:e2e:ui / test:e2e:debug
- .gitignore: playwright-report/, playwright-results/, playwright/.auth/ ignoriert
- npm run test:e2e startet alle E2E-Tests (erfordert laufende App)
- v0.34.0
Kassenbon-OCR — Tesseract.js (self-hosted WASM, kein API-Key)
Statt Mindee läuft die Kassenbon-OCR jetzt mit Tesseract.js: vollständig self-hosted via WebAssembly im Node.js-Prozess, kein externer API-Key, kein Kostenlimit. Sprachdaten für Deutsch + Englisch werden beim ersten Aufruf gecacht. Aktivierung via RECEIPT_PARSER_PROVIDER=tesseract.
Neu- modules/receipt-parsing/adapters/tesseract-js.adapter.ts: neuer OCR-Adapter mit parseTesseractReceipt()
- Deutscher Kassenbon-Parser: erkennt Produktname, Menge, Einzelpreis, Gesamtpreis, Ladenname und Datum
- Unterstützte Formate: 2x Bio-Gurke, DINKELMEHL 1KG, Vollmilch 3,5% mit MwSt-Kürzel A/B
- PSM 6 (Single uniform block of text) optimiert für Kassenbon-Layout
- receipt-parsing.service.ts: RECEIPT_PARSER_PROVIDER=tesseract als neue Option
Infrastruktur- next.config.ts: serverExternalPackages für tesseract.js + tesseract.js-core (verhindert Webpack-Bundling von WASM)
- Dockerfile: expliziter COPY von tesseract.js und tesseract.js-core als Safety-Net für Standalone-Tracing
- RECEIPT_PARSER_PROVIDER=tesseract in .env.production auf VPS gesetzt
- package.json: tesseract.js ^7.0.0 in dependencies
- v0.33.0
Kassenbon-OCR Phase 37 — Mindee-Integration live
Das Kassenbon-Scan-Feature ist von Mock auf echte OCR umgestellt. Bilder werden sicher als Server Action an die Mindee-API (oder Tabscanner) gesendet — der API-Key bleibt serverseitig. Rate Limiting: 10 OCR-Scans pro Tag. Steuerbar via RECEIPT_PARSER_PROVIDER=mindee|tabscanner|mock.
Neu- parseReceiptAction: neue Server Action nimmt File via FormData entgegen, ruft OCR-Service auf, gibt strukturierte LineItems zurück
- Mindee OCR aktiviert (250 Seiten/Monat gratis) — liefert Produktname, Menge, Einzelpreis, Gesamtpreis, Confidence
- receipt-scan-client.tsx: ruft parseReceiptAction statt parseReceiptMock direkt auf — API-Key bleibt server-seitig
- MIME-Typ-Guard: nur JPG, PNG, WebP, HEIC, PDF erlaubt
- Dateigrößen-Guard: max. 10 MB
Sicherheit- Rate Limit: 10 OCR-Anfragen pro Tag pro Nutzer (Mindee API Cost Protection)
- next.config.ts: Server-Actions-Body-Limit auf 10 MB angehoben (Kassenbonbilder)
Infrastruktur- Feature-Flag RECEIPT_PARSER_PROVIDER=mindee|tabscanner|mock (Umschaltung ohne Code-Änderung)
- MINDEE_API_KEY in .env.production auf VPS gesetzt
- v0.32.1
Sentry Error Tracking aktiviert (Phase 39) + Impressum & Datenschutz
Sentry ist jetzt vollständig aktiv — NEXT_PUBLIC_SENTRY_DSN und SENTRY_DSN auf dem VPS gesetzt. Fehler in Produktion werden ab sofort erfasst und an sentry.io gemeldet. Impressum und Datenschutzerklärung mit echten Betreiberdaten (eProjekt, Bad Segeberg) befüllt.
Infrastruktur- Sentry Error Tracking aktiviert: NEXT_PUBLIC_SENTRY_DSN + SENTRY_DSN in .env.production gesetzt
- PII-Scrubbing aktiv: E-Mail, Username und IP-Adresse werden vor dem Senden aus Events entfernt
- tracesSampleRate: 0.1 (10 % der Requests werden als Performance-Traces erfasst)
- Gilt für server-seitige Fehler, Edge-Runtime-Fehler und Client-seitige Fehler (instrumentation.ts)
Docs- Impressum: echte Adresse (Teichstraße 18c, 23795 Bad Segeberg), USt-IdNr. DE815483875, Telefon, eprojekt.design-Link
- Datenschutz: Verantwortlicher aktualisiert, Hosting-Abschnitt (IONOS Deutschland) ergänzt, Stand Juni 2026
- Footer: 'StockPilot c/o eProjekt' mit Link zu eprojekt.design
- v0.32.0
Rate Limiting (Phase 36) + Google OAuth Code-Complete (Phase 35)
Redis-basiertes Rate Limiting schützt alle API-Endpoints vor Brute-Force und Missbrauch. Google OAuth war bereits im Code vollständig implementiert — der 'Mit Google anmelden'-Button ist auf Login- und Registrierungsseite aktiv, wartet nur auf GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET in der Produktionsumgebung.
Sicherheit- lib/rate-limit/rate-limiter.ts: Sliding-window Rate Limiter via ioredis — fail-open bei Redis-Ausfall
- lib/rate-limit/api-helpers.ts: guardApiRoute() (100 req/min) + guardAuthRoute() (20 req/min) für API Routes
- app/api/auth/[...nextauth]/route.ts: Auth-Endpunkt mit 20 req/min Rate Limit pro IP gesichert
- app/register/actions.ts: Registrierungsversuch mit checkAuthLimit() gesichert (20/min pro IP)
- app/app/scan/actions.ts: addScannedItemAction mit checkScanLimit() gesichert (200 Scans/Tag pro Nutzer)
- app/app/meal-plan/actions.ts: generateMealPlanAction mit checkAiMealPlanLimit() gesichert (5 KI-Pläne/Tag)
- lib/redis/client.ts: RedisLike-Stub um incr(), expire(), ttl() erweitert (fail-open stubs)
Neu- Phase 35: Google OAuth vollständig live — 'Mit Google anmelden' auf Login + Registrierungsseite aktiv
- Account-Linking: bestehender E-Mail-Account wird bei gleichem Google-Konto automatisch verknüpft
- Google Provider in NextAuth mit allowDangerousEmailAccountLinking + find-or-create user flow
- v0.31.1
Produktions-Hotfixes — Prisma-Adapter, Service Worker, use server
Drei Produktionsfehler behoben, die erst in der Docker-Deployment-Umgebung auftraten: Prisma @adapter-pg gibt DateTime-Felder als Strings zurück; String[]-Felder kamen nicht als JS-Arrays an; AVAILABLE_CATEGORIES und ALLERGEN_OPTIONS crashten weil sie aus einer 'use server'-Datei importiert wurden (Next.js erlaubt dort nur async-Funktions-Exporte).
Bugfix- inventory/page.tsx: daysUntil() + formatDate() defensiv für string|Date (Prisma @adapter-pg in Docker gibt DateTime als Strings zurück)
- settings/page.tsx: Array.isArray()-Schutz für preferredCategories + allergenProfile
- Alle Settings-Client-Komponenten: Array.isArray()-Guard für alle Array-Props (Account, Storage, Members, Allergens, Categories)
- settings/constants.ts (neu): AVAILABLE_CATEGORIES + ALLERGEN_OPTIONS in eigene Datei ohne 'use server' ausgelagert — Root Cause des x.map-Crashes
- actions.ts: Illegale Re-Exporte von Konstanten aus 'use server'-Datei entfernt
- public/sw.js: /apple-icon.png aus Service-Worker-Precache entfernt (wird von Next.js dynamisch generiert → 404)
- v0.31.0
Stripe Billing (Phase 34) & Sentry Error Tracking (Phase 39)
Stripe war bereits vollständig aufgebaut — es fehlten die server-seitigen Feature-Gate-Enforcements. Die Inventar- und Scan-Actions prüfen jetzt das 50-Item-Limit, die Kassenbon-Action prüft das Monats-Limit. Der Admin zeigt den Plan jedes Nutzers. Sentry war ebenfalls bereits konfiguriert — nur die Env-Variable NEXT_PUBLIC_SENTRY_DSN muss auf dem VPS gesetzt werden. Deployment-Dokumentation aktualisiert.
Neu- Stripe Billing: addItemAction, quickAddItemAction, addScannedItemAction prüfen jetzt canAddInventoryItem() (50-Item-Limit)
- Stripe Billing: bulkAddReceiptItemsAction prüft canScanReceipt() (5 Kassenbons/Monat im Free-Plan)
- Admin Nutzerverwaltung: neue 'Plan'-Spalte mit farbigen Badges (Free/Plus/Family)
- Sentry: bereits vollständig konfiguriert (instrumentation.ts, sentry.server.config.ts) — nur NEXT_PUBLIC_SENTRY_DSN setzen
- .env.example: STRIPE_PRICE_PLUS_MONTHLY, STRIPE_PRICE_FAMILY_MONTHLY, ANTHROPIC_API_KEY ergänzt
- Unit Tests: RecipeStep.duration → RecipeStep.step Typo-Fix
Infrastruktur- Feature-Gate-Enforcement: Feature-Gates waren nur für UI-Banners genutzt, jetzt auch server-seitig in Actions
- Stripe-Setup-Anleitung: dashboard.stripe.com → Products → 2 Prices anlegen → IDs als Env-Vars setzen
- v0.30.0
Unit Tests (vitest) — 97 Tests für Business-Logik
Vollständige vitest-Test-Suite für alle reinen Berechnungsfunktionen: Health-Scoring, CO₂-Berechnung, Rezept-Matching, Additives-Lookup, Rewards-Level, Preislogik und Changelog-Konsistenz. 97 Tests in 7 Dateien, alle grün. CI/CD führt Tests jetzt als Quality-Gate vor jedem Deploy aus.
Infrastruktur- vitest.config.ts: Node-Umgebung, @-Alias, include tests/**/*.test.ts
- tests/unit/health.service.test.ts: 12 Tests für buildHealthSummary() + DAILY_REFERENCE_VALUES
- tests/unit/carbon.service.test.ts: 12 Tests für computeCarbonSummary() + ECO_CO2
- tests/unit/recipe.service.test.ts: 23 Tests für calculateMatch(), filterRecipes(), withMatch(), getAllRecipes()
- tests/unit/additives-data.test.ts: 14 Tests für lookupAdditive(), lookupAdditives(), RISK_LABEL/COLOR
- tests/unit/rewards.helpers.test.ts: 17 Tests für getLevelForPoints(), getNextLevel(), POINT_ACTIONS
- tests/unit/changelog.test.ts: 6 Tests für Versions-Konsistenz (CURRENT_VERSION === package.json)
- tests/unit/price.service.test.ts: 13 Tests für Trend-Berechnung, Preisformatierung, Budget-Logik
- CI/CD: 'npx vitest run' als neuer Schritt im Quality-Gate (nach TypeCheck, vor Lint)
- v0.29.0
Community-Rezeptbuch (Ph.28), FoodShare 2.0 (Ph.29), Mikronährstoffe (Ph.30) & Price Intel 2.0 (Ph.33)
Vier Phasen auf einmal: Community-Rezepte können jetzt gemeldet werden (AdminAuditLog). FoodShare vergibt endlich Punkte (+25 beim Erstellen, +15 beim Abholen) und zeigt 'Meine Abholungen'. Health zeigt EU-Referenzwerte als Fortschrittsbalken für alle verfügbaren Nährstoffe. Price Intelligence 2.0: Preis-Alerts lösen automatisch In-App-Benachrichtigungen aus und können manuell geprüft werden.
Neu- Phase 28: 'Melden'-Button auf Community-Rezepten → AdminAuditLog-Eintrag mit Bestätigungs-Dialog
- Phase 29: FoodShare-Punkte endlich vergeben: +25 beim Erstellen, +15 beim Abholen (BUGFIX!)
- Phase 29: 'Meine Abholungen'-Sektion in FoodShare zeigt Historie der abgeholten Angebote
- Phase 30: Health-Seite: Ø Nährstoffprofil mit EU-RDI-Balken (Eiweiß, KH, Fett, Ballaststoffe, Salz)
- Phase 33: checkPriceAlertsAction: prüft aktive Alerts, erstellt Notification bei Preisunterschreitung
- Phase 33: 'Preisalarme jetzt prüfen'-Button auf der Preisbeobachtungs-Seite
- Phase 33: Alert-Check wird automatisch nach jeder manuellen Preis-Eingabe beim Scan ausgelöst
- v0.28.0
CO₂-Budget (Phase 27), Echte Preisschätzung (Phase 31) & Redis-Caching
Phase 27 vervollständigt: auf der CO₂-Seite gibt es jetzt ein interaktives Wochenziel-Widget mit Fortschrittsbalken, Presets (5–30 kg) und Slider. Phase 31 verbessert: die Einkaufslisten-Budgetschätzung nutzt jetzt echte ProductPriceObservation-Daten (aus Scan-Preiseingabe oder Kassenbons) — mit Fallback auf €1,50/Artikel. Redis-Caching: Inventory (60s), ShoppingList (15s) und Rewards (120s) sind jetzt gecacht mit automatischer Invalidierung bei Mutationen.
Neu- CO₂-Seite: Wochenziel-Widget mit Slider (1–50 kg), Presets, Fortschrittsbalken & Überschreitungs-Alert
- CO₂-Seite: Ziel wird in UserProfile.carbonBudgetKgPerWeek persistiert (nullable Float, prisma db push)
- Einkaufsliste: Budget-Schätzung nutzt echte Ø-Preise aus ProductPriceObservation; ≈ statt 'ca.' wenn Realdaten vorhanden
Infrastruktur- Redis-Cache ausgebaut: TTL.INVENTORY (60s), TTL.SHOPPING_LIST (15s), TTL.REWARDS (120s)
- CacheKey.inventory(householdId, locationId?), CacheKey.shoppingList, CacheKey.rewards
- getInventory() → cached(); invalidate() bei add/consume/delete
- getShoppingList() → cached(); invalidate() bei add/toggle/delete/clear
- getRewardsSummary() → cached(); invalidate() nach awardPoints()
- v0.27.0
Preis-Schnelleingabe, FoodShare-Impact & Bulk-Lagerort (Phasen 78–80)
Beim Scannen kann nun optional ein Preis eingetragen werden — er wird als ProductPriceObservation gespeichert und ermöglicht persönliche Preisverlaufsdaten ohne Kassenbon-Import. Das Dashboard zeigt ein FoodShare-Impact-Widget wenn Angebote erstellt wurden. In der Inventar-Mehrfachauswahl gibt es jetzt einen Lagerort-Button der einen Inline-Picker öffnet.
Neu- Scan-Formular: optionales Preisfeld (€) → speichert ProductPriceObservation mit source='manual_scan'
- Dashboard: FoodShare-Impact-Widget zeigt Anzahl erstellter Angebote und weitergegeben Items
- Inventar Bulk: 🧊 Lagerort-Button öffnet Inline-Picker mit allen Haushalts-Lagerorten
- Inventar Bulk: 'Kein Lagerort' Option entfernt zugewiesenen Lagerort von allen selektierten Items
- v0.26.0
Jetzt kochen, Einladungs-QR-Code & Sofort-kochbar-Widget (Phasen 75–77)
'Jetzt kochen' schließt den Loop zwischen Rezepten und Vorrat — passende Inventory-Items werden per Klick als verbraucht markiert. Im Einladungslink-Bereich der Settings gibt es jetzt einen QR-Code-Toggle via api.qrserver.com. Das Dashboard zeigt ein 'Sofort kochbar'-Widget mit Rezepten, für die ≥ 80 % der Zutaten im Vorrat sind.
Neu- Rezept-Detail: 'Jetzt kochen'-Banner mit grünem CTA — markiert passende Inventory-Items CONSUMED (FIFO, searchTerm-Matching)
- Rezept-Detail: +3 Punkte pro verbrauchtem Artikel, Erfolgs-Feedback mit Produktanzahl
- Settings Haushalt: QR-Code-Button neben dem Einladungslink (Toggle, api.qrserver.com, 180×180 px)
- Dashboard: 'Sofort kochbar'-Widget zeigt bis zu 3 Rezepte mit ≥ 80 % Zutaten-Match
- v0.25.0
Community-Rezeptbuch (Phase 28) & Smarte Einkaufsliste 2.0 (Phase 31)
Phase 28 (Community-Rezeptbuch) wird vervollständigt: auf öffentlichen Community-Rezepten gibt es jetzt einen Teilen-Button (nativ / Clipboard), und die Rezepte-Seite zeigt eine 'Neu in der Community'-Galerie. Phase 31 (Smarte Einkaufsliste 2.0): Markt-Sortierung nach Supermarkt-Laufweg, Spracheingabe via Web Speech API und eine Kostenabschätzung für offene Artikel.
Neu- Rezepte: 'Teilen'-Button auf Community-Rezept-Detailseiten (navigator.share / Clipboard-Fallback)
- Rezepte: 'Neu in der Community'-Galerie zeigt die 3 neuesten öffentlichen Rezepte anderer Nutzer
- Einkaufsliste: Sortierung nach Supermarkt-Laufweg ('Markt'-Button) mit 12-Aisle-Keyword-Mapping
- Einkaufsliste: Alphabetisch-Sort-Button ('A–Z') als zweite Sortierung
- Einkaufsliste: Spracheingabe-Button (🎤) via Web Speech API, Sprache de-DE
- Einkaufsliste: Geschätzte Kosten ('ca. € X,XX') bei ≥ 2 offenen Artikeln (Ø €1,50/Artikel)
- v0.24.0
Bulk-Verbraucht, Monatliche Stats & Wochenplan-Druck (Phasen 72–74)
In der Inventar-Mehrfachauswahl gibt es jetzt einen grünen 'Verbraucht'-Button der alle selektierten Artikel auf einmal als aufgebraucht markiert (mit Punkte-Vergabe). Die Statistik-Seite zeigt ein 'Dieser Monat'-Highlight mit Verbraucht/Abgelaufen-Zahlen, Rescue Rate und Top-Kategorie. Der Wochenplan hat einen Drucken-Button der window.print() auslöst.
Neu- Inventar: Bulk-Mehrfachauswahl — neuer 'Verbraucht'-Button (grün) markiert alle gewählten Artikel
- Inventar: Lösch-Button in der Bulk-Bar auf Icon-only verkleinert (mehr Platz für neue Aktion)
- Stats: 'Dieser Monat'-Karte mit Verbraucht / Abgelaufen / Rescue Rate / Top-Kategorie
- Wochenplan: 'Drucken'-Button im Header (window.print, print:hidden — kein Extra-CSS)
- v0.23.0
Scan-Verlauf, Rescue-Rate-Widget & Einkaufsliste teilen (Phasen 69–71)
Die Scan-Seite zeigt jetzt die zuletzt hinzugefügten Vorrats-Artikel direkt darunter — mit relativem Zeitstempel und Link zur Detail-Seite. Das Dashboard hat ein farbcodiertes Rescue-Rate-Widget, das den Anteil verbrauchter vs. abgelaufener Produkte der letzten 30 Tage anzeigt. Die Einkaufsliste lässt sich per nativen Share-Dialog (mobil) oder Zwischenablage-Kopie mit anderen teilen.
Neu- Scan-Seite: 'Zuletzt hinzugefügt'-Liste mit relativem Timestamp (Gerade eben / Vor X Min. / Vor X Tagen)
- Dashboard: Food-Rescue-Rate-Widget mit Fortschrittsbalken und Farbcodierung (grün ≥ 80 %, amber ≥ 50 %, rot < 50 %)
- Einkaufsliste: 'Teilen'-Button mit navigator.share (mobil/PWA) und Clipboard-Fallback
- Einkaufsliste: exportiertes Format enthält offene + erledigte Artikel mit Datum und Haushaltsnamen
- v0.22.0
Notification-Banner, Marketplace-Redesign & Inventar-Deeplinks (Phasen 66–68)
Das Dashboard zeigt jetzt einen prominenten Benachrichtigungs-Banner, wenn ungelesene MHD-Warnungen vorliegen. Die Marktplatz-Seite wurde komplett auf das aktuelle Design-System migriert und ist nun mit echter Datenbankanbindung live. Von jedem Inventar-Detail gibt es direkte Links zur vollständigen Produktdetailseite und — bei ablaufenden Artikeln — eine FoodShare-CTA.
Neu- Dashboard: Notification-Banner mit Ungelesen-Zähler und Link zu /app/notifications
- Marketplace: vollständiges Redesign (aktuelle Design-Sprache, Tailwind v4)
- Marketplace: echte Prisma-Abfrage auf MarketplaceListing statt Mock-Daten
- Marketplace: horizontale Filter-Chips als URL-Parameter, sauberer Empty State
- Inventar-Detail: 'Vollständige Produktinfo'-Link zur Barcode-Produktseite
- Inventar-Detail: 'FoodShare-Angebot teilen'-CTA für Artikel mit ≤ 7 Tagen MHD
- v0.21.0
Kategorie-Filter, Health-Allergen-Warnung & CSV-Export (Phasen 63–65)
Der Vorrat lässt sich jetzt nach Kategorien filtern — Chips-Leiste kombinierbar mit dem bestehenden Lagerort-Filter. Die Health-Seite zeigt eine persönliche Allergen-Warnung wenn Produkte im Vorrat mit dem eigenen Allergen-Profil übereinstimmen. Der gesamte aktive Vorrat ist als CSV-Datei exportierbar.
Neu- Inventar: Kategorie-Filter-Chips (kombinierbar mit Lagerort-Filter)
- Health: persönliche Allergen-Warnung mit roter Hervorhebung bei Profil-Übereinstimmung
- Health: Link zu Einstellungen für Allergen-Profil wenn noch nicht eingerichtet
- Inventar: CSV-Export via GET /api/inventory/export (UTF-8 BOM für Excel-Kompatibilität)
- Inventar: '↓ CSV Export'-Button am Ende der Vorrats-Ansicht
- v0.20.0
Allergen-Profil, Wochenplan für alle & Dashboard-Widgets (Phasen 60–62)
Nutzer können ihr persönliches Allergen-Profil in den Einstellungen hinterlegen — beim Scan und auf der Produktdetail-Seite erscheint dann eine personalisierte Warnung. Der Wochenplan ist jetzt für alle Nutzer zugänglich (Free-Tier: Rezeptvorschlag ohne KI; Plus: Claude-powered). Das Dashboard zeigt eine Kategorie-Übersicht des Vorrats und einen direkten Wochenplan-Link.
Neu- Allergen-Profil in Einstellungen: 22 wählbare Allergene (Gluten, Milch, Erdnüsse, Soja, …)
- Allergen-Warnung auf Produktdetail-Seite: persönliche Treffer rot hervorgehoben
- Wochenplan für alle Nutzer: Free-Tier zeigt automatischen Rezeptvorschlag ohne KI-Personalisierung
- Wochenplan: Free-Tier-Banner mit Upgrade-Link, Plus-Badge bei aktivem Claude-API-Key
- Dashboard: Kategorie-Übersicht — scrollbare Chips mit Anzahl pro Kategorie
- Dashboard: Wochenplan-Quick-Link-Card in der Hauptnavigation
Infrastruktur- Prisma-Schema: UserProfile.allergenProfile String[] @default([]) neu
- settings/actions.ts: saveAllergenProfileAction + ALLERGEN_OPTIONS (22 Einträge)
- prisma generate nach Schema-Erweiterung
- v0.19.0
Open Food Facts Adapter, Produktdetail-Seite & EFSA-Zusatzstoffhinweise (Phasen 57–59)
Open Food Facts (OFF) Adapter vollständig aktiviert — wechselbar via PRODUCT_DATA_ADAPTER=open-food-facts. Neue Produktdetail-Seite /app/products/[barcode] mit Nährwerttabelle, NutriScore/EcoScore/NOVA, Allergenen und EFSA-Zusatzstoffbewertungen. Im Scan-Erfolgs-Screen werden erkannte E-Nummern als Chips angezeigt und ein direkter Link zur Produktdetail-Seite eingeblendet.
Neu- Produktdetail-Seite /app/products/[barcode]: Nährwerttabelle pro 100 g (Energie, Kohlenhydrate, Fett, Eiweiß, Ballaststoffe, Salz)
- Produktdetail-Seite: NutriScore, EcoScore und NOVA-Gruppe als farbige Badges
- Produktdetail-Seite: Allergen-Liste mit farbiger Amber-Hervorhebung
- Produktdetail-Seite: EFSA-Zusatzstoff-Lookup — E-Nummer, Funktion, Risikobewertung (low/medium/high), EFSA-Hinweis
- Produktdetail-Seite: aktueller Lagerbestand für dieses Produkt (Anzahl Einträge im Vorrat)
- Scan-Erfolgs-Screen: E-Nummern-Chips wenn Produkt Zusatzstoffe enthält
- Scan-Erfolgs-Screen: 'Produktdetails & Zusatzstoffe ansehen'-Link zur Detailseite
- Scan-Formular (vor Hinzufügen): 'Details'-Link zur Produktdetail-Seite
- additives in ScanProductResult übergeben (vom OFF-Adapter und Mock)
Infrastruktur- modules/product-data/additives-data.ts: 70+ E-Nummern (E100–E960), EFSA-basiert, mit deutschem Namen, Funktion, Risikolevel und Hinweis
- lookupAdditive(code), lookupAdditives(codes[]), RISK_LABEL, RISK_COLOR exportiert
- PRODUCT_DATA_ADAPTER=open-food-facts aktiviert OFF-Adapter (mit Mock-Fallback bei Fehler/unbekannt)
- Typefix: SCAN → SCAN_PRODUCT in inventory/actions.ts und scan/receipt/actions.ts
- Typefix: expiresAtFormatted zu EnrichedItem-Typ in inventory/page.tsx ergänzt
- Typefix: RecipeCategory-Vergleiche in app/page.tsx korrigiert
- Typefix: recharts PieLabelRenderProps in category-pie-chart.tsx
- v0.18.0
MHD-Cron, Notification Bell & Rezept des Tages (Phasen 54–56)
Täglicher MHD-Cron-Endpoint für alle Haushalte, gesichert durch CRON_SECRET. Notification Bell mit Unread-Badge war bereits implementiert. Neues "Rezept des Tages"-Widget auf dem Dashboard: deterministisch nach Tagesdatum gewählt, zeigt Match-Prozent mit aktuellem Vorrat und fehlende Zutaten.
Neu- Rezept des Tages auf dem Dashboard: täglich wechselndes Rezept, deterministische Tag-des-Jahres-Auswahl
- Rezept des Tages: Zutaten-Match-Prozent mit aktuellem Vorrat, fehlende Zutaten aufgelistet
- Rezept des Tages: Farb-Balken nach Kategorie, Kochzeit, Tags, direkt verlinkbar
- MHD-Cron-Endpoint POST /api/cron/mhd-check: läuft für alle Haushalte aller Nutzer
- Cron-Endpoint durch CRON_SECRET Bearer-Token gesichert (optional, aber empfohlen)
Infrastruktur- runDailyMhdCheckForAll(): iteriert über alle HouseholdMember, ruft createMhdNotifications auf
- app/api/cron/mhd-check/route.ts: POST-Handler mit Auth-Check + strukturiertem Logging
- Cron-Setup-Kommentar im Route-File (VPS-crontab Beispiel)
- Notification Bell + /app/notifications waren bereits vollständig implementiert (Phase 54 ✓)
- v0.17.0
Statistik-Seite, FoodShare & Heatmap vollständig (Phasen 51–53)
Neue Statistik-Seite /app/stats mit Balken-Chart (verbraucht vs. abgelaufen, letzte 8 Wochen), Donut-Chart der aktuellen Vorrats-Kategorien und KPI-Block (Rescue-Rate, gerettete kg, CO₂-Schätzung, FoodShare-Count). FoodShare inkl. aggregierter Heatmap ist bereits voll implementiert und direkt verlinkt. Navigation und Dashboard um Stats-Einstiegspunkte erweitert.
Neu- Statistik-Seite /app/stats: KPI-Block mit Rescue-Rate, Verbraucht-Count, geretteten kg und CO₂-Schätzung
- Balken-Chart: wöchentlich verbrauchte vs. abgelaufene Artikel (letzte 8 Wochen, recharts BarChart)
- Donut-Chart: Vorrat nach Kategorie (Top 10, recharts PieChart mit innerRadius)
- Food-Waste-Hinweis-Banner wenn abgelaufene Artikel vorhanden
- FoodShare- und Rewards-CTA-Cards am Ende der Stats-Seite
- "Statistiken"-Eintrag in der Navigation (Mehr-Menü, direkt nach Rezepte)
- "Haushalts-Statistiken"-Quick-Link auf dem Dashboard (zwischen Rewards und Food-Rescue-Score)
Infrastruktur- isoWeekLabel() und weekOffset() Hilfsfunktionen für Wochen-Gruppierung
- Parallele Prisma-Abfragen: consumed, expired, inventoryWithCats, foodShareOffers
- Kategorien JavaScript-seitig gruppiert (kein Prisma groupBy nötig)
- v0.16.0
Shopping-List UX, Kassenbon-Scan & Bulk-Import (Phasen 48–50)
Die Einkaufsliste zeigt jetzt ablaufende Vorrats-Artikel als Nachkauf-Vorschläge (Amber-Chips mit Tage-Countdown). Neuer Kassenbon-Scanner unter /app/scan/receipt: Foto hochladen oder aufnehmen, automatische Texterkennung (Mock), Line-Item-Prüfung mit Konfidenz-Badges und inline bearbeitbaren Namen. Mit einem Klick alle gewählten Artikel direkt in den Vorrat übernehmen.
Neu- Einkaufsliste: "Bald aufgebraucht — nachkaufen?"-Chips für Vorrats-Artikel ≤7 Tage bis Ablauf
- Ablauf-Chips: Tage-Countdown-Badge, Amber-Farbe, klickbar zum direkten Hinzufügen zur Liste
- Kassenbon-Scanner: neue Route /app/scan/receipt mit Upload-Bereich (Drag & Drop) und Kamera-Button
- Kassenbon-Parsing: Mock-Adapter simuliert OCR-Erkennung mit 1,6 s Ladezeit
- Ergebnis-Liste: Konfidenz-Badges (grün ≥85 %, amber ≥65 %, rot <65 %), unsichere Artikel einklappbar
- Inline-Bearbeitung: Produktname durch Tippen direkt in der Ergebnisliste korrigierbar
- Bulk-Import: ausgewählte Artikel werden als Inventar-Einträge angelegt (+5 Punkte je Artikel, max. 10)
- Kassenbon-Link auf der Scan-Seite als prominente Card mit Beschreibungstext
Infrastruktur- bulkAddReceiptItemsAction: findet oder erstellt Produkte per Name, bulk-create InventoryItems
- getExpiringReplacements(): Prisma-Query auf InventoryItem mit expiresAt ≤7 Tage, dedupliziert nach Name
- ExpiringReplacement-Typ aus shopping-list/page.tsx für Client-Komponente exportiert
- v0.15.0
Quick-Add, Lagerort-Manager, Ablauf-Timeline & Food-Rescue-Score (Phasen 44–47)
Produkte ohne Barcode per FAB-Dialog direkt im Vorrat anlegen. Lagerorte (Kühlschrank, Keller, …) in den Einstellungen verwalten. Neuer Ablauf-Timeline-Tab im Vorrat zeigt alle Artikel farbkodiert nach Dringlichkeit. Auf dem Dashboard erscheint der Food-Rescue-Score mit Fortschrittsbalken.
Neu- Quick-Add FAB im Vorrat: schwebender "+"-Button öffnet Bottom-Sheet mit Name, Kategorie, Menge, MHD und Lagerort
- Quick-Add: legt Produkt per Name an (kein Barcode nötig), vergibt +5 Punkte, Reset für nächsten Artikel
- Lagerort-Manager in Einstellungen: Lagerorte anlegen, umbenennen (Inline-Edit) und löschen
- Lagerort-Löschen setzt Items sanft auf keinen Lagerort (kein Datenverlust)
- Vorrat Ablauf-Timeline: dritter Tab mit 6 farbkodierten Gruppen (Abgelaufen → Kein MHD)
- Food-Rescue-Score auf dem Dashboard: Rate verbrauchter vs. abgelaufener Produkte (letzte 30 Tage)
- Food-Rescue-Widget: farbkodierter Fortschrittsbalken + Motivationstext (Ausgezeichnet / Gut / Luft nach oben)
- Food-Rescue-Widget: nur sichtbar wenn mindestens ein verbrauchtes oder abgelaufenes Produkt vorhanden
Infrastruktur- quickAddItemAction: findet oder erstellt Produkt per case-insensitivem Namensvergleich
- addStorageLocationAction / renameStorageLocationAction / deleteStorageLocationAction als Server Actions
- Dashboard Promise.all erweitert: zwei count-Abfragen für Food-Rescue-Metriken
- v0.14.0
Haushalt-Einladungen, Health-Scan & Kategorienpräferenzen (Phasen 40–43)
Mitglieder per Link einladen, Haushalt mit einem Klick beitreten, Mitglieder verwalten. Im Scan-Erfolgs-Screen erscheinen jetzt NutriScore, EcoScore und Allergen-Hinweise direkt nach dem Hinzufügen. Kategorienpräferenzen in den Einstellungen editierbar (12 Chips, sofort gespeichert).
Neu- Haushalt-Einladungslink: einmaliger 16-Zeichen-Code per Link teilen oder regenerieren
- Einladungs-Annahme-Seite /app/join/[code] mit Haushaltsname, Mitgliederanzahl und Join-Button
- Mitgliederliste in den Einstellungen: Avatar, Name, E-Mail, Rollen-Badge (Krone für Eigentümer)
- Mitglied entfernen direkt in der Einstellungssektion (Eigentümer nicht entfernbar)
- Einladungslink mit Copy-Button und Regenerieren-Schaltfläche in den Einstellungen
- Scan-Erfolgsscreen: NutriScore-Badge, EcoScore-Chip (🌿) und Allergen-Warnung (⚠️) nach dem Hinzufügen
- Kategorienpräferenzen: 12 auswählbare Chip-Kategorien (Obst & Gemüse, Milch & Käse, Fleisch & Fisch, …)
- Kategorien-Auswahl sofort per Button speicherbar, Toast-Bestätigung, leere Auswahl = alle Kategorien
Infrastruktur- Prisma-Schema: inviteCode String? @unique auf Household-Modell ergänzt
- Server Actions: generateInviteCodeAction, joinHouseholdAction (idempotent), removeMemberAction
- saveCategoriesAction mit Whitelist-Validierung (nur bekannte Kategorien werden akzeptiert)
- prisma generate nach Schema-Erweiterung (inviteCode + preferredCategories in Client-Types)
- v0.13.0
UX-Improvements: Onboarding, Profil, Scan, Vorrat & Dashboard (Phasen 34–39)
Sechs UX-Phasen in einem Release: verbesserter Onboarding-Flow mit Kategorienwahl und Willkommensbonus, neue Profilseite mit Stats und Aktivitätslog, überarbeiteter Barcode-Scanner mit Scan-History und Vibration, Inventar-Suche/-Sortierung und Quick-Consume, Rewards-Karte auf dem Dashboard sowie Rezeptvorschläge direkt fuer ablaufende Zutaten.
Neu- Onboarding: Lieblingskategorien-Auswahl (Schritt 4), Fortschrittsbalken statt Kreisindikator, Willkommensbonus-Karte im Abschluss-Screen
- Onboarding: Auto-Redirect aus dem App-Layout wenn Nutzer noch keinen Haushalt hat
- Profilseite /app/profile: Avatar, Name, Level-Badge, Streak, Stats-Strip (Punkte/Streak/Vorrat/FoodShare), Haushalt-Karte, Achievements-Grid, Aktivitaetslog, Abmelden
- Barcode-Scanner: Scan-History in localStorage, Produkt-Thumbnail, Haptic-Feedback (vibrate), EcoScore-Badge, verbesserte Erfolgsseite mit MHD-Bestaetigung und +5-Punkte-Toast
- Inventar: Client-side Suche (Name/Marke/Kategorie/Lagerort), Sortierung (MHD/Name/Menge), Quick-Consume-Button direkt auf jeder Karte
- Dashboard: Rewards-Karte mit Punktestand, Level, Streak und Fortschrittsbalken zur naechsten Stufe
- Dashboard: Quick-Consume auf ablaufenden Produkten (grüner Checkmark-Button mit Done-Animation)
- Dashboard: Rezeptvorschlaege fuer ablaufende Zutaten — Top-3-Rezepte mit Match-Prozent und Zubereitungszeit
Infrastruktur- app/app/_components/quick-consume-button.tsx: Client Component mit loading/done-State und Router-Refresh
- UserProfile.preferredCategories String[] im Prisma-Schema ergaenzt
- Onboarding-Gate im App-Layout (redirect wenn USER ohne Haushalt und DB erreichbar)
- v0.10.0
Eigene Rezepte, Fork-System & Foto-Galerie (Phase 28)
Nutzer koennen eigene Rezepte erstellen, Systemrezepte anpassen (Fork) und Fotos hochladen. Community-Tab zeigt geteilte Nutzerrezepte. Dreistufiger Wizard (Basisinfos, Zutaten, Schritte & Fotos).
Neu- Dreistufiger Rezept-Wizard: Basisinfos, Zutaten (mit Menge/Einheit), Schritte + Foto-Upload
- Systemrezepte mit einem Klick forken: Anpassen-Button auf jeder Rezept-Karte
- Fork-Badge zeigt bei abgeleiteten Rezepten das Original-Rezept an
- Foto-Slideshow-Galerie auf Rezept-Detailseite (Dot-Indikatoren, Pfeilnavigation)
- Cover-Foto wird automatisch aus dem ersten Upload gesetzt
- Sichtbarkeit: Privat oder Community (mit Lock/Globe-Icon-Toggle)
- Rezepte-Tab-Leiste: Alle Rezepte / Meine Rezepte / Community
- Neues-Rezept-Button in der Rezept-Uebersicht
- Bearbeiten und Loeschen von eigenen Rezepten (mit Bestaetigung)
- Foto-Upload-API unter /api/uploads/recipes (JPEG/PNG/WebP, max. 5 MB)
Infrastruktur- Prisma-Schema: UserRecipe- und RecipePhoto-Modelle, RecipeVisibility-Enum
- domains/recipes/user-recipe.service.ts: CRUD, Fork, Foto-Verwaltung, Cover-Logik
- Docker-Volume recipe_uploads fuer persistente Foto-Speicherung auf dem VPS
- Foto-Dateien liegen unter public/uploads/recipes/ (via Docker-Volume gemountet)
- v0.9.0
Redis-Caching + CO₂-Footprint-Tracking (Phase 26+27)
Redis als Best-Effort-Cache fuer Layout-kritische DB-Queries (Notifications, Haushalte). Neues CO2-Footprint-Feature mit Eco-Score-basierter Klimaberechnung, Wochenchart und grueneren Produktalternativen.
Neu- CO2-Footprint-Seite unter /app/sustainability mit Klimakennzahlen und Eco-Score-Verteilung
- Wochenchart (AreaChart) zeigt geschaetzten CO2-Fussabdruck der letzten 6 Wochen
- Top-5-CO2-Produkte aus dem Vorrat (schlechteste Eco-Scores zuerst)
- Gruenal ternative-Empfehlungen: Kategorie mit besserem Eco-Score, konkretes CO2-Einsparpotenzial
- FoodShare-CO2-Impact: verbrauchte Produkte = vermiedenes CO2
- CO2-Footprint-Eintrag im App-Navigationsmenue (Leaf-Icon)
Infrastruktur- ioredis als Redis-Client (lib/redis/client.ts) mit Singleton und No-op-Stub fuer lokale Entwicklung
- Typisierte Cache-Helfer cached() und invalidate() (lib/redis/cache.ts) mit TTL-Konstanten
- getUnreadCount() cached mit TTL 30s, invalidiert nach markAllRead / deleteAll / createMhd
- getUserHouseholds() cached mit TTL 5min, invalidiert nach Onboarding
- Health + Carbon Cache (TTL 5min) invalidiert nach addInventoryItem / markConsumed / deleteInventoryItem
- domains/carbon/carbon.service.ts: computeCarbonSummary (pure), getCarbonSummary (mit Cache), getCarbonWeeklyTrend
- v0.8.0
Admin & Partner produktiv (Phase 25)
Admin- und Partner-Bereich vollstaendig auf echte DB-Daten umgestellt. Kampagnenwizard speichert direkt in PostgreSQL, Admin-Freigabe schreibt Status zurueck, Werbepartner-Uebersicht zeigt echte Advertiser. Prisma-Schema um Advertiser-User-Link und Campaign-Felder erweitert.
Neu- Partner-Kampagnenwizard: Einreichung speichert jetzt in der DB (Status: REVIEW)
- Admin-Kampagnenfreigabe schreibt ACTIVE/REJECTED zurueck in Campaign-Tabelle
- Werbepartner-Seite zeigt echte Advertisers mit Kampagnen-Statistik
- Admin-Billing: KPI-Karten (Paid-Nutzer, geschaetzter MRR, aktive Kampagnen) aus echter DB
- Admin-Dashboard: ausstehende Kampagnenzahl kommt jetzt aus DB (nicht mehr Mock)
- Partner-Dashboard: Kampagnenliste und Stats aus echten DB-Daten
- Partner-Kampagnendetail: echte Daten aus DB, Anzeigen-Vorschau nutzt gespeicherte Ad-Inhalte
Infrastruktur- Prisma-Schema: Advertiser erhaelt userId-Field (Link zu PARTNER-Nutzer)
- Prisma-Schema: Campaign erhaelt Felder fuer Ziel, Kategorien, Ad-Content, Metriken, submittedAt
- Neuer domains/partner/partner.service.ts mit getPartnerCampaigns, createCampaign, getPartnerStats
- Admin-Service erweitert: getAdminCampaigns, getAdminAdvertisers, getAdminBillingStats
- Server Action createCampaignAction mit Zod-Validierung und Mindestbudget-Check
- v0.7.0
Rewards-Einlösung live + Sentry Error Tracking
Das Rewards-System ist vollstaendig produktiv: Punkte koennen jetzt gegen echte Mock-Gutscheine eingeloest werden. Ausserdem wurde Sentry integriert - alle ungefangenen Client- und Server-Fehler werden ab sofort erfasst (PII-bereinigt).
Neu- Praemien-Einloesung: 'Einloesen'-Button loest echte Punkte aus der DB ab
- Voucher-Modal zeigt generierten Mock-Gutscheincode nach erfolgreicher Einloesung
- Einzel-Code-Kopier-Button mit Clipboard-Feedback
- Serverseitige Balance-Pruefung verhindert Ueberziehen des Punktekontos
- Punktestand nach Einloesung sofort aktualisiert (router.refresh + revalidatePath)
- Gutschein-Format: SP-RECIPE-XXXX-XXXX, SP-PLUS-XXXX-XXXX etc. (Partner-Codes folgen)
Infrastruktur- Sentry v10 (@sentry/nextjs) integriert - Client, Server und Edge Runtime
- PII-Scrubbing: E-Mail, Name und IP werden vor dem Senden entfernt
- Next.js instrumentation.ts - onRequestError fuer Server-Fehler
- withSentryConfig in next.config.ts - Source-Map-Upload vorbereitet
- NEXT_PUBLIC_SENTRY_DSN in .env.example dokumentiert
- Ohne gesetztes SENTRY_DSN laeuft Sentry silent im No-op-Modus
Docs- Roadmap: pwa-offline und rewards-productive als shipped entfernt (waren in 0.5.1/0.5.2 geliefert)
- Roadmap: admin-partner-productive als naechste In-Progress-Phase aufgenommen
- v0.6.1
Auth: Rolle wird bei jedem Request live aus der DB gelesen
Die Benutzerrolle wird nicht mehr nur beim Login in den JWT eingefroren, sondern bei jedem Token-Refresh live aus der DB gelesen. Rollenerhöhungen (z.B. USER -> SUPER_ADMIN) gelten damit sofort beim naechsten Seitenaufruf.
Sicherheit- JWT-Callback in auth.ts liest role bei jedem Refresh aus der DB nach
- Rollenaenderungen (z.B. Admin-Promotion) wirken sofort ohne Logout
- DB-Fehler (Offline) fallen graceful zurueck auf gecachte Rolle
- v0.6.0
Einstellungen: Konto-Info, Anmeldemethode & E-Mail-Verifizierung
In den Einstellungen ist jetzt eine neue Sektion 'Konto & Anmeldung' sichtbar: E-Mail-Adresse (schreibgeschützt), Anmeldemethode (E-Mail/Passwort, Google oder Facebook als Badge) und E-Mail-Bestätigungsstatus mit direktem Resend-Button.
Neu- Neue Sektion 'Konto & Anmeldung' in den Einstellungen (direkt unter dem Profilbild)
- E-Mail-Adresse anzeigen — mit Schloss-Icon, nicht editierbar
- Anmeldemethode als Badge: E-Mail & Passwort, Google oder Facebook
- E-Mail-Bestätigungsstatus: gruenes Bestätigt-Feld mit Datum oder Amber-Warnung mit Resend-Button
- Resend-Button in den Einstellungen — unabhängig vom App-Banner verwendbar
- Nach erfolgreichem Senden: blaues Bestätigungs-Feedback in der Sektion
- v0.5.9
Admin Roadmap-Seite — Projekt-Übersicht im Backend
Neue Admin-Seite /admin/roadmap gibt dem Superadmin jederzeit einen vollständigen Überblick: Roadmap-Items nach Status, zuletzt gelieferte Releases, Backend-Live-Status aller Bereiche und Tech-Stack. Milestone-Icon in der Admin-Navigation.
Neu- Neue Admin-Seite /admin/roadmap: kombinierte Changelog- und Roadmap-Übersicht
- Roadmap-Abschnitte: In Arbeit / Geplant / Ideen mit Kategorie-Badges, Phasennummern, Aufwand
- Changelog-Sidebar: letzte 6 Releases als kompakte Timeline mit Change-Type-Badges
- Backend-Status-Widget: Live-/Mock-Fortschrittsbalken für Admin-, Partner- und Nutzer-Bereich
- Tech-Stack-Übersicht als kompakte Grid-Kacheln
- 5-Felder-Statistikleiste: Versionen shipped, In Arbeit, Geplant, Ideen, Gesamt
- Milestone-Icon in Admin-Sidebar-Navigation unter Analytics
- v0.5.8
Rewards-System produktiv — Welcome-Bonus & Referral
Das Gamification-System ist nun vollständig live: neue Nutzer erhalten +50 Willkommens-Punkte, Referral-Links vergeben automatisch Bonus-Punkte an den Einladenden. Punkte für Scan, Kassenbon, Shopping, Rezepte und FoodShare waren bereits verdrahtet.
Neu- Welcome-Bonus: +50 Punkte werden automatisch nach der Registrierung vergeben
- Referral-System live: /register?ref=CODE erkennt den Einladenden und vergibt +100 Punkte
- Onboarding-Screen zeigt Willkommensbonus-Bestätigung (+50 Punkte)
- Registrierungsformular zeigt Hinweis-Banner bei eingehendem Referral-Link
- Datenschutz-Link im Consent-Block zeigt auf /datenschutz statt #
Infrastruktur- app/register/actions.ts: awardPoints(WELCOME) + getOrCreateReferralCode() fire-and-forget nach User-Create
- Referral: UserProfile.referredBy wird gesetzt, Referrer erhält REFERRAL_SENT-Punkte
- app/register/page.tsx: Suspense-Wrapper + useSearchParams für ?ref= Übergabe via hidden input
- lib/roadmap/entries.ts: email-verification entfernt (shipped), rewards-productive als in-progress markiert
- v0.5.7
E-Mail-Verifizierung & öffentliche Roadmap
Neue Nutzer erhalten nach der Registrierung automatisch eine Bestätigungsmail. Ein Amber-Banner erinnert unbestätigte Accounts. Die öffentliche Roadmap unter /roadmap zeigt alle geplanten Features, Phasen und Ideen.
Neu- E-Mail-Verifizierung: Bestätigungsmail nach Registrierung (24h-gültiger Token)
- Amber-Banner im App-Layout für unbestätigte E-Mail-Adressen
- "Erneut senden"-Button mit Rate-Limiting über vorhandenen Resend-Adapter
- Verifikations-Seite /verify-email?token=… mit Erfolgs- und Fehler-Feedback
- Öffentliche Roadmap-Seite /roadmap mit 14 Einträgen (In Arbeit / Geplant / Ideen)
- Footer-Link auf /roadmap aktiviert
Infrastruktur- Prisma-Schema: neues Modell EmailVerificationToken (id, email, token, expiresAt)
- lib/auth/email-verification.ts: createVerificationToken() + verifyEmailToken()
- lib/roadmap/entries.ts: typisierte Roadmap-Daten mit Status, Priorität, Kategorie, Aufwand
- v0.5.6
DSGVO-Compliance: Datenlöschung, Datenschutz & Impressum
Nutzer können ihr Konto und alle personenbezogenen Daten jetzt selbst vollständig löschen (DSGVO Art. 17). Die Datenschutzerklärung wurde um alle externen Dienste ergänzt. Cookie-Banner, Impressum und Datenschutzseite sind produktiv.
Neu- DSGVO Art. 17 — Konto-Löschung: Einstellungen → Gefahrenzone → Konto unwiderruflich löschen
- Bestätigungsdialog: Nutzer muss 'LÖSCHEN' eintippen, bevor die Aktion ausgeführt wird
- Vollständige Datenlöschung in DB-Transaktion: Profil, Haushalt, Vorrat, Kassenbons, Belohnungen, Marketplace, OAuth-Verbindungen
- Haushalt-Logik: alleinige Eigentümer-Haushalte werden gelöscht, Mitglieder-Memberships werden nur entfernt
- Nach Löschung: automatischer Sign-Out und Weiterleitung zur Startseite
Docs- Datenschutzerklärung um externe Dienste ergänzt: Stripe, Resend, Tabscanner, Google OAuth, Facebook OAuth
- DSGVO Art. 17-Hinweis (Konto-Löschung) in Datenschutzerklärung verlinkt
- Impressum bereits vorhanden und verlinkt
- Cookie-Banner bereits aktiv (nur technisch notwendige Cookies)
- v0.5.5
Auto-Save Einstellungen mit Toast-Feedback
Alle Einstellungen werden jetzt sofort nach einer Änderung automatisch gespeichert — kein Submit-Button mehr nötig. Ein animierter Toast-Indikator unten rechts zeigt Lade-Status, Bestätigung oder Fehlermeldung an.
Neu- Globaler ToastProvider im App-Layout — steht allen App-Seiten zur Verfügung
- Toast-Komponente: 3 Zustände (Laden mit Spinner, Erfolg grün, Fehler rot), animiertes Ein-/Ausblenden
- Auto-Dismiss: Erfolg nach 3 s, Fehler nach 5 s, manuell schließbar
- ProfileForm: Text-Felder speichern beim Verlassen des Feldes (onBlur), Einwilligungs-Checkboxen sofort (onChange)
- HouseholdAppearanceSection: Farbe und Titelbild werden ohne Submit sofort gespeichert
- NotificationSettings: Toggle und Vorlaufzeit-Buttons speichern sofort mit Toast-Feedback
- AvatarSection: inline-Statustext durch Toast ersetzt
- Submit-Buttons in Profil- und Haushalt-Form entfernt
Infrastruktur- autoSaveProfileFields() Server Action für direkten Aufruf ohne FormData-Wrapper
- saveHouseholdAppearanceDirect() Server Action für direkten Aufruf aus dem Client
- v0.5.4
OAuth: Google & Facebook Login / Registrierung
Nutzer können sich jetzt mit ihrem Google- oder Facebook-Konto in einem Klick anmelden oder registrieren. Neue Accounts werden automatisch angelegt und mit dem OAuth-Anbieter verknüpft. Bestehende E-Mail-Konten werden per E-Mail-Adresse zusammengeführt.
Neu- Google OAuth: Login & Registrierung auf Login- und Register-Seite
- Facebook OAuth: Login & Registrierung auf Login- und Register-Seite
- Automatische User-Anlage beim ersten OAuth-Login (kein Passwort nötig)
- Account-Linking: gleiches E-Mail → existierender Account wird verknüpft
- OAuth-Account-Eintrag in der Datenbank (provider + providerAccountId)
- Markierte Social-Buttons mit Google- und Facebook-Brand-Icons
- Ladeindikator pro Button während der OAuth-Weiterleitung
Infrastruktur- GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET in .env dokumentiert
- FACEBOOK_CLIENT_ID / FACEBOOK_CLIENT_SECRET in .env dokumentiert
- allowDangerousEmailAccountLinking aktiviert für nahtloses Account-Merging
- v0.5.3
KI-Wochenplan: Claude generiert 7-Tage-Speiseplan
Plus-Nutzer erhalten einen vollständigen, KI-generierten 7-Tage-Mahlzeitenplan. Claude berücksichtigt Vorratsinhalte, Diätpräferenzen, Budget und Lieblingsküche. Fehlende Zutaten lassen sich mit einem Klick zur Einkaufsliste hinzufügen. Ohne API-Key greift ein deterministischer Fallback-Plan auf Mock-Rezepte zurück.
Neu- KI-Wochenplan via Claude (claude-haiku-4-5): 7 Tage × 3 Mahlzeiten
- Frühstück, Mittagessen, Abendessen mit Zutaten, Kalorien und Zubereitungszeit
- Inventory-Abgleich: inStock-Badge pro Zutat, Gesamtfortschrittsbalken
- Fehlende Zutaten per Klick zur Einkaufsliste hinzufügen (tage- oder wochenweise)
- Präferenz-Steuerung: Personen, Budget, Diät, Küche
- Deterministischer Fallback-Plan (Mulberry32-RNG) ohne API-Key
- Speicherung im DB-Modell MealPlan (upsert pro User)
- Plan-Gate: Freie Nutzer sehen Upgrade-Prompt, kein Zugang zum KI-Planer
- Navigation: Wochenplan in Seitenleiste und Mehr-Menü
- v0.5.2
PWA: App installierbar, Service Worker, Offline-Modus
StockPilot ist jetzt als Progressive Web App installierbar. Auf Android erscheint automatisch ein Installieren-Banner. Statische Assets werden gecacht, bei fehlender Verbindung erscheint eine saubere Offline-Seite. App-Icon in Brand-Grün generiert Next.js automatisch.
Neu- App installierbar: Web App Manifest vollständig (id, lang, shortcuts, screenshots)
- Service Worker: Cache-First für _next/static und Icons, Network-First für Seiten
- Offline-Fallback: saubere /offline.html bei fehlender Verbindung
- Installieren-Banner (Android/Chrome): beforeinstallprompt — verschwindet nach Wahl oder Dismiss
- App-Icon 512×512 und Apple-Icon 180×180 per Next.js ImageResponse — kein externes Tool nötig
- Theme-Color korrigiert: #16a34a (Brand-Grün) statt #5a3d27
- iOS Add-to-Home-Screen: apple-mobile-web-app-capable bereits gesetzt
- v0.5.1
Rewards: Punkte-Vergabe jetzt live
Das Rewards-System ist vollständig produktiv: Punkte werden bei echten Aktionen automatisch vergeben, Streaks werden täglich aktualisiert, Achievements werden automatisch entsperrt. Die Rewards-Seite zeigt echte DB-Daten aus bisherigen Aktivitäten.
Neu- Punkte-Vergabe bei Kassenbon-Import (+10 Punkte)
- Punkte-Vergabe bei Produkt verbraucht/gerettet (+3 Punkte)
- Punkte-Vergabe beim Abhaken von Einkaufslisten-Positionen (+2 Punkte)
- Barcode-Scan (+5 Punkte) und Rezept-Fehlende-Zutaten (+3 Punkte) waren bereits verdrahtet
- Streak-Tracking: täglich bei jeder Punktevergabe automatisch aktualisiert
- 7-Tage-Streak (+25 Bonus) und 30-Tage-Streak (+100 Bonus) automatisch ausgelöst
- Achievement-Unlock automatisch nach Erreichen von Meilensteinen (erster Scan, 5/25 Scans, erster Bon, 1k/3k Punkte, 7/30 Streak, Referral)
- Rewards-Seite zeigt echten Punktestand, Level, Streak, Errungenschaften und Transaktionshistorie
- v0.5.0
Preisintelligenz: echte Daten, Marktvergleich & Alarme
Die Preisbeobachtungs-Seite läuft jetzt auf echten Kassenbon-Daten statt Mock. Preistrends werden aus persönlichen Kassenbons berechnet, Marktvergleiche zeigen welcher Händler am günstigsten ist, Preisalarme werden in der DB gespeichert und der CSV-Export ermöglicht DSGVO-konformen Datenabzug.
Neu- Preisseite als Server Component — echte Daten aus ReceiptLineItem + ProductPriceObservation
- Monatliche Preishistorie pro Produkt mit recharts-Liniendiagramm
- Marktvergleich: welcher Händler ist für ein Produkt am günstigsten (aus Kassenbons)
- Preisalarm: Schwellenwert setzen, in DB persistieren, visuell anzeigen wenn ausgelöst
- Alarm-Referenzlinie im Chart als grüne gestrichelte Linie
- CSV-Export persönlicher Preishistorie (DSGVO Art. 20 — Datenübertragbarkeit)
- Empty-State wenn noch keine Kassenbons eingescannt wurden (kein Crash)
- Triggered-Alarme-Banner wenn Preis unter Schwellenwert gefallen
- Consent-Hinweis: unterscheidet zwischen persönlicher und aggregierter Nutzung
Infrastruktur- Neues PriceAlert-Modell in Prisma-Schema (userId, productName, targetPrice, unit, active)
- User-Relation priceAlerts[] hinzugefügt
- modules/prices/price.service.ts — Preisaggregation, Trendberechnung, Marktvergleich, CSV-Builder
- app/app/prices/actions.ts — createPriceAlertAction, deletePriceAlertAction, exportPriceCsvAction
- v0.4.3
Rezept-Schritte: Mengen & Equipment-Trenner
In den Zubereitungsschritten werden jetzt die konkreten Mengen jeder Zutat angezeigt. Zutaten und Equipment sind optisch durch einen Trennstrich getrennt. Mengen skalieren mit dem Portionenregler.
Neu- Zutatenchips in Schritten zeigen jetzt Menge + Einheit (z. B. "200 g Mehl")
- Mengen skalieren automatisch mit dem Portionenregler
- Trennlinie (<hr>) zwischen Zutaten-Chips und Equipment-Chips
- Zubereitung in Client-Komponente verschoben — Portionsskalierung greift jetzt auch in den Schritten
- Mengenangabe in Fettschrift, Zutatname normal — bessere Lesbarkeit
- v0.4.2
Changelog: Uhrzeit (Berliner Zeit)
Jeder Changelog-Eintrag zeigt jetzt zusätzlich zum Datum die exakte Uhrzeit in Berliner Zeit an.
Neu- Changelog-Einträge zeigen Datum + Uhrzeit in Berliner Zeit (Europe/Berlin)
- Uhrzeit wird in Monospace-Schrift neben dem Datum dargestellt
- Alle bisherigen Einträge mit exakten Git-Commit-Zeitstempeln versehen
- date-Feld in ChangelogEntry verwendet volle ISO-8601-Datetimes statt YYYY-MM-DD
- v0.4.1
Bugfix: Profilbild-Upload
Profilbild wird jetzt zuverlässig gespeichert und nach Seitenreload wieder angezeigt.
Bugfix- Avatar-Upload: FormData/Hidden-Input-Ansatz durch direkten Server-Action-Aufruf ersetzt — kein Datenverlust mehr bei React-Re-Render zwischen Dateiauswahl und Submit
- try/catch schluckt keine Next.js-Redirect-Fehler mehr (NEXT_REDIRECT wird korrekt weitergegeben)
- Optimistisches Preview mit Rollback: bei Speicherfehler wird das alte Bild wiederhergestellt
- Auto-Save beim Dateiauswählen — kein separater Speichern-Button mehr nötig
- Lade-Spinner direkt auf dem Avatar-Kreis während des Speichervorgangs
- Fehlerresistente Canvas-Resize-Funktion mit expliziten onerror-Callbacks
- v0.4.0
Stripe Billing & Kassenbon-OCR
Vollständige Abo-Integration mit Free/Plus/Family-Plänen, Kassenbon-Scan via Tabscanner-OCR und robustes CI/CD-Deployment.
Neu- Stripe Billing: Free / Plus (2,99 €/Monat) / Family (5,99 €/Monat) Pläne
- Feature-Gating: Inventory-Limit und monatliches Bon-Kontingent je Plan
- Upgrade-Banner (soft / hard) wenn Limits erreicht oder annähernd erreicht
- Billing-Einstellungsseite mit Plan-Vergleich, Upgrade-Buttons und Stripe Portal
- Stripe Webhook-Handler für automatische Plan-Aktivierung nach Zahlung
- Kassenbon-OCR via Tabscanner (100 Bons/Monat kostenlos, kein Credit Card)
- OCR-Provider wählbar via ENV: mock | mindee | tabscanner
Infrastruktur- GitHub Actions CI/CD: git archive | ssh statt git pull — Server braucht keine GitHub-Credentials
- deploy.sh: --force-recreate stellt sicher, dass ENV-Änderungen sofort wirksam werden
- Neuer --env-only Modus: Container-Neustart ohne Build in ~10 Sekunden
- pg_isready-Healthcheck ersetzt blindes sleep 5
- Sanity-Check warnt bei nicht gesetzten Pflicht-Secrets
- Aktive Konfiguration wird nach jedem Deploy im Log ausgegeben
Bugfix- Stripe SDK v22: API-Version auf 2026-04-22.dahlia aktualisiert
- Build-sicherer Placeholder-Key verhindert Crash wenn STRIPE_SECRET_KEY nicht gesetzt
- .gitattributes: LF-Zeilenenden erzwungen (Windows/CRLF-Deploymentfehler behoben)
- v0.3.0
Admin, E-Mail & CI/CD
Vollständiger Admin-Bereich, Passwort-Reset via E-Mail (Resend) und automatisches Deployment über GitHub Actions.
Neu- Admin-Dashboard: Nutzer-, Haushalts- und Kampagnenverwaltung
- Passwort vergessen / Passwort zurücksetzen (Anti-Enumeration-sicher)
- Welcome-E-Mail nach Registrierung
- Resend E-Mail-Adapter (100 E-Mails/Tag kostenlos)
- Audit-Log für sensible Admin-Aktionen
- Infografik: StockPilot-Plattformüberblick
Infrastruktur- GitHub Actions: TypeCheck + Lint als Quality Gate vor jedem Deploy
- deploy.sh: prisma db push statt migrate deploy (kein migrations-Ordner benötigt)
- Docker Compose Produktions-Setup mit Traefik, SSL (Let's Encrypt) und Redis
- VPS-Deployment auf IONOS (eprojekt.cloud) erstmalig live
- v0.2.0
Core-App: Vorrat, Scan, Rezepte & mehr
Vollständige Kern-App mit Vorratsverwaltung, Barcode-Scan, Einkaufsliste, Rezeptvorschlägen, Health-Scoring und FoodShare.
Neu- Vorratsverwaltung mit MHD-Tracking und Statusbadges
- Barcode-Scan (Browser-Kamera) mit Open Food Facts Adapter
- Kassenbon-Upload mit Mock-Parser und Line-Item-Korrektur
- Einkaufsliste mit smarten Vorschlägen und Pantry-Staples
- Rezeptvorschläge basierend auf vorhandenem Vorrat
- Health-Scoring mit Ampelsystem (informativ, keine medizinischen Versprechen)
- FoodShare: Produkte zum Teilen markieren, Impact-Counter, aggregierte Heatmap
- Preisintelligenz: Preisverläufe und Marktvergleiche
- Punkte & Prämien: Aktionspunkte und Einlösung
- Marktplatz für Haushaltsgegenstände
- Werbepartner-Dashboard: Kampagnen, Angebote, Berichte
- Push-Benachrichtigungen für MHD-Warnungen
- Dark Mode (systemfolgende und manuelle Umschaltung)
Infrastruktur- Prisma-Schema mit allen Domänenmodellen
- NextAuth v5 mit RBAC (USER, PARTNER, ADMIN, SUPER_ADMIN)
- Redis für Session-Caching
- Avatar, Haushalt-Farbauswahl und Cover-Bild
- v0.1.0
UI-Shell, Landingpage & Auth
Initiales Setup mit Designsystem, Marketing-Seiten, Authentifizierung und App-Shell für alle drei Bereiche.
Neu- Designsystem: Tailwind v4, brand/accent Farbpalette, shadcn/ui-ready
- Landingpage mit Hero, Features, Preismodell und FAQ
- Login, Registrierung und Onboarding-Flow
- App-Shell mit responsiver Sidebar (Desktop) und Bottom-Nav (Mobile)
- Avatar-Dropdown mit Haushalt-Switcher und Darkmode-Toggle
- Datenschutz- und Impressum-Seiten (DSGVO)
- Cookie-Banner (Privacy-by-Design)
- Marketing-Footer mit Spaltennavigation
Infrastruktur- Next.js 15 App Router, TypeScript strict, Prisma 7, PostgreSQL
- Docker Compose Dev-Setup
- Mock-Adapter für alle externen APIs (Produkte, Bons, Billing, E-Mail)