feat: implement advanced tagging system, tag weighting, and app focus refactoring
- Implemented reusable TagSelector component with i18n support - Added tag weighting system (popularity scores 1-5) - Created admin panel for tag management - Integrated Nebius AI and Brave Search for 'Magic Scan' - Refactored app focus: removed bottle status, updated counters, and displayed extended bottle details - Updated i18n for German and English - Added database migration scripts
This commit is contained in:
114
.nebiusbravetasks
Normal file
114
.nebiusbravetasks
Normal file
@@ -0,0 +1,114 @@
|
||||
# IMPLEMENTIERUNGS-PLAN: Whisky Scanner App
|
||||
## Stack: Next.js | Supabase | Nebius AI | Brave Search | Coolify
|
||||
|
||||
---
|
||||
|
||||
### 1. SICHERHEIT & INFRASTRUKTUR (Fundament)
|
||||
|
||||
**Ziel:** Sicherstellen, dass keine API-Keys leaken und keine User-Daten direkt an US-Anbieter fließen.
|
||||
|
||||
- [ ] **Environment Variablen säubern**
|
||||
- Prüfe deine `.env` Datei.
|
||||
- [ ] `NEBIUS_API_KEY`: Darf NICHT mit `NEXT_PUBLIC_` beginnen.
|
||||
- [ ] `BRAVE_API_KEY`: Darf NICHT mit `NEXT_PUBLIC_` beginnen.
|
||||
- [ ] `SUPABASE_SERVICE_ROLE_KEY`: Darf NICHT mit `NEXT_PUBLIC_` beginnen (für Admin-Schreibrechte).
|
||||
- [ ] `NEXT_PUBLIC_SUPABASE_ANON_KEY`: Darf öffentlich sein (nur für RLS Lesezugriffe).
|
||||
|
||||
- [ ] **Server-Side Architektur erzwingen**
|
||||
- Stelle sicher, dass alle Aufrufe zu Nebius und Brave ausschließlich über **Server Actions** (`'use server'`) oder **API Routes** (`app/api/...`) laufen.
|
||||
- *Test:* Öffne die Entwicklertools im Browser (Netzwerk-Tab). Beim Scannen darf KEIN Aufruf zu `api.brave.com` oder `api.studio.nebius.ai` sichtbar sein. Nur Aufrufe zu deinem eigenen Backend (localhost/deine-domain).
|
||||
|
||||
- [ ] **Supabase Admin Client einrichten**
|
||||
- Erstelle eine Utility-Datei (z.B. `lib/supabase-admin.ts`), die `createClient` mit dem `SUPABASE_SERVICE_ROLE_KEY` initialisiert.
|
||||
- Nutze diesen Client NUR in Server Actions für das Schreiben in den globalen Cache.
|
||||
|
||||
---
|
||||
|
||||
### 2. NEBIUS AI STUDIO (Das "Auge")
|
||||
|
||||
**Ziel:** Bildanalyse und Extraktion strukturierter Daten für ca. 0,03 Cent pro Bild.
|
||||
|
||||
- [ ] **OpenAI SDK konfigurieren**
|
||||
- Installiere das SDK: `npm install openai`
|
||||
- Initialisiere den Client in `lib/ai-client.ts`:
|
||||
```typescript
|
||||
import { OpenAI } from "openai";
|
||||
export const aiClient = new OpenAI({
|
||||
baseURL: "[https://api.studio.nebius.ai/v1](https://api.studio.nebius.ai/v1)",
|
||||
apiKey: process.env.NEBIUS_API_KEY,
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Prompt Engineering (JSON Mode)**
|
||||
- Erstelle den Prompt für das Modell `Qwen/Qwen2.5-VL-72B-Instruct` (oder Qwen2-VL-72B).
|
||||
- Anweisung: "Extrahiere: Distillery, Name/Edition, Age/Vintage, ABV. Formatiere als reines JSON."
|
||||
- WICHTIG: Setze `response_format: { type: "json_object" }` im API-Call, damit du valides JSON erhältst.
|
||||
|
||||
- [ ] **Such-Query Generierung**
|
||||
- Lass die AI zusätzlich ein Feld `search_string` generieren.
|
||||
- Format-Vorgabe an AI: `"site:whiskybase.com [Distillery] [Name] [Vintage]"`
|
||||
- *Grund:* Das spart Logik im Code, die AI weiß am besten, was auf dem Etikett wichtig ist.
|
||||
|
||||
Bitte für den Adminuser einen Schalter zwischen Gemini und Nebius implementieren. Idealerweise im Magic Scan Formular.
|
||||
---
|
||||
|
||||
### 3. BRAVE SEARCH API (Der "Notfall-Plan")
|
||||
|
||||
**Ziel:** Finden der Whiskybase-ID, wenn der Cache leer ist (Prepaid, keine Fixkosten).
|
||||
|
||||
- [ ] **Fetch-Funktion bauen**
|
||||
- Erstelle eine Server-Funktion, die Brave aufruft.
|
||||
- URL: `https://api.search.brave.com/res/v1/web/search?q=...`
|
||||
- Header: `X-Subscription-Token: process.env.BRAVE_API_KEY`
|
||||
|
||||
- [ ] **Ergebnis-Parser implementieren**
|
||||
- Nimm das erste Ergebnis (`results[0]`).
|
||||
- Prüfe per Regex, ob der Link valide ist: `whiskybase.com/whiskies/whisky/([0-9]+)/...`
|
||||
- Extrahiere die ID (z.B. "12345").
|
||||
|
||||
- [ ] **Fallback-Logik**
|
||||
- Wenn Brave nichts findet (array leer), gib einen Fehler zurück oder markiere das Produkt als "Manuelle Prüfung nötig".
|
||||
|
||||
---
|
||||
|
||||
### 4. DATENBANK & CACHING (Die "Spar-Maschine")
|
||||
|
||||
**Ziel:** Suchkosten minimieren und Datenqualität sichern.
|
||||
|
||||
- [ ] **Datenbank-Schema (Tabelle `global_products`)**
|
||||
- `id`: uuid (PK)
|
||||
- `wb_id`: text (Whiskybase ID, unique)
|
||||
- `full_name`: text (z.B. "Lagavulin 16")
|
||||
- `search_vector`: tsvector (Für unscharfe Suche!)
|
||||
- `image_hash`: text (Optional, falls du Hash-Vergleiche machst)
|
||||
- `created_at`: timestamp
|
||||
|
||||
- [ ] **Row Level Security (RLS) Policies**
|
||||
- Tabelle `global_products`:
|
||||
- Policy "Enable Read Access for all users": `true` (für SELECT).
|
||||
- Policy "Disable Insert/Update for users": `false` (für INSERT/UPDATE).
|
||||
- *Grund:* Nur dein Server (Service Role) darf hier schreiben, um "Cache Poisoning" durch User zu verhindern.
|
||||
|
||||
- [ ] **Der "Main Loop" (Server Action)**
|
||||
1. **AI:** Bild an Nebius -> JSON erhalten.
|
||||
2. **DB Check:** Suche in `global_products` mit `.textSearch('search_vector', ai_name)`.
|
||||
3. **Entscheidung:**
|
||||
- *Treffer:* Nimm ID aus DB (Kosten: 0€). Return an Client.
|
||||
- *Kein Treffer:* Rufe Brave Search auf (Kosten: 0,3 Cent).
|
||||
4. **Cache Write:** Wenn Brave erfolgreich war, nutze `supabaseAdmin`, um den neuen Whisky in `global_products` zu speichern.
|
||||
|
||||
---
|
||||
|
||||
### 5. DSGVO / PRIVACY CHECKLISTE
|
||||
|
||||
**Ziel:** Rechtssicherer Betrieb in der EU.
|
||||
|
||||
- [ ] **Data Minimization**
|
||||
- Schicke an Brave NUR den Suchstring (z.B. "Lagavulin 16").
|
||||
- Schicke NIEMALS User-IDs, E-Mails oder IP-Adressen im Header oder Body an Brave.
|
||||
|
||||
- [ ] **Proxy-Check**
|
||||
- Bestätige nochmals, dass Brave nur die IP deines Hetzner-Servers sieht, nie die des Endnutzers (siehe Punkt 1).
|
||||
|
||||
- [ ] **Nebius Region**
|
||||
- Prüfe im Nebius Dashboard, dass dein Projekt in der Region **eu-north1** (Finnland) oder einer anderen EU-Region läuft, falls wählbar.
|
||||
Reference in New Issue
Block a user