# Produkt-Scan — UI-Spezifikation für den Mobile-Agenten > **Von:** Vision-Agent · **Stand:** 2026-07-07 · **Founder-Go liegt vor.** > API ist **fertig und live** (`GET /v1/product/{barcode}`, v2.1.x auf > `https://alami-eco-alami-vision-api.hf.space`). Dieses Dokument ist die > vollständige Umsetzungs-Spec: Flow, Karten-Layout, Render-Regeln pro Feld, > und die bewussten Grenzen, die wir mit dem Founder besprochen haben. --- ## 0. Produkt-Entscheidungen (Kontext, damit du weißt WARUM) 1. **Positionierung:** Alami beantwortet „Was macht das Produkt mit der Welt — und wohin damit nach Gebrauch?" Das ist unser Alleinstellungsmerkmal (Yuka = Gesundheit, Oasis = Toxine — beide zeigen NICHT Entsorgung/Umwelt-Kreislauf). 2. **Gesundheits-Basics zeigen wir GRATIS mit** (Nutri-Score, NOVA, Zusatzstoffe) — das holt preisbewusste Yuka-Nutzer ab. **ABER: wir zeigen nur offizielle Schemata an, wir bewerten nie selbst** (Haftung! Yuka wurde für eigene Risiko-Einstufungen verklagt). Also: keine Texte wie „gefährlich", „krebserregend", „schädlich" aus unserer Feder — nur amtliche Grades + Rohlisten. 3. **Kein Toxin-Scoring** (PFAS/Mikroplastik/Schwermetalle à la Oasis) — dafür gibt es keine offenen Daten. Nicht andeuten, nicht simulieren. 4. **Kein TC/Economy-Bezug:** Der Produkt-Scan ist reines Info-Feature. Kein `ai_status`, kein Submit-Pfad, keine Wallet-Berührung. 5. **UI-Vorbild:** Oasis-Karten-Pattern (großer Score oben, aufklappbare Detail-Zeilen mit Ampel-Punkten darunter) — bewährt, Nutzer kennen es. --- ## 1. Einstieg & Scan-Flow - **Modus-Toggle im bestehenden Kamera-Screen:** `🗑️ Trash | 🛒 Product` (App ist englisch → englische Labels, siehe §5 i18n). - Im Produkt-Modus: **Stufe-A-Preview-Loop pausieren** (keine parallelen `/v1/analyze`-Calls) und Barcode-Scanning aktivieren: ```tsx onScan(data)} /> ``` - **Debounce:** gleiche Barcode-Nummer max. 1× pro ~3 s (`onBarcodeScanned` feuert mehrfach/Sekunde). Nach erfolgreichem Scan kurz haptisches Feedback + Scanning pausieren, bis die Karte geschlossen wird. - **Call:** `GET {BASE_URL}/v1/product/{data}` — gleicher `x-api-key`-Header wie künftig überall. Immer HTTP 200 (400 nur bei Nicht-Barcode-Strings); **branchen ausschließlich auf `response.status`**. ## 2. Die Produkt-Karte (Bottom-Sheet, wie euer Tag-Sheet) Reihenfolge von oben nach unten — bewusst: **Umwelt zuerst** (unsere Marke), Gesundheit als Zusatz, Entsorgung als Alami-Unikat prominent: ``` ┌──────────────────────────────────────────┐ │ [Bild] Coca-Cola │ ← product.name + brand + image_url │ Coca-Cola · 33 cl │ ← quantity │ │ │ ENVIRONMENT │ │ ◯ Eco-Score: C (ampel-farbig) │ ← sustainability.ecoscore_grade │ 🏷 made-in-the-eu · triman │ ← sustainability.labels (Chips, max ~5) │ │ │ DISPOSAL — the Alami special │ │ ▢ Metal · drink can │ ← packaging[]: Chip in .color, label_en │ ♻️ Metal/packaging recycling. │ ← disposal_hint_en │ Deposit cans: return to store. │ │ ~15 g if littered │ ← litter_weight_estimate_g (optional) │ │ │ HEALTH BASICS (official schemes) │ │ ◯ Nutri-Score: E (ampel-farbig) │ ← health.nutriscore_grade │ ▸ Processing: NOVA 4 — ultra-processed │ ← health.nova_group (Mapping §3.3) │ ▸ Additives: 2 (e150d, e338) │ ← health.additives_count + Liste aufklappbar │ ▸ vegan? maybe · palm-oil-free ✓ │ ← health.ingredients_analysis │ │ │ Data: Open Food Facts — ODbL [link] │ ← attribution — PFLICHT, immer sichtbar └──────────────────────────────────────────┘ ``` ## 3. Render-Regeln pro Feld ### 3.1 Eco-Score & Nutri-Score (beide als Ampel-Kreis) | Grade | Farbe | |---|---| | a | `#1fa363` dunkelgrün | | b | `#8bc34a` hellgrün | | c | `#f9a825` gelb | | d | `#ef6c00` orange | | e | `#d32f2f` rot | | `null` / `"not-applicable"` / `"unknown"` | grauer Kreis + Text **"No data"** — ehrlich zeigen, nie verstecken, nie raten | ### 3.2 Verpackung (`packaging[]`) - Pro Eintrag ein **Chip in `color`** (unsere Materialfarben, identisch zu den Kamera-Overlays!) mit `label_en`, optional `shape` (bereinigt: `en:`-Präfix strippen, Bindestriche → Leerzeichen). - Darunter `disposal_hint_en` als Fließtext. - `litter_weight_estimate_g`: optional als „~15 g if littered" — kleine, aber einzigartige Alami-Note. - `packaging == []` → Zeile „No packaging data yet". ### 3.3 Health-Block — NUR anzeigen, nie werten - **Nutri-Score:** Ampel wie §3.1. Untertitel exakt: *"Nutri-Score (official EU scheme)"* — macht klar, dass es nicht unsere Bewertung ist. - **NOVA** (`health.nova_group`), neutrales Wording: - 1 → "unprocessed / minimally processed" - 2 → "processed culinary ingredients" - 3 → "processed food" - 4 → "ultra-processed" - `null` → Zeile weglassen - **Zusatzstoffe:** `Additives: {additives_count}` + aufklappbare Liste der E-Nummern (`health.additives`). **Keine eigenen Risiko-Farben/-Urteile** — neutral grau. Optional pro E-Nummer ein Link auf `https://world.openfoodfacts.org/additive/{code}` (externe Quelle urteilt, nicht wir). - **ingredients_analysis:** Chips; Werte können `maybe-vegan` etc. sein → als "vegan?" mit Fragezeichen rendern, `*-free`/bestätigte als ✓. ### 3.4 Status-UX (`response.status`) | status | UI | |---|---| | `found` | Karte wie oben | | `not_found` | "Product not in the database yet." + Button **"Add it on Open Food Facts"** (Link `https://world.openfoodfacts.org/`) — Goodwill + die DB wächst | | `unavailable` | "Service temporarily unreachable." + Retry-Button. Niemals blockieren/crashen | ### 3.5 Attribution — nicht optional `attribution.text` + `attribution.url` **immer sichtbar** auf der Karte (Fußzeile reicht). Das ist ODbL-Lizenzpflicht, kein Nice-to-have. ## 4. Latenz & Verhalten - Erster Lookup ~0,5–1,5 s (Upstream) → Skeleton/Spinner in der Karte. - Danach 24 h serverseitig gecacht → Wiederholungs-Scans schnell. - Ihr müsst **nichts loggen** — Server schreibt anonyme Scan-Statistik (Barcode+Status, bewusst ohne user_id). **Keine User-Daten mitschicken.** ## 5. i18n Alle Anzeige-Felder kommen **doppelt**: `label_en`/`label_de`, `disposal_hint_en`/`disposal_hint_de`. **App ist englisch → `*_en` verwenden.** Deutsch liegt für die Mehrsprachigkeit bereit (per Geräte-Locale wählen); weitere Sprachen kommen später als zusätzliche `*_`-Felder (additiv). Statische UI-Texte dieses Features (Section-Header, Status-Meldungen) bitte gleich in euer i18n-System, nicht hardcoden. ## 6. Beispiel-Response (echt, live getestet: Coca-Cola 5449000000996) ```json { "status": "found", "found": true, "barcode": "5449000000996", "source": "openfoodfacts", "product": { "name": "coca-cola", "brand": "Coca-Cola", "quantity": "33 cl", "image_url": "https://images.openfoodfacts.org/…/front_en.1035.200.jpg" }, "sustainability": { "ecoscore_grade": "not-applicable", "ecoscore_score": null, "labels": ["made-in-the-eu", "fr:triman"] }, "health": { "nutriscore_grade": "e", "nova_group": 4, "additives_count": 2, "additives": ["e150d", "e338"], "ingredients_analysis": ["palm-oil-free", "maybe-vegan", "maybe-vegetarian"] }, "packaging": [ { "raw": "en:aluminium", "shape": "en:drink-can", "bucket": "metal", "label_en": "Metal", "label_de": "Metall", "color": "#64748b", "disposal_hint_en": "Metal/packaging recycling. Deposit cans: return to store.", "disposal_hint_de": "Gelber Sack / Gelbe Tonne. Pfanddosen: Rückgabe im Handel.", "litter_weight_estimate_g": 15.0 } ], "attribution": { "text": "Daten: Open Food Facts — Open Database License (ODbL)", "url": "https://world.openfoodfacts.org" } } ``` ## 7. Explizit NICHT bauen (besprochen & entschieden) - ❌ eigene Gesundheits-/Risiko-Scores oder Warntexte („harmful", „toxic", …) - ❌ Toxin-/PFAS-/Mikroplastik-Anzeigen (keine Datenbasis) - ❌ Kopplung an TC/Economy/Submit-Pfad - ❌ Attribution weglassen oder verstecken ## 8. Später (nur Ausblick, nichts bauen) - P3: „Found in real cleanups: n×" pro Marke (Brand Radar, geparkt) - P4: kombinierter Alami-Score + Premium/B2B - Regionale Entsorgungsregeln (Region-Tabelle serverseitig) Fragen → an den Vision-Agenten. Referenzen: `docs/api.md`, `docs/PRODUCT_SCAN_VISION.md` (Konzept/Strategie), `docs/MOBILE_AGENT_HANDOFF.md` §4d.