264 lines
18 KiB
Markdown
264 lines
18 KiB
Markdown
# App-Aufbau – Screens, Navigation, Datenflüsse
|
||
|
||
**Stand:** 28. Juli 2026
|
||
**Zweck:** Beschreibt, wie die App aufgebaut sein muss, damit die Funktionen aus `konzept-bilder-feed.md` und `projekt-uebersicht.md` zusammenpassen. Grundlage für die Umsetzung – der Etappenplan steht in `programmier-plan.md`.
|
||
**Bezug:** Prototyp `prototyp-app.html` im Repo `git.webklar.com/knso/videogen` (nur Handy-Ansicht; die Desktop-Adaption ist noch nicht gültig).
|
||
|
||
---
|
||
|
||
## 1. Getroffene Grundentscheidungen
|
||
|
||
| Thema | Entscheidung |
|
||
|---|---|
|
||
| Stack | **Expo / React Native** – eine Codebase für Web und native. Zahlung über die Web-App (App-Store-Abgabe umgehen) |
|
||
| Bottom-Navigation | **drei Tabs: Feed · ➕ · Profil** |
|
||
| Social Graph | **ja** – Nutzer können einander folgen, fremde Profile ansehen |
|
||
| Fremdes Profil zeigt | **nur veröffentlichte Posts** – keine Modelle, keine Ordner, keine Statistiken |
|
||
| Kopieren | **eigener Kopier-Screen** mit Slot-Chips, erst danach Create |
|
||
| Konto-Modell | **ein Konto = eine Brand** (Appwrite-Team), kein Brand-Umschalter |
|
||
| Einstieg der Umsetzung | **Fundament zuerst** – Schema, Auth, Navigationsgerüst |
|
||
|
||
---
|
||
|
||
## 2. Drei Prinzipien, aus denen sich fast alles ableitet
|
||
|
||
### 2.1 Generierung ist immer asynchron
|
||
|
||
Kein Button darf auf ein Ergebnis warten. Jede KI-Aktion legt eine Zeile in `jobs` an, das UI abonniert den Realtime-Kanal und rendert den Fortschritt. Das ist keine Optimierung, sondern eine Notwendigkeit: eine Bildkette sind drei bis fünf Generierungen, ein Video dauert Minuten.
|
||
|
||
**Konsequenz für den Aufbau:** Es braucht einen **globalen Job-Bereich**, der screenübergreifend sichtbar ist – im Prototyp existiert er nicht. Wer während der Generierung wegnavigiert, muss das Ergebnis wiederfinden. Dafür ist der Entwürfe-Screen zuständig.
|
||
|
||
> Der Prototyp täuscht hier: dort ist „Bestätigen & 4 Videos generieren" ein direkter Screenwechsel (`prototyp-app.html:820`). Genauso „Modell generieren" (`:911`) und „Neue Versionen generieren" (`:970`). Alle drei sind in Wahrheit Wartezustände.
|
||
|
||
### 2.2 Der aktive Ordner ist globaler Zustand
|
||
|
||
Der Ordner bestimmt, welches Wissen in den Prompt wandert (`konzept-bilder-feed.md` §9). Er wird **vor** der Generierung gewählt und gilt, bis er gewechselt wird. Damit ist er kein Bildschirm-lokaler Wert, sondern App-Zustand – vergleichbar mit dem aktiven Konto.
|
||
|
||
**Konsequenz:** Der aktive Ordner gehört sichtbar in die Kopfzeile des Erstellen-Bereichs, nicht in ein Untermenü. Sonst generiert der Nutzer im falschen Scope und versteht nicht, warum das Ergebnis anders aussieht als erwartet.
|
||
|
||
### 2.3 Es gibt genau eine öffentliche Grenze
|
||
|
||
Alles ist privat, außer `posts` mit `sichtbarkeit = oeffentlich` – und von denen nur die Bilder, `slot_summary`, `werbetext`, `nische` und `feed_score`.
|
||
|
||
| Öffentlich | Privat |
|
||
|---|---|
|
||
| veröffentlichte Posts (Bilder, Slot-Chips, Werbetext) | `posts.prompt_sent` 🔒 |
|
||
| Anzeigename, Avatar, Nische, Followerzahl | Ordner – **immer** |
|
||
| Modell-Namen als **Beschriftung** im Kopier-Screen | Modelle als nutzbare Assets, Referenzbilder, Einwilligungen |
|
||
| | `attribute_scores`, `rules`, Knowledge Base, Entwürfe, Metriken |
|
||
|
||
**Diese Grenze muss auf Datenbank-Ebene durchgesetzt werden, nicht im UI.** Appwrite-Zeilenrechte pro Team; die öffentliche Lesbarkeit wird beim Veröffentlichen als Permission auf die Zeile gesetzt. Ein UI-Filter allein ist keine Absicherung.
|
||
|
||
---
|
||
|
||
## 3. Navigationsgerüst
|
||
|
||
```
|
||
┌─ VOR DEM LOGIN ────────────────────────────────────────┐
|
||
│ Willkommen → Registrieren / Anmelden │
|
||
└────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─ ONBOARDING (einmalig, modal, Tabs ausgeblendet) ──────┐
|
||
│ Tut 1 → 6 Pflichtfragen → Tut 2 → Uploads (optional) │
|
||
└────────────────────────────────────────────────────────┘
|
||
↓
|
||
╔═ TABS ═════════════════════════════════════════════════╗
|
||
║ ║
|
||
║ ① FEED ② ➕ (Popover) ③ PROFIL ║
|
||
║ ├ Feed-Deck ├ Post erstellen ├ Eigenes Profil║
|
||
║ │ (Videos / ├ Video erstellen ├ Ordner ║
|
||
║ │ Folge ich / ├ Modell erstellen ├ Modelle ║
|
||
║ │ Posts) └ Entwürfe ├ Knowledge Base║
|
||
║ ├ Post-Detail ├ Einstellungen ║
|
||
║ ├ ► Kopieren └ ⚙ Dev-Modus ║
|
||
║ └ Fremdprofil (versteckt) ║
|
||
╚════════════════════════════════════════════════════════╝
|
||
```
|
||
|
||
**Warum ➕ ein Popover ist und kein Tab:** Es gibt drei verschiedene Erstellen-Abläufe (Post, Video, Modell) mit völlig unterschiedlicher Länge. Ein Tab müsste einen davon zum Standard machen. Das Popover fragt stattdessen zuerst, was entstehen soll – so wie im Prototyp bereits angelegt (`#createMenu`).
|
||
|
||
**Warum die Ordner im Profil bleiben und keinen eigenen Tab bekommen:** Bei drei Tabs ist der Feed die Startseite, das Erstellen der Kern und das Profil alles, was einem selbst gehört. Ordner sind Teil davon. Damit sie trotzdem erreichbar sind, gehören sie **oben** ins Profil – nicht wie im Prototyp unter Metriken und Knowledge Base.
|
||
|
||
---
|
||
|
||
## 4. Screen-Katalog
|
||
|
||
Legende Prototyp-Status: **✅ vorhanden** · **⚠️ vorhanden, unvollständig** · **🆕 fehlt**
|
||
|
||
### 4.1 Vor dem Login
|
||
|
||
| Screen | Zweck | Liest | Schreibt | Prototyp |
|
||
|---|---|---|---|---|
|
||
| **Willkommen** | Was ist die App, Registrieren/Anmelden | – | – | 🆕 |
|
||
| **Registrieren / Anmelden** | Appwrite Auth (E-Mail + Passwort) | – | Appwrite-Account, `brands`, Team | 🆕 |
|
||
|
||
> Fehlt im Prototyp komplett. Ohne Auth gibt es keine Zeilenrechte und damit keine Mandantentrennung – das ist Teil des Fundaments, nicht ein späteres Extra.
|
||
|
||
### 4.2 Onboarding (einmalig)
|
||
|
||
| Screen | Zweck | Liest | Schreibt | Prototyp |
|
||
|---|---|---|---|---|
|
||
| **Tut 1** | Erklärt, warum gefragt wird | – | – | ✅ `#tut1` |
|
||
| **Pflichtfragen** | 6 Fragen inkl. **Nische** | – | `brands`, via P2 → `attributes` + `attribute_scores` | ⚠️ `#onboarding1` – nur 5 Felder, ohne Nische, ohne `id`/`name` |
|
||
| **Tut 2** | Erklärt die Uploads | – | – | ✅ `#tut2` |
|
||
| **Uploads** | Logo, Produktbilder, Top-Ads, Gesicht, Kulisse | – | Bucket `uploads`, via P1 → `assets`, `attributes` | ⚠️ `#onboarding2` – Attrappen, kein `<input type="file">` |
|
||
|
||
**Wichtig:** Das Onboarding erscheint beim **ersten Klick auf Erstellen**, nicht beim App-Start (so im Fragenkatalog festgelegt). Der Feed ist also vorher schon benutzbar – das ist gewollt, weil man erst sehen soll, was möglich ist.
|
||
|
||
### 4.3 Tab ① Feed
|
||
|
||
| Screen | Zweck | Liest | Schreibt | Prototyp |
|
||
|---|---|---|---|---|
|
||
| **Feed-Deck** | Swipe-Deck, 3 Reiter: Videos · Folge ich · Posts | `posts` (öffentlich, nach Nische gefiltert, nach `feed_score` sortiert) | `post_metrics` (views, likes) | ⚠️ `#explore` – Deck-Logik da, Daten hartkodiert |
|
||
| **Post-Detail** | Bilderkette, Slot-Chips, Autor, „Nachmachen" | `posts`, `post_images`, `assets` (nur Namen) | `post_metrics` | ⚠️ `#detail` – Inhalte fest verdrahtet |
|
||
| **► Kopieren** | Slots übernehmen oder ersetzen | `posts.slot_summary`, eigene `assets` (kompatibel nach `typ_tags`) | – (übergibt an Create) | 🆕 |
|
||
| **Fremdprofil** | Öffentliche Posts einer Person, Folgen-Button | `brands` (öffentliche Felder), `posts`, `follows` | `follows` | 🆕 |
|
||
|
||
**Der Kopier-Screen ist der wichtigste neue Screen.** Er zeigt je Slot einen Chip mit dem Wert des Originals. Modell-Chips sind **rot markiert und pflicht zu ersetzen**; Kulisse, Licht, Kamera, Farbe sind übernehmbar. Format und Kettenlänge werden ohne Rückfrage mitgenommen. Unten: „Weiter" → Create mit vorbefüllten Slots.
|
||
|
||
**Kompatibilitätsprüfung:** Beim Antippen eines Modell-Chips werden nur eigene Modelle angeboten, deren `typ_tags` zum Original passen. Ein Fahrzeug-Slot bietet kein Lippenstift-Modell an (`konzept-bilder-feed.md` §4).
|
||
|
||
### 4.4 Tab ② Erstellen
|
||
|
||
| Screen | Zweck | Liest | Schreibt | Prototyp |
|
||
|---|---|---|---|---|
|
||
| **➕ Popover** | Post / Video / Modell / Entwürfe | – | – | ⚠️ `#createMenu` – nur CSS, Markup unklar |
|
||
| **Post erstellen** | Ordner, Format, Kette, Slots, Prompt | `folders`, `assets`, `attribute_scores` (aktiver Ordner) | `posts`, `jobs` (`bild_gen`) | ⚠️ `#create` – Struktur da, ohne Ordnerwahl |
|
||
| **Generierung läuft** | Fortschritt der Kette, abbrechbar | `jobs` (Realtime) | – | 🆕 |
|
||
| **Post-Ergebnis** | Kette prüfen, privat behalten oder veröffentlichen | `posts`, `post_images` | `posts.sichtbarkeit`, Zeilen-Permission | 🆕 |
|
||
| **Video: Szene** | Prompt + Videoanzahl + Ordner | `folders`, `attribute_scores` | `scenes`, `jobs` (`script`) | ⚠️ `#scene-create` – ohne Ordnerwahl |
|
||
| **Video: Script** | Script bestätigen oder ändern (Diff = P6) | `scenes.script_md` | `scenes.script_final_md`, `jobs` (`video_gen`) | ✅ `#script-confirm` |
|
||
| **Video: Ergebnisse** | 3–6 Videos, Systemfavorit markiert | `videos` | `votes` | ✅ `#scene-results` |
|
||
| **Video: Vote** | Auswahl + optionale gezielte Frage | `questions` | `votes`, `questions.antwort` → `score_events` | ✅ `#scene-vote` |
|
||
| **Veröffentlichen** | Upload/Freigabe, danach Live-Performance | `video_metrics` | `videos.published` | ✅ `#publish` |
|
||
| **Modell erstellen** | Person / Produkt / **Kulisse** + Referenzen | – | `assets`, `asset_versions`, `jobs` | ⚠️ `#model-create` – Kulisse fehlt, kein echter Upload |
|
||
| **Modell-Ergebnis** | Freigeben oder verbessern | `asset_versions` | `assets.released_version_id` | ✅ `#model-result` |
|
||
| **Verbessern** (4 Screens) | Feedback → Versionen → Vote | `assets`, `asset_versions` | `asset_versions`, `score_events` | ✅ `#improve-*` |
|
||
| **Entwürfe** | Alles Unfertige **und alles Laufende** | `posts`, `scenes`, `assets` (Status ≠ fertig), `jobs` | – | ⚠️ `#drafts` – drei feste Karten |
|
||
|
||
> **Zwei fehlende Screens sind kritisch:** „Generierung läuft" und „Post-Ergebnis". Ohne sie gibt es keinen Ort, an dem der Nutzer wartet, und keinen Moment, an dem er sich bewusst fürs Veröffentlichen entscheidet – dabei ist genau das laut Konzept ein aktiver Schritt.
|
||
|
||
### 4.5 Tab ③ Profil
|
||
|
||
| Screen | Zweck | Liest | Schreibt | Prototyp |
|
||
|---|---|---|---|---|
|
||
| **Eigenes Profil** | Kopf, Ordner, eigene Posts, Kennzahlen | `brands`, `folders`, `posts`, `follows` | – | ⚠️ `#profile` – Reihenfolge stimmt nicht, Zahlen fest |
|
||
| **Ordner-Liste** | Alle Ordner, aktiver hervorgehoben, neu anlegen | `folders` | `folders` | ⚠️ im Profil eingebettet |
|
||
| **Ordner anlegen** | Name, **Zweck**, **Startwerte** | `folders` | `folders` → Function `ordner-initialisieren` | 🆕 |
|
||
| **Ordner-Detail** | Posts im Ordner, Reifegrad, als aktiv setzen | `post_folders`, `posts`, `folders.signal_count` | `post_folders` | ⚠️ `#folder` – nur Hülle |
|
||
| **Modelle** | Eigene Modelle nach Typ, Versionen | `assets`, `asset_versions` | – | 🆕 (nur über Erstellen erreichbar) |
|
||
| **Knowledge Base** | Regeln (lesend) + Attribute mit Score **je Ordner** | `rules`, `attribute_scores` | – | ⚠️ `#profile` – ein globaler Score, kein Ordner-Scope |
|
||
| **Attribut-Detail** | Verlauf, Siege, Unter-Attribute | `attribute_scores`, `score_events` | – | ⚠️ `#kb-detail` – hartkodiert, nicht erreichbar |
|
||
| **Einstellungen** | Konto, verbundene Konten, Abo, Abmelden | `brands`, `usage_records` | `brands` | 🆕 |
|
||
| **Developer-Modus** | Regeln, Prompt-Einblick, Elo-Parameter | `rules`, `prompt_templates`, `jobs.prompt_sent` | – | ⚠️ im Prototyp angelegt, Inhalt unbekannt |
|
||
|
||
**Zwei Änderungen gegenüber dem Prototyp:**
|
||
|
||
1. **Ordner nach oben.** Im Prototyp stehen sie unter den Metriken. Sie sind aber der Zugang zum wichtigsten Mechanismus der App und müssen ohne Scrollen erreichbar sein.
|
||
2. **Die Knowledge Base zeigt Scores je Ordner, nicht global.** Der Prototyp zeigt „Licht: warmes Abendlicht 6350". Richtig ist eine Ordner-Auswahl darüber – derselbe Wert ist in zwei Ordnern verschieden.
|
||
|
||
---
|
||
|
||
## 5. Die drei Abläufe, an denen sich der Aufbau entscheidet
|
||
|
||
### 5.1 Post erstellen
|
||
|
||
```
|
||
➕ → Post
|
||
│
|
||
├─ Ordner wählen ─────────► bestimmt, welche attribute_scores gezogen werden
|
||
├─ Format + Kettenlänge
|
||
├─ Slots füllen (Kulisse, Person, Produkt aus eigenen assets)
|
||
├─ Werbetext
|
||
└─ Prompt
|
||
↓ posts-Zeile (status=entwurf) + n jobs-Zeilen (bild_gen)
|
||
„Generierung läuft" ◄── Realtime auf jobs
|
||
↓ P22 taggt jedes Bild → post_images.tags
|
||
Post-Ergebnis
|
||
├─ privat behalten → bleibt in Entwürfen
|
||
└─ veröffentlichen → sichtbarkeit=oeffentlich + Zeilen-Permission öffentlich
|
||
```
|
||
|
||
**Der Bruch gegenüber dem Prototyp:** Zwischen „Generieren" und „Ergebnis" liegt ein Wartezustand mit eigener Bildschirmdarstellung, der überlebt, wenn man die App verlässt.
|
||
|
||
### 5.2 Kopieren
|
||
|
||
```
|
||
Feed-Deck → Post-Detail → „Nachmachen"
|
||
│
|
||
▼ Kopier-Screen
|
||
Format 4:5 ✓ übernommen (kein LLM)
|
||
Kette 3 Bilder ✓ übernommen
|
||
Kulisse [Badezimmer, Morgenlicht] → behalten oder eigenes
|
||
Person [fremdes Modell] ⛔ PFLICHT → eigenes wählen
|
||
Produkt [kleine Kerze] ⛔ PFLICHT → eigenes wählen
|
||
Licht/Kamera/Farbe [weich seitlich…] → behalten oder ändern
|
||
Werbetext ✎ wird von P21 neu geschrieben
|
||
│
|
||
├─ Ordner wählen (Ziel des Imports)
|
||
▼
|
||
Create (vorbefüllt) → wie 5.1
|
||
↓
|
||
Function feed-import: Slots als Attribute in attribute_scores des Ordners
|
||
post_metrics.kopien +1 beim Original
|
||
```
|
||
|
||
**Warum ein eigener Screen:** Der Nutzer muss vor dem Generieren sehen, was aus dem Original stammt und was seins ist. Springt man direkt in Create, verschwimmt das – und die Pflicht, eigene Modelle einzusetzen, wird zu einer Fehlermeldung statt zu einer sichtbaren Regel.
|
||
|
||
### 5.3 Ordner wechseln
|
||
|
||
Der aktive Ordner wird im Profil oder beim Erstellen gesetzt und bleibt bestehen. Beim Wechsel ändert sich **nichts an bestehenden Posts** – nur die nächste Generierung zieht aus einem anderen Scope.
|
||
|
||
Sichtbar sein muss: **welcher Ordner aktiv ist** (Kopfzeile im Erstellen-Bereich) und **wie reif er ist** („4 Posts – lernt noch"). Ohne diese zwei Angaben ist für den Nutzer nicht erklärbar, warum zwei gleiche Prompts verschiedene Bilder ergeben.
|
||
|
||
---
|
||
|
||
## 6. Abgleich mit dem Prototyp
|
||
|
||
### Was bleibt
|
||
|
||
Die komplette **Video-Strecke** (`scene-create` → `script-confirm` → `scene-results` → `scene-vote` → `publish`) und die **Verbessern-Strecke** (`improve-*`) sind schlüssig und decken sich mit dem Konzept. Ebenso das **Swipe-Deck** und die **3D-Ordner-Darstellung**.
|
||
|
||
### Was sich ändern muss
|
||
|
||
| Prototyp | Muss werden |
|
||
|---|---|
|
||
| Onboarding: 5 Felder ohne `id`/`name` | 6 Fragen inkl. Nische, Werte werden gespeichert |
|
||
| Modell-Typen: Person / Produkt | Person / Produkt / **Kulisse** |
|
||
| Ordner unten im Profil | Ordner oben, mit Zweck- und Startwert-Schaltern beim Anlegen |
|
||
| Knowledge Base mit einem globalen Score | Score je Ordner, mit Ordner-Auswahl |
|
||
| „Generieren" = Screenwechsel | Job + Wartezustand + Realtime |
|
||
| Entwürfe: drei feste Karten | echte Liste aus `posts`/`scenes`/`assets` + laufende Jobs |
|
||
| „Nachmachen" als Button | eigener Kopier-Screen |
|
||
| Uploads als Attrappen | echte Datei-Uploads in die Buckets |
|
||
| Fake-Tastatur, `inputmode="none"` | native Eingabe – die Fake-Tastatur ist ein reines Design-Requisit und darf nicht in die App |
|
||
|
||
### Was komplett fehlt
|
||
|
||
Willkommen · Registrieren/Anmelden · Kopier-Screen · Fremdprofil · Ordner anlegen · Modelle-Übersicht · Generierung läuft · Post-Ergebnis · Einstellungen.
|
||
|
||
---
|
||
|
||
## 7. Neu wegen des Folgen-Konzepts
|
||
|
||
Der Social Graph war in keinem Dokument enthalten und bringt eigenen Bedarf mit:
|
||
|
||
**Datenbank:** neue Tabelle `follows` (`follower_brand_id`, `followed_brand_id`, unique auf beide, Index auf beide Richtungen). Dazu auf `brands` öffentliche Felder: `anzeigename`, `avatar_file_id`, `follower_count`, `ist_oeffentlich`.
|
||
|
||
**Feed-Reiter „Folge ich":** eigene Abfrage – Posts der gefolgten Brands, **chronologisch statt nach Feed-Score**. Wer jemandem folgt, will dessen Neues sehen, nicht dessen Bestes von vor drei Monaten.
|
||
|
||
**Rechtlich:** Ein öffentliches Profil mit Folgen-Funktion ist ein soziales Netzwerk im Kleinen. Nötig werden damit: **Blockieren**, **Melden** (DSA) und eine Entscheidung zum **Mindestalter**. Das steht so noch in keinem Dokument und gehört vor dem Livegang geklärt, nicht danach.
|
||
|
||
---
|
||
|
||
## 8. Offene Punkte
|
||
|
||
| # | Punkt | Blockiert |
|
||
|---|---|---|
|
||
| 1 | **Bildmodell** noch nicht ausgewählt | jede echte Generierung |
|
||
| 2 | **Nischen- und `typ_tags`-Enums** nicht festgelegt | Kopier-Kompatibilität, Feed-Filter, P19, P22 |
|
||
| 3 | **Preismodell / Credits** | Einstellungen-Screen, `usage_records`, Stripe |
|
||
| 4 | **Moderation und Melden** | Livegang des öffentlichen Feeds |
|
||
| 5 | **Desktop-Ansicht** | im Repo als Handoff vorhanden, laut dir noch nicht gültig |
|
||
| 6 | **Developer-Modus** | Inhalt des Prototyp-Screens ist unbekannt (Datei war beim Abruf abgeschnitten) |
|