prd-helpMake your own PRD

Read-only PRD for a coding agent

Das bestehende Tagging-System erkennt Tags generisch und unterscheidet nicht zwischen…

17 of 18 sections ready
1. Problem, goal & success metric
  • Problem: Das bestehende Tagging-System erkennt Tags generisch und unterscheidet nicht zwischen biologischen und formalen Kategorien. Verwandte Begriffe liegen verstreut in der Mindmap, die Map ist schwer erkundbar.
  • Goal: Das Tagging-System soll automatisch biologische Kategorien (Organ, Gewebe, Zelltyp, Krankheit, Funktion) und formale Kategorien (Methode, Ergebnis, Definition, Beispiel, Literatur) erkennen. Knoten derselben Kategorie clusterieren in der Map; biologische Kategorien liegen außen, formale Kategorien innen.
  • Success metric: Bei 10 Testdokumenten werden mindestens 80 % der Tags der richtigen Kategorie zugeordnet. Die Mindmap startet unter 2 Sekunden bei 121 Tags.
2. Users & roles
  • Studierende: laden Vorlesungsmaterialien (PDF/TXT/DOCX) hoch, erkunden Dokumente als interaktive Mindmap, bearbeiten und mergen Tags.
  • Keine weiteren Rollen; es gibt kein Auth-/Nutzerkonzept.

Default: Keine weiteren Rollen, kein Auth.

3. Core workflows
  1. Studierende laden eine Datei (PDF/TXT/DOCX) hoch über den Upload-Dialog.
  2. Das Backend extrahiert Text, segmentiert Sätze, extrahiert Keywords (c-TF-IDF), clustert Tags bottom-up (L1–L5) und erzeugt eine Zusammenfassung.
  3. Die neue Kategorisierungs-Erkennung ordnet jedem Tag eine Kategorie (biologisch/formal + Unterkategorie) zu.
  4. Die Mindmap rendert Tags als Dots; Knoten derselben Kategorie clusterieren, biologische außen, formale innen.
  5. Studierende filtern nach Ebenen/Tags, bearbeiten Tags inline, mergen/löschen globale Tags und öffnen Dokumenten-Vorschau mit Summary.
4. Features & requirements

Upload ohne Größenbegrenzung

  • Es gibt keine feste maximale Dateigröße.
  • Ab 20 MB erscheint im Upload-Status der Hinweis „Große Datei – die Analyse kann länger dauern“.
  • Der Hinweis blockiert den Upload nicht; die Mindmap-Startzeit (unter 2 s bei 121 Tags) bleibt davon unberührt.
5. Scope: must / later / never

Must

  1. Biologisch/formal-Kategorisierung jedes Tags (biologisch = Organ, Gewebe, Zelltyp, Krankheit, Funktion; formal = Methode, Ergebnis, Definition, Beispiel, Literatur). Prüfung: A9.
  2. Kategorienbasierte Positionierung in der Mindmap: Knoten derselben Kategorie clustern; biologische Cluster außen, formale innen. Prüfung: A10.
  3. Einmalige automatische Hintergrund-Neuanalyse bestehender Dokumente beim ersten Start nach dem Umbau; die Mindmap startet sofort und wird nie blockiert. Prüfung: A9, A10.
  4. Automatische Neuanalyse eines Dokuments nur bei Upload oder bei Änderung der Analyseversion. Prüfung: A9.
  5. Upload ohne feste Größenbegrenzung mit Hinweis „Große Datei – die Analyse kann länger dauern“ ab 20 MB, nur im Upload-Status, solange die Analyse läuft. Prüfung: A9.
  6. Retry fehlgeschlagener Analysen beim nächsten Start (max. 3 Versuche, Zähler dauerhaft gespeichert, Reset bei erneutem Upload). Prüfung: A9, A9b, A9c.
  7. Messbare Akzeptanz: 80 % korrekte Kategorisierung bei 10 Testdokumenten; Mindmap startet unter 2 s bei 121 Tags. Prüfung: A10, A10b.

Later
Leer. Erweiterungen werden bei Bedarf neu bewertet.

Never

  • Benutzerkonten, Login, Berechtigungen, Microservices, Queues, Kubernetes.
  • Manueller Button „Neu kategorisieren“ oder Retry-Button; die automatische Logik übernimmt beides.
  • Blockierender Start: die Mindmap wartet nie auf die Hintergrund-Neuanalyse.
  • Feste Größenbegrenzung beim Upload.
  • Playwright-Test als Build-Gate: ein Fehlschlag erzeugt nur eine Terminal-Warnung.
6. Screens & UI

Upload-Status

  • Ab 20 MB Dateigröße erscheint im Upload-Status der Hinweis „Große Datei – die Analyse kann länger dauern“, solange die Analyse läuft.
  • Der Hinweis verschwindet automatisch, sobald die Analyse abgeschlossen ist.
  • Schlägt die Analyse fehl, verschwindet der Hinweis; an seiner Stelle erscheint der Status „Analyse fehlgeschlagen“.
  • Der Hinweis blockiert den Upload nicht; die Mindmap startet unverändert.
  • In der Dokument-Vorschau erscheint kein zusätzlicher Hinweis; dort gilt nur der normale Analysestatus.
7. Design system & visual style1 fix
  • 15490 characters is too long for small coding models: cut it under 2500, in short bullets without repeats

Dateien:

  • src/index.css: Design-Tokens, Wasserfarben-Textur, Art-Déco-Rahmen,
    Eck-Ornamente, Layer-/Übergangsregeln.
  • src/components/Dashboard.tsx: Haupt-Panels im Deco-Look, Suchleiste,
    Tag-Fenster, Status-/Level-Panels.
  • src/components/MindmapView.tsx: Label-Platzierung, Kollisionsauflösung,
    Legenden-Plakette, LOD-Übergänge.
  • src/components/WeightedEdge.tsx: gewichtete Kanten (aus Schritt 5).
  • src/components/TagEditor.tsx, MindmapFilterMenu.tsx, TagManager.tsx,
    DocumentViewerModal.tsx: einheitliche Deco-Rahmen und Hintergründe.

Design-Tokens & Palette

  • Primär-Grün #1F331A (rgb 31, 51, 26) für aktive Elemente, Header,
    Buttons, Fokuszustände und primäre Akzente.
  • Sand-Beige #DDDDC7 (rgb 221, 218, 199) als Sekundär- und Rahmenton,
    Papierton #FAF8F5 für Kartenflächen.
  • Die Variablen liegen in @layer utilities (:root):
    --deco-green, --deco-beige.
  • Utility-Klassen: .bg-watercolor-soft, .art-deco-border,
    .art-deco-card.
  • Wasserfarben-Textur: body (fixierter Doppel-Verlauf) sowie Hauptcontainer
    und Canvas über .bg-watercolor-soft; Panels erhalten zusätzlich einen

    dezenten Radialverlauf.

Art-Déco-Rahmen & Verzierung

  • Alle Haupt-Panels (Status, Abstraktionslevel, Gewählter Knoten,
    Dokument-Vorschau, Tag-Fenster, Zusammenfassung, Mindmap, Footer-Suche)

    nutzen .art-deco-card .art-deco-border: 2-px-Rahmen plus inset-Doppelring

    (#DDDDC7 / #1F331A).
  • .art-deco-card .art-deco-border ergänzt vier kleine Rauten in den Ecken
    (SVG-Data-URI im background-image) – rein dekorativ, ohne Layout-Einfluss.
  • .deco-heading zieht eine klassische Trennlinie mit verdickten Enden unter
    Panel-Titeln; Rauten-Marker dienen als Titel-Akzente.
  • Modale nutzen .deco-scrim (gedecktes Grün statt kühlem Stein) und
    denselben Doppelrahmen.
  • Typografie unverändert nach Vorgabe: Cinzel (Versalien, weites Tracking)
    für Überschriften, Labels und Buttons; Times New Roman für Fließtext,

    Zähler, Titel, Badges und das Suchfeld.

Label-Platzierung (Stand: feste Verankerung, Schritt 10)

  • Die Labels werden direkt in den Node-Komponenten gerendert
    (GalaxyNode, DocumentNode, GroupNode), als Kind des InvZoomLayer

    im DOM des Punkts. Dadurch laufen sie bei Drag, Zoom und Layoutwechsel

    immer exakt mit ihrem Punkt mit – ein Abkoppeln ist baulich unmöglich.
  • Feste Anker statt freier Verschiebung: Standard ist zentriert direkt
    unter dem Punkt (Abstand = Punktradius + LABEL_GAP = 6 px). Ist dieser

    Platz durch einen fremden Punkt belegt, sitzt das Label direkt darüber,

    sonst direkt links bzw. rechts daneben (Text zeigt zum Punkt hin).

    labelAnchorStyle() liefert dafür nur left / top / transform

    relativ zum Punkt. Es gibt keine Zeilen, keine X-Versätze und keine

    Platzierung quer über die Karte mehr.
  • `placeLabels()` prüft nur noch die Sichtbarkeit: Es berechnet die
    Screen-Rechtecke dieser festen Anker, vergleicht sie mit bereits

    vergebenen Labels und allen sichtbaren Punkten und markiert Kollisionen

    als hidden (Hover blendet sie ein). Kein Label wird verschoben.
  • Echter Viewport statt Canvas-Mitte: Die Screen-Position eines Punkts
    ist view.x + x · zoom bzw. view.y + y · zoom. Der Viewport wird beim

    Berechnen direkt über getViewport() gelesen; labelZoom bleibt nur der

    entprellte Trigger, damit während einer Geste nicht jedes Frame neu

    platziert wird.
  • Beim ersten Render existiert noch kein zentrierter Viewport; onInit
    stößt nach setCenter einmalig eine Neuberechnung an (viewVersion).
  • Punkte sind Hindernisse: Neben bereits platzierten Labels zählen alle
    sichtbaren Punkte als Hindernis – auch die Punkte feiner Tags, die auf der

    aktuellen Stufe kein eigenes Label bekommen. Geprüft wird der Abstand zur

    Kreisfläche (Radius + 4 px), nicht die Bounding-Box: Ein Label, das

    nur die Ecke des Punkt-Quadrats berührt, verschwindet dadurch nicht.
  • Kollisionsbox ≈ sichtbare Schriftfläche: Breite aus der Zeichenzahl
    (Cinzel-Versalien inkl. letterSpacing breiter als Times), lange Namen

    brechen auf zwei Zeilen um (max. 132 px); die Schätzung ist bewusst

    konservativ (Zuschlag 14 px), damit die gemessene Schriftfläche nie

    größer ist als die Box.
  • Priorisierung: Makro-Labels zuerst, danach der fokussierte Rang, zuletzt
    der Rest. So bleiben die Hauptbegriffe am längsten lesbar.
  • Strikte Auflösung: Findet ein Label an keinem der vier Anker einen
    kollisionsfreien Platz, wird es ausgeblendet und beim Hover wieder

    eingeblendet (.mm-label-hidden). Labels werden nie übereinander gelegt.

    Die Anzahl ausgeblendeter Labels hängt von der Canvas-Größe ab (bei

    1600×1000: L3 19/22, L4 94/104 sichtbar; bei 1280×800: L3 9/22, L4 77/104).
  • Die Kraftsimulation nutzt einen labelbreitenabhängigen Kollisionsradius
    (tagCollisionRadius, d3.forceCollide), damit die Knoten bereits im

    Layout Abstand halten.

Radikaler Art-Déco-Reset (Logik-Erhalt)

Das komplette UI wurde ohne Änderung an Datenfluss, Hooks, Props oder
Handlern neu gestaltet. Angepasst wurden ausschließlich Klassen, Inline-Styles

und dekorative Elemente.

Neue Design-Elemente in `src/index.css`:

KlasseWirkung
.deco-surface-darkTiefgrüne Fläche mit Gold-Verlauf (Header, Toolbar, Auswahlkarte)
.deco-rule-goldGoldene Haarlinie mit Rauten-Akzente
.deco-ornament-fanBogen- und Fächerlinien (Referenz „Musterplakat")
.deco-ornament-cornerFeiner Eckwinkel für Karten
.deco-ornament-starKleiner Rautenstern als Akzent
.deco-archBogenförmige Kachel (Dateisymbole)
.art-deco-border-goldDoppelrahmen mit zusätzlicher Gold-Haarlinie
.deco-heading-goldGold-Trennlinie unter Panel-Titeln
.deco-btn / .deco-btn-invert / .deco-btn-activeBedienelemente (hell/dunkel/aktiv)

Farbwelt: Primär #1F331A, Sand #DDDDC7, Papier #FAF8F5,
Gold #B08D57 / #D8C08C (neu in @theme als --color-gold).

Alle neutralen Tailwind-Töne (bg-gray-*, border-gray-*, bg-white,

border-black/*, shadow-sm) wurden entfernt – im Quellcode kommt kein

Grauton mehr vor.

Datei für Datei umgesetzt:

  • Dashboard.tsx – Kopfzeile als tiefgrüne Deco-Bande mit Fächerornament,
    Goldlinie und invertierten Buttons; Status-Panel mit Eckwinkel und Stern;

    Abstraktionslevel mit Gold-Akzentkante; „Gewählter Knoten" als

    dunkle Goldkarte; Suchleiste mit Gold-Haarlinie; Dokumentkarten mit

    Bogen-Kachel.
  • MindmapView.tsx – Toolbar als tiefgrüne Bande mit Gold-Aktionen,
    Legende inline in der Toolbar (kein Overlay mehr auf der Karte),

    Hover-Card mit Gold-Doppelrahmen, Eckwinkel und Stern.
  • WeightedEdge.tsx – Kantenfarben der neuen Palette (Grün, Salbei, Gold).
  • mindmapLevels.ts – Punktskala: Makro #1F331A → Fein #DDDDC7,
    Punktgrößen 14/13/12/11 px.
  • DocumentPreview.tsx, DocPlaceholder.tsx, TagEditor.tsx,
    TagManager.tsx, DocumentViewerModal.tsx, MindmapFilterMenu.tsx,

    MarkdownText.tsx, NewTabLink.tsx – einheitliche Rahmen, Goldakzente,

    Bogen-Kacheln, Fächerornamente, Cinzel-Überschriften.

Punkte & Edges in React Flow: Der fokussierte Rang (Stufe 1/2) und die
Makro-Knoten tragen einen goldenen Ring; Edges nutzen die Palette der neuen

Tokens. Die D3-Kollision (d3.forceCollide, labelbreitenabhängiger Radius)

bleibt unverändert, die Label-Platzierung zusätzlich um einen 2-px-Sicherheits-

abstand zwischen den Textflächen erweitert.

Gemini-Analyse (Schritt 8)

Dateien

  • src/services/geminiService.ts – Client, Prompt, robustes JSON-Parsing.
  • src/api.ts – updateDocumentSummary().
  • src/components/DocumentPreview.tsx – „Gemini"-Aktion + Statusleiste.
  • src/components/Dashboard.tsx – Ablauf, Tag-/Level-Anzeige.
  • backend/app/{models,store,main}.py – PATCH /api/documents/{id}/summary.

Konfiguration (.env, Vorlage in .env.example):

VITE_GEMINI_API_KEY=<Key aus https://aistudio.google.com/app/apikey>
VITE_GEMINI_MODEL=gemini-3.5-flash     # Modellkette, kommagetrennt
VITE_GEMINI_BASE_URL=                   # optional, z. B. eigener Proxy

Der Key ist in .env eingetragen (Datei ist in .gitignore).
gemini-2.5-flash ist für neue AI-Studio-Keys gesperrt (404 „no longer

available to new users“) und neuere Modelle zeitweise überlastet (503 „high

demand"). Der Dienst probiert deshalb eine Modell-Kette durch

(gemini-3.5-flash → 3.6 → 3.7 → 3.8 → gemini-flash-latest) und

nutzt das erste erreichbare Modell. Das genutzte Modell wird in der

Statusleiste angezeigt.

> Sicherheit: VITE_*-Variablen landen im JS-Bundle und sind im Browser
> sichtbar. Der Key ist damit nur für Entwicklung/Demonstration geeignet.

> Produktiv den Key serverseitig halten und die Anfrage über das Backend

> proxyen. .env ist in .gitignore ausgenommen.

Ablauf

  1. Die Analyse startet automatisch nach dem Upload (siehe Schritt 11):
    Das Backend analysiert die Datei beim Hochladen lokal (das erzeugt die

    Tag-Hierarchie), direkt danach läuft – sofern ein Key hinterlegt ist –

    die Gemini-Verfeinerung von Zusammenfassung und Tags im Hintergrund.

    Einen „Analysieren"-Button gibt es nicht mehr.
  2. analyzeDocumentWithGemini() schickt max. 15 000 Zeichen an das erste
    erreichbare Modell der Kette und erwartet

    {summary, tags[], abstractionLevel}.
  3. Der Parser entfernt Markdown-Fences, extrahiert das erste JSON-Objekt
    auch aus Fließtext und validiert die Felder (Abstraktionslevel L1–L4).
  4. Die Zusammenfassung wird per PATCH /api/documents/{id}/summary
    dauerhaft gespeichert (analysisProvider: "gemini"), die Keywords

    ersetzen die bisherigen.
  5. Jeder Tag wird über die bestehende Tag-API angelegt und verknüpft – er
    erscheint damit sofort als interaktiver Chip im Tag-Fenster, in der

    Mindmap und in den Level-Zählern.
  6. Die Statusleiste zeigt „Gemini-Analyse", das Abstraktionslevel und die
    extrahierten Tags (ohne technische Modell-Bezeichnung); während des Laufs

    steht dort „✨ Analysiere Dokument …". Das Abstraktionslevel-Panel weist

    das Gemini-Abstraktionslevel aus; das Zusammenfassungs-Panel trägt ein

    „Gemini"-Siegel.

Kopfzeile der Dokument-Vorschau (Standort ist nur 588 px breit):
Zeile 1 zeigt Icon, Dateiname und Metadaten, Zeile 2 die geschlossene

Aktionsgruppe „In neuem Tab öffnen · Dokument öffnen".

Fehlerverhalten: Ohne Key, ohne Text oder bei API-Fehlern bleibt die App
voll funktionsfähig – die lokale Backend-Analyse beim Upload läuft

unverändert weiter, der Status springt auf „Fehler".

Automatische Analyse nach dem Upload (Schritt 11)

Die Gemini-Verfeinerung ist an den Upload gekoppelt; ein manueller Klick ist
nicht mehr nötig. Der Upload-Dialog blockiert dabei nicht.

Ablauf in `Dashboard.tsx`

  1. addFiles() lädt jede Datei über api.uploadDocument() hoch. Die
    Antwort enthält den neuen Gesamtzustand (inkl. text, summary und der

    lokal erzeugten Tags). Neue Dokumente werden per ID-Vergleich gegen den

    vorherigen Stand gesammelt (uploaded).
  2. Nach dem letzten Upload werden Zustand und Auswahl aktualisiert
    (setState, setSelectedId(uploaded[0].id)) und busy fällt auf

    false – die Oberfläche ist sofort wieder bedienbar.
  3. Die Notice meldet „… hochgeladen – die KI-Analyse läuft im Hintergrund.“
  4. enqueueGeminiAnalysis(uploaded) setzt für jedes neue Dokument den
    Status running und hängt die Arbeit an eine Promise-Warteschlange

    (geminiQueue, useRef). Mehrere Uploads bzw. schnelle Folge-Uploads

    werden sequenziell abgearbeitet, damit sich die Zustandsantworten

    des Backends (updateDocumentSummary, Tag-API) nicht überholen.
  5. Pro Dokument läuft applyGemini(): Text an Gemini, speichern der
    Zusammenfassung/Keywords (analysisProvider: "gemini"), Anlegen und

    Verknüpfen der Tags, setState() mit dem Serverzustand. Vorschau,

    Tag-Chips, Level-Zähler und Mindmap aktualisieren sich dadurch ohne

    weiteren Klick.
  6. Fehler (kein Key, leerer Text, API-/Netzwerkfehler) setzen den
    Dokumentstatus auf error; die lokal erzeugte Analyse bleibt erhalten.

UI-Indikatoren während des Laufs

  • Dokument-Vorschau (Dashboard): Statusleiste „✨ Analysiere Dokument …“.
  • Status-Panel links: zusätzliche Zeile „✨ KI-Analyse · läuft · n“, solange
    mindestens eine Analyse aktiv ist (runningAnalyses aus geminiStatus).

    Diese Zeile ist auch in der Mindmap-Ansicht sichtbar, wo die Vorschau-

    Karte fehlt.
  • Notice-Toast direkt nach dem Upload (4 s).

Entfernt

  • „Analysieren"-Button in DocumentPreview.tsx samt onAnalyze-Prop und
    RefreshCw-Import; analyzeDoc() in Dashboard.tsx.
  • Leerer-Zusammenfassung-Hinweis verweist nicht mehr auf den Button
    („Noch keine Zusammenfassung vorhanden.“).
  • api.analyzeDocument() bleibt als Mapping auf den bestehenden Endpoint
    POST /api/documents/{id}/analyze erhalten (derzeit ohne UI-Aufrufer).

Politur: Zierelemente, Abstände, Kontrast

Nach dem Design-Reset wurden die verbliebenen Artefakte bereinigt:

  • Grüne Flächen ohne Textur: .deco-surface-dark ist flaches #1F331A
    ohne Gold-Verlauf. Die Fächer-Overlays (deco-ornament-fan) wurden aus

    Header, Mindmap-Toolbar und „Gewählter Knoten" entfernt – auf dunklem

    Grund wirkten sie wie ein kopiertes Muster. Gold bleibt den echten

    Akzenten vorbehalten (Rauten, Linien, aktive Buttons).
  • Eck-Rauten auf dem Rahmen: Die vier Rauten der
    .art-deco-card.art-deco-border sind jetzt 8 px groß und über

    background-origin: border-box auf dem Rahmen platziert. Sie dringen

    dadurch höchstens ~4 px in den Innenbereich ein; mit p-4 bleiben

    Text und Icons ≥ 12 px entfernt (gemessen: 25 px für alle

    Panel-Überschriften, 29–30 px für Toolbar und Suchfeld).
  • Kein Stern, keine gestapelten Rauten: Der Stern im Status-Panel und
    die Rauten-Marker neben den Panel-Überschriften wurden entfernt.

    Übrig bleibt je Panel eine einzige saubere Gold-Trennlinie.
  • Titel-Raute: Der Kopfzeilen-Diamant ◇ sitzt jetzt mit pl-8 und
    left-1 vollständig sichtbar.
  • Suchleiste: Innenabstand px-6 py-3, Lupe und Platzhalter durch
    gap-3 getrennt, Goldlinie auf inset-x-6 eingerückt.
  • Innenabstände: Hover-Card p-4, Filtermenü px-4 py-3, Vorschau-
    Sektionen p-4, Tag-Editor/Tag-Verwaltung/Viewer px-5 py-4.
  • Kontrast: Beschriftungen im Status-Panel (DOKUMENTE, AUSSTEHEND,
    TAGS) stehen jetzt in vollem #1F331A; der Erklärungstext unten links

    in #1F331A (Versalien) bzw. #3E4136 (Serif). Die Level-Badges beziehen

    Farbe und Textfarbe aus der Rang-Palette statt aus einem zufälligen

    Backend-Tag – dadurch bleibt das Badge unabhängig von den Daten lesbar.

Übergänge

  • Knoten-Ein-/Ausblenden: 380 ms, Label-Opacity 300 ms.
  • Labels: nur Opacity (300 ms) – die Position ist fest am Punkt verankert
    und wird nicht mehr animiert. Beim Wechsel des Ankers springt das Label

    bewusst direkt (kein Wandern über die Karte).
  • Punkt-Hover/Selektion: 160 ms (Ring, Kontur).
  • Kanten: 220 ms für stroke-width und opacity.
  • prefers-reduced-motion: reduce schaltet alle Übergänge ab.

Layout-Stabilität

  • Das 12-Spalten-Grid (grid-cols-12 gap-4) bleibt unverändert; alle
    Panels sind fest, interne Scroll-Container scrollen nur intern.
  • Verifiziert: Grid, Footer und Suchfeld bleiben pixelgleich beim Wechsel
    von Ebene, Modus, Auswahl und Hover; kein globales Scrollen.

---

8. Data model
EntitätFeldTypPflicht
Docidstringja
Docnamestringja
Doctypestringja
Docsizenumberja
Docstatusstringja
Docsummarystringnein
Dockeywordsstring[]nein
DoctagIdsstring[]nein
Doctextstringnein
DocfileUrlstringnein
DocuploadedAtdatetimeja
DocanalyzedAtdatetimenein
DocanalysisProviderstringnein
DocfailedAttemptsnumber (≥0, Startwert 0, Reset auf 0 bei erneutem Upload)ja
Tagidstringja
Tagnamestringja
Taglevelnumber (1–5)ja
TagparentIdstringnein
TagchildCountnumberja
Tagcolorstringja
TagtextColorstringja
TagdocumentIdsstring[]ja
Tagcategoryenum (biologisch \formal)ja
Tagsubcategoryenum (organ, gewebe, zelltyp, krankheit, funktion, methode, ergebnis, definition, beispiel, literatur)ja

Verbindlich: failedAttempts wird im Datenspeicher persistent abgelegt und übersteht Neustarts. Ein erneuter Upload setzt den Wert auf 0 zurück.

9. APIs & integrations

Backend-Routen (FastAPI, Port 8000)

  • GET /api/state · POST /api/documents · GET /api/documents/{id}/file · POST /api/documents/{id}/analyze · GET /api/documents/{id}/prompt · DELETE /api/documents/{id}
  • POST /api/documents/{id}/tags · DELETE /api/documents/{id}/tags/{tagId}
  • GET /api/tags · PATCH /api/tags/{id} · DELETE /api/tags/{id} · POST /api/tags/merge · GET /api/health

Optional extern

  • Gemini API über VITE_GEMINI_API_KEY (in Entwicklung clientseitig; für Produktion serverseitig proxyen).
  • OpenAI-kompatibler LLM-Client über LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, LLM_TIMEOUT; ohne Schlüssel rein lokal.

Default: CORS nur für http://localhost:5173; alle Routen wie in der bestehenden Datei.

10. Auth, permissions & security
  • Nicht nötig: Keine Benutzerkonten, kein Login, keine Berechtigungen. Alle Nutzer sehen denselben Zustand.
  • Default: Kein Auth-Konzept, wie in Ihrer Datei beschrieben.
11. Performance, privacy & accessibility

Build-Verhalten

  • npm run build bricht bei TypeScript- oder Build-Fehlern weiterhin ab.
  • Der Playwright-Hilfslauf in Slice 4 erzeugt bei Abweichungen nur eine Warnung im Terminal; der Build läuft trotzdem durch.

Performance

  • Messbedingung: typischer Laptop mit 4 bis 8 GB RAM, Browser mit weiteren geöffneten Tabs.
  • Messpunkt: vom ersten Render bis alle 121 Knoten sichtbar; Schwelle 2 Sekunden.
  • Die Messung erfolgt manuell vor der Abgabe; der Playwright-Lauf dient nur als Hilfe.
  • Die Startzeit gilt auch während die Hintergrund-Neuanalyse läuft; die Mindmap wartet nie darauf.
  • Zoom/Pan ohne sichtbares Flackern; Label-Kollisionen 0 bei 1280×800 bis 1920×1080.
  • Positionsanpassung nach Kategorie-Update: sanfte Animation ca. 300 ms, ohne Sprünge und ohne Neuaufbau des Layouts.

Privacy

  • Keine Benutzerdaten, keine Auth; Dokumente bleiben lokal auf dem Rechner.

Accessibility

  • prefers-reduced-motion: reduce schaltet alle Übergänge ab, auch die 300-ms-Positionsanpassung.
  • Kontrast der Level-Badges unabhängig von der Backend-Tagfarbe.
12. Edge cases & errors

Wiederholungen bei fehlgeschlagener Analyse

  • Jedes Dokument speichert die Anzahl fehlgeschlagener Analyseversuche (failedAttempts, Startwert 0) dauerhaft im Datenspeicher; der Wert bleibt nach einem Neustart erhalten.
  • Beim nächsten Start werden Dokumente mit Status „Analyse fehlgeschlagen“ automatisch erneut analysiert, solange failedAttempts kleiner als 3 ist; kein Button.
  • Nach dem dritten fehlgeschlagenen Versuch wird nicht mehr automatisch wiederholt; der Status „Analyse fehlgeschlagen“ bleibt sichtbar, bis das Dokument erneut hochgeladen wird.
  • Ein erneuter Upload setzt failedAttempts auf 0 zurück.
13. Stack & constraints
  • Frontend: React 19, Vite, TypeScript, Tailwind, @xyflow/react, d3-force, @google/genai (optional). Backend: FastAPI, Python 3.9.6, uvicorn, In-Memory-Store, pdf.js/react-pdf für PDF-Extraktion.
  • Default: Stack aus Ihrer Datei übernommen.
14. Existing code & do-not-change
  • Backend: backend/app/{main.py, store.py, analysis.py, pipeline.py, prompts.py, llm.py, hierarchy.py, models.py}. Frontend: src/components/{Dashboard.tsx, MindmapView.tsx, TagEditor.tsx, TagManager.tsx, MindmapFilterMenu.tsx, DocumentPreview.tsx, DocumentViewerModal.tsx, WeightedEdge.tsx, MarkdownText.tsx}, src/api.ts, src/mindmapLevels.ts, src/mindmapFilters.ts, src/mindmapDocuments.ts, src/mindmapOverlap.ts, src/index.css.
  • Default: Alle bestehenden Dateien aus Ihrer Datei übernommen, dürfen nicht ohne Not geändert werden.
15. Build order
  1. Slice 1 – Kategorisierung im Backend: category + subcategory in Pipeline und Modelle; Analyseversion je Dokument speichern; Test mit 10 Dokumenten gegen Referenzkategorien.
  2. Slice 2 – Hintergrund-Neuanalyse: Beim ersten Start nach dem Umbau Dokumente ohne aktuelle Analyseversion sequenziell im Hintergrund neu analysieren; Mindmap startet sofort mit bestehenden Daten und aktualisiert Kategorien und Positionierung je fertigem Dokument; danach nur bei Upload oder Versionswechsel.
  3. Slice 3 – Positionierung: Cluster-Kräfte in mindmapOverlap.ts/mindmapDocuments.ts; biologisch außen, formal innen; Anzeige in MindmapView.tsx.
  4. Slice 4 – Performance & End-to-End-Prüfung: React-Memo, d3-force-Ticks begrenzen; Playwright-Lauf für Upload, Hintergrund-Neuanalyse, Kategorien, Filter, Startzeit, keine Konsolenfehler.
16. Acceptance criteria & tests
#CheckErwartetes Ergebnis
A9Fehler bei NeuanalyseFehlgeschlagenes Dokument bleibt sichtbar mit bisherigen Kategorien und Status „Analyse fehlgeschlagen“; beim nächsten Start wird automatisch erneut analysiert, ohne Button
A9bRetry-GrenzeNach drei fehlgeschlagenen Versuchen (über Neustarts hinweg gezählt) wird nicht mehr automatisch wiederholt; der Status bleibt bis zum erneuten Upload sichtbar
A9cZähler-ResetErneuter Upload eines fehlgeschlagenen Dokuments setzt failedAttempts auf 0 und startet die Analyse neu
A10StartzeitManuelle Messung vor der Abgabe auf typischem Laptop (4–8 GB RAM, Browser mit weiteren Tabs): alle 121 Knoten sichtbar in unter 2 s ab erstem Render
A10bPlaywright-HilfslaufPlaywright-Lauf in Slice 4 meldet Abweichungen nur als Warnung; der Build bricht nicht ab
17. Deployment, environments & secrets

Umgebung: lokal-first. Backend uvicorn app.main:app --port 8000, Frontend npm run dev auf Port 5173.
Hosting: kein externes Hosting; alles läuft auf dem Rechner der Studierenden.

Secrets: VITE_GEMINI_API_KEY und LLM_API_KEY nur in .env bzw. Umgebungsvariablen; .env bleibt in .gitignore.

Build: npm run build muss fehlerfrei durchlaufen.

18. Open questions & assumptions

Default: Bestehende Dokumente werden per Button neu kategorisiert, nicht automatisch.