Spaces:
Running
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 aufhttps://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)
- 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).
- 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.
- Kein Toxin-Scoring (PFAS/Mikroplastik/Schwermetalle à la Oasis) — dafür gibt es keine offenen Daten. Nicht andeuten, nicht simulieren.
- Kein TC/Economy-Bezug: Der Produkt-Scan ist reines Info-Feature. Kein
ai_status, kein Submit-Pfad, keine Wallet-Berührung. - 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:
<CameraView
barcodeScannerSettings={{ barcodeTypes: ['ean13', 'ean8', 'upc_a', 'upc_e'] }}
onBarcodeScanned={({ data }) => onScan(data)}
/>
- Debounce: gleiche Barcode-Nummer max. 1× pro ~3 s (
onBarcodeScannedfeuert mehrfach/Sekunde). Nach erfolgreichem Scan kurz haptisches Feedback + Scanning pausieren, bis die Karte geschlossen wird. - Call:
GET {BASE_URL}/v1/product/{data}— gleicherx-api-key-Header wie künftig überall. Immer HTTP 200 (400 nur bei Nicht-Barcode-Strings); branchen ausschließlich aufresponse.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!) mitlabel_en, optionalshape(bereinigt:en:-Präfix strippen, Bindestriche → Leerzeichen). - Darunter
disposal_hint_enals 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 aufhttps://world.openfoodfacts.org/additive/{code}(externe Quelle urteilt, nicht wir). - ingredients_analysis: Chips; Werte können
maybe-veganetc. 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 *_<lang>-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)
{
"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.