# kulibri — Strategischer Kontext

## Start hier: Ziel, Richtung, Reihenfolge (Stand 6. Oktober 2026)

Für neue Entwickler und deren Claude Code. Dieser Abschnitt hat Vorrang vor älteren Aussagen in `docs/`.

- **Ziel.** Dieses Repo (`kulibri-rewrite`, Vue 3) bringt die klassische kulibri-Oberfläche (Vue 2 im Repo `kulibri-laravel`, Ordner `frontend/`) mit allen Fähigkeiten in eine neue Oberfläche. Es arbeitet gegen dasselbe Backend (test.kulibri.com). Die Lücken zur klassischen Oberfläche führt `PARITY-GAPS.md`.
- **Richtung.** Das Rewrite wird später in den Ordner `frontend-v3` des Branches `vue3-redesign` von `kulibri-laravel` übernommen, mit einem Umschalter klassisch/neu. Bis dahin wird hier gearbeitet. Ein Modul gilt erst als korrekt, wenn Design, Regeln und API gegen die klassische Version und das Backend abgeglichen sind. Der Plan steht in `REWRITE-INTEGRATION.md` (Repo `kulibri-laravel`, Branch `vue3-redesign`, Stand 3. Oktober 2026).
- **Anmeldung.** Das Rewrite allein arbeitet mit Bearer-Token. Wie sich die integrierte Fassung anmeldet (Session in beiden Oberflächen, Brücke oder Token) ist offen bis kurz vor dem Probelauf; Arbeitsannahme ist die Session. Die Aussagen vom 2. Oktober „das Rewrite ersetzt `frontend-v3`“ und „Token ist der einzige Weg“ sind überholt.
- **Reihenfolge zum Einlesen.** 1. diese Datei (Regeln unten); 2. `PARITY-GAPS.md` (Stand der Lücken: Abschnitt 11 „Nächste Schritte“ und Abschnitt 12 Anmeldeseiten); 3. `REFACTORING-ROADMAP.md`; 4. `docs/kulibri-backend-befunde_1.md` und `docs/kulibri-backend-anforderungen-auth.md`; 5. `docs/qa-pruefliste.md` (manueller Prüfstand) und `docs/po-fragen.md` (offene Entscheidungen).
- **Arbeitsweise.** Erst prüfen, dann vorschlagen, dann bauen. Eine Zeile aus `PARITY-GAPS.md` zuerst gegen den Code der klassischen Oberfläche prüfen (die Liste war schon mehrfach falsch). Das Backend nur lesend prüfen (leere oder ungültige Anfragen an die Testumgebung, nie Routen, die schreiben). Die Regeln 1 bis 14 unten einhalten, Tests schreiben, `PARITY-GAPS.md` im selben Zug ändern. Backend-Befunde gehören in `docs/kulibri-backend-befunde_1.md`; Änderungen am Backend (Repo `kulibri-laravel`) nur nach Absprache mit Mitko.
- **Language: English for docs and code comments.** When you change a document or a file with non-English comments, translate the parts you touch (or the whole document if it is short) in the same commit. Do not translate untouched docs in bulk. Commit messages and GitHub issues are in English. User-facing strings (UI, locales) stay multi-language.

## Positionierung
kulibri ist die Termin- und Anmeldeplattform für Gruppen, die sich regelmäßig organisieren — werbefrei, DSGVO-konform, in Deutschland gehostet. Ohne Konto für Teilnehmer, ohne Datenhandel, ohne Nutzerlizenzen.

## Primäre Zielgruppe
- **A — Organisierte Gemeinschaft (13–60 Personen):** Schulklassen, Kitas, Vereine, Mannschaften, Chöre, Feuerwehren. Zahlungsbereitschaft 8–16 %.
- **B — Kursanbieter ohne Buchungsgeschäft:** VHS-Dozenten, Chorleitungen, Ferienbetreuung. Anmeldung ohne Buchungssystem. 18,5 % Premium.

## Kernspannung
Der virale Loop (private Gruppen ≤12) bringt Nutzer, die nie zahlen. Das Geschäft liegt bei organisierten Gruppen. Beide Gruppen brauchen unterschiedliche Antworten, sind aber nicht im Konflikt.

## Harte Regeln
- Funktionen, die neue Teilnehmer erzeugen, werden **nie bepreist** (Einladen, Kopieren, Selbsteintragung = Loop-Mechaniken).
- **Kein Zahlungsmodul.** Sobald Geld über die Plattform fließt, konkurriert kulibri mit Kurssoftware statt neben ihr.
- Teilnehmer brauchen **kein Konto**. Das ist ein Kernunterschied zu Buchungssystemen.
- **Vorlagen 1:1 umsetzen.** Wenn HTML-Dateien oder Screenshots als Vorlage bereitgestellt werden, sind diese inhaltlich und stilistisch 1:1 umzusetzen, sofern nicht explizit anders geprompted. Bestehende Funktionalität muss dabei immer erhalten bleiben. Im Falle eines Konflikts (z.B. Vorlage vs. bestehende Funktion) immer zuerst rückfragen, bevor geändert wird.

## Produktreihenfolge
0. Grid-Performance bei großen Umfragen (Voraussetzung, kein Feature)
1. Kursplaner fertigstellen (einzige belegte Nachfrage aus Kundengesprächen)
2. Adressliste (zweite Aufgabe für Schule/Kita, Zeitfenster Schuljahresbeginn)
3. Kapazitäts-Primitiv → Bringliste als Nebenprodukt
4. Schichtplanung mit zweiphasiger Zuteilung (stärkster Retention-Hebel)
5. 1:1-Terminvergabe (Einstieg über Elterngespräche)
6. Ausgabenabrechnung (Vereins-/Klassenkasse, reine Buchführung)

## Strukturelle Einsicht
Kursplaner, Bringliste, Schichtplanung und 1:1 sind dasselbe Primitiv: *Option mit Kapazität, Teilnehmer trägt sich ein.* Das `limit`-Feld an `choices` existiert bereits. Einmal richtig bauen, dann sind vier Module überwiegend Konfiguration.

## Abgrenzung zu Doodle
- Keine Werbung für Teilnehmer (auch nicht kostenlos)
- „Wenn nötig"-Antwort immer kostenlos
- Unbegrenzt aktive Umfragen kostenlos
- 36 €/Jahr, keine Nutzerlizenzen (~132 $/Jahr bei Doodle)
- Serverstandort Deutschland, DSGVO

## Was kulibri nicht ist
Kein Social Network, kein Messenger, kein Buchungs- oder Zahlungssystem, keine Projektmanagement-Software.

## Offene Punkte
- Terminologie Schichtplanung (Schicht/Dienstplan/Mannschaftsplanung)
- AT/CH-Landingpages als eigener Hebel
- Paywall-Platzierung und kulibri-credits-Modell zurückgestellt
- 56–61 % der institutionellen Erstnutzer kommen nie wieder — Priorität: zweite Umfrage selbstverständlich machen

## Vollständiges Strategiedokument
Siehe Anhang im Chat-Verlauf: kulibri-vision-positionierung-v2.md (August 2026)

## Technische Arbeitsregeln — VORSCHLAG, bitte bestätigen

**Status:** Vorschlag von kulibri, Stand 30.09.2026, von Bolt noch nicht bestätigt. Rückmeldung bitte in `docs/kulibri-wiederverwendung-diskussion.md`, Abschnitt 8. Bis dahin sind es Empfehlungen. Geprüft werden Regel 1, nur für neue Views (`src/__tests__/architecture.spec.ts`), und Regel 12 (`src/__tests__/designTokens.spec.ts`).

**Zweck:** Der Code soll später mit möglichst wenig Änderung in kulibris `frontend-v3` weiterlaufen. Dort gibt es die Zielform schon: reine Regelmodule, kleine Komponenten, Zustand in Composables. Die Regeln gelten für **neuen oder angefassten** Code, nicht für einen Großumbau. Am verbindlichen Design ändern sie nichts (siehe „Harte Regeln").

1. **Views rufen `api`/`http` nicht direkt auf.** Datenzugriff läuft über ein Composable oder einen Store; die View bekommt fertige Daten und löst Aktionen aus. Der Test lässt keine neuen direkten Importe zu. Die zehn heutigen Views stehen auf einer Liste, die nur kürzer werden darf.
2. **Was sich aus reinen Daten ableiten lässt, gehört in ein eigenes Modul** ohne Vue, DOM und `fetch`: Daten rein, Ergebnis raus, testbar ohne Komponente.
   ```ts
   export const isArchived = (poll: DashboardPoll): boolean => Boolean(poll.isArchive);
   export const lastActivity = (poll: DashboardPoll): string => poll.updated_at ?? poll.created_at;
   ```
   Ein `computed`, das nur aus Props oder Antwortdaten rechnet, gehört dorthin.
3. **Kleine Komponenten.** Eine Komponente, eine Aufgabe, grob unter 300 Zeilen. `PollDetailView.vue` hat über 4300; den Schnitt legt Bolt fest (Antwort-/Zeilenbearbeitung, Teilnehmerverwaltung, Teilen/Einladen, Kommentare).
4. **IDs sind Zeichenketten** (Hashids). Nicht parsen, nicht numerisch vergleichen, nicht danach sortieren. Bekannter Fall: `mappers.ts` sortiert Textoptionen nach `id`, was bei Hashids eine zufällige Reihenfolge ergibt.
5. **Zwei Antwortskalen nie vermischen:** `preferences.value` je Option (`-2` vielleicht, `-1` keine, `0` nein, `1` ja, `2` wenn nötig, `3` Warteliste) und `participants.choice` je Teilnehmer (nur Gästelisten).
6. **Keine umgebungsspezifischen Werte im Code** (Hosts, Adressen). Sie kommen aus einer Umgebungsvariable. Bekannter Fall: `resolveAssetUrl` mit `https://test.kulibri.com/`.
7. **Jeder sichtbare Text über `t()`.**
8. **Das Backend entscheidet** über Zählungen, Rechte, Kapazität und Wartelisten. Die View zeigt das Ergebnis und rechnet nicht nach (Kursplaner: nicht selbst entscheiden „voll, also Warteliste"). Im Zweifel gilt der API-Vertrag; wo der nicht reicht, fragen statt raten.
9. **Regeln haben Tests** (Vitest, `npm test`). Ein Fehler beginnt mit einem fehlschlagenden Test.
10. **Jede Abweichung von der klassischen UI** steht mit Begründung im Kopf des Moduls („Abweichung von MyPolls.vue: …").
11. **Keine neue Bibliothek ohne Notiz** in der Commit-Nachricht. Beim Portieren wird jede geprüft. Bekannt: `xlsx` 0.18.5 hat offene Sicherheitsmeldungen.
12. **Farben und Schrift nur über Tokens.** Kette: Variable `--k-*` (`src/index.css`, hell und dunkel) → Tailwind-Name (`tailwind.config.js`) → Komponente oder View.
    - In Templates die Tailwind-Namen benutzen: `bg-primary`, `text-foreground`, `text-muted-foreground`, `border-border`, `bg-surface`, `text-destructive`, `bg-destructive-soft`, Deckkraft mit `bg-primary/20`. In CSS `var(--k-…)`.
    - **Keine** festen Werte (`#F2760A`, `rgb()`, `bg-[#…]`) und **keine** Paletten-Klassen (`red-500`, `gray-200`) in `.vue`-Dateien. Der Test lässt keine neuen zu; die Dateien auf seiner Budget-Liste dürfen nur sauberer werden.
    - **Fehlt ein Ton**, wird zuerst ein Token in `src/index.css` angelegt (hell, dunkel und in `.k-light-overlay`) und dann in `tailwind.config.js` benannt. Nicht als Einzelwert in die Komponente.
    - Farbe allein trägt keine Bedeutung: Zustände (Fehler, Erfolg, Warteliste) haben zusätzlich Text oder Symbol. Tastaturfokus bleibt sichtbar (`ring`/`--k-focus-ring`), ein `outline-none` braucht Ersatz.
    - **Schrift über Rollen**, nicht über Größen: `text-display`, `text-h1`, `text-h2`, `text-h3`, `text-body`, `text-body-sm`, `text-label`, `text-caption` (`tailwind.config.js`; Größe, Zeilenhöhe und Gewicht zusammen, in `rem`). Keine Rolle ist kleiner als 12 px. Eine Familie: `--k-font-sans`, `font-sans` ist der Standard; keine eigenen `font-family`-Angaben und keine Schrift von fremden Servern (DSGVO). Keine neuen beliebigen Werte (`text-[13px]`, `leading-[…]`, `tracking-[…]`, `font-[…]`, `font-size:` in `.vue`-Dateien); der Test hat dafür ein Budget je Datei wie bei den Farben. Die Standardgrößen `text-xs` und `text-sm` bleiben bis zur Migration erlaubt, neue Stellen nehmen die Rollen.
    - Brauchen mehrere Stellen dieselbe neue Größe, wird zuerst eine Rolle ergänzt, nicht ein Einzelwert gesetzt.
13. **Wiederverwendung prüfen, Umbau besprechen.** Gilt für Bolt, kulibri und Claude Code gleichermaßen.
    - **Vor jedem neuen Baustein** (Komponente, Composable, Regelmodul, Dialog, Seitenleiste) suchen, ob es schon etwas Passendes gibt: `src/components/`, `src/composables/`, die Regelmodule und die bestehenden Views. Gibt es es, wird es benutzt oder erweitert, nicht daneben neu gebaut.
    - **Entsteht dabei eine dritte Kopie** desselben Musters (Hülle, Kopfzeile, Schalter, Dialog, Speicher-Aufruf), oder fällt beim Anfassen von Code etwas auf, das sich zusammenführen ließe: **nicht stillschweigend umbauen und nicht stillschweigend kopieren.** Den Vorschlag als PBI in `REFACTORING-ROADMAP.md` eintragen (Fundstellen, Nutzen, Umfang) und mit dem anderen Team besprechen, bevor gebaut wird.
    - **Ausnahme:** Eine kleine Extraktion, die ohne Verhaltensänderung im eigenen Änderungsumfang liegt, darf im selben PR passieren, mit einem Satz in der PR-Beschreibung.
    - **In jedem PR** steht ein Satz „Wiederverwendung geprüft: …" (was gefunden und benutzt wurde, oder warum nichts passte).
14. **Formularfelder und Knöpfe aus `src/components/ui/`.** `TextField`, `SelectField`, `TextAreaField` (Beschriftung, Fehlerzeile, Hinweis und ARIA sind eingebaut) und `AppButton`; keine rohen `<input>`, `<select>`, `<textarea>` und keine selbst gestalteten Knöpfe in Views.
    - Ein Feld ohne sichtbare Beschriftung (Uhrzeit in einer Zeile) bekommt `hide-label`, nicht gar keine. Felder in Zeilen: `size="sm"`; Zeit und Zahl: `align="center"`.
    - Weitere Attribute (`maxlength`, `placeholder`, `@blur`, `@input`) gehen an das Eingabeelement, `class` an den Rahmen (Breite). Die Optik steht in `.k-field-input` (`src/index.css`), nicht im View.
    - Ausnahmen (kein Textfeld): Checkbox, Radio, Regler, Farbe, Datei. Der Test `src/__tests__/formFieldsGuard.spec.ts` lässt keine neuen rohen Felder zu; die Dateien auf seiner Budget-Liste dürfen nur sauberer werden.

Begründung und Zahlen: `docs/kulibri-wiederverwendung-diskussion.md`.

## Referenzdokumente in docs/

Vor der Arbeit an einem Feature den jeweils aktuellen Stand lesen:

- **API-Vertrag:** `docs/kulibri-api-vertrag-bolt_3.md` (aktuellste Version, 30.08.2026)
- **Backend-Befunde:** `docs/kulibri-backend-befunde_1.md` — Sicherheit, Datenintegrität, Schema, bekannte Bugs G6/G7/G8
- **Backend-Anforderungen Anmeldung/Konto:** `docs/kulibri-backend-anforderungen-auth.md` — was das Backend für Registrierung, Anmeldung, Google-Login ergänzen muss
- **Link & Teilnahme:** `docs/kulibri-teilnahme-und-links.md`
- **Zeilen-Bearbeitung (verbindlich):** `docs/kulibri-bolt-prompt-zeilenbearbeitung.md`
- **Zweiphasige Zuteilung (künftig, nicht bauen):** `docs/kulibri-zweiphasige-zuteilung-anforderung_1.md`
- **Mockup (verbindliche Optik):** `docs/kulibri-schicht-zuteilung-final_8.html`
- **Requirements (laufend gepflegt):** `docs/requirements.md`
- **Paritätslücken zu Legacy:** `PARITY-GAPS.md`
- **Offene Fragen an den PO (Produkt, Preis, Recht):** `docs/po-fragen.md`; zur Optik: `docs/ui-po-fragen.md`
- **Prüfliste für das QA-Team (manuell, mit Stand):** `docs/qa-pruefliste.md`; neue Funktionen dort eintragen
- **Refactoring-Warteschlange (Regel 13):** `REFACTORING-ROADMAP.md`
