Zum Inhalt
Hey AlbertMarke und Designsystem
Als MarkdownEnglishEN

Entwickeln

Wie wir entwickeln

Eine Quelle, viele Oberflächen. Wie Tokens, Bauteile und Prüfer zusammenhängen, welche Regeln im Code gelten und wann eine Ansicht fertig ist.

Hey Albert läuft im Browser, auf iPhone, iPad, Mac und Watch. Alle Oberflächen zeigen dieselben Zeilen aus derselben Datenbank. Und alle tragen dieselbe Gestaltung aus derselben Quelle: packages/design-system.

Dieses Kapitel ist für alle, die Code schreiben. Das gilt für Menschen im Team, für externe Fachleute und für Agenten.

Eine Quelle

Jeder Wert der Marke steht genau einmal im Repository. Farben, Maße, Schriften und Bewegungen liegen in packages/design-system/tokens/quelle/*.json. Alles andere verweist darauf.

WasWoWird zu
Tokenstokens/quelle/*.json (Format der W3C Design Tokens Community Group)tokens/*.css, tailwind/theme.css, swift/Tokens.swift
Bauteilecomponents/<gruppe>/<Name>.jsx mit .d.ts und .prompt.mdVorlage für apps/web/src/bausteine und für SwiftUI
Web-Primitivebauteile/ui/*.tsx (shadcn auf unseren Rollen)Formulare, Dialoge, Tabellen im HQ und auf der Website
Website-Blöckebloecke/*.tsx, eins zu eins zu packages/content-modeldie Seiten von hey-albert.app aus Payload
Regelnregeln/regeln.jsondiese Seite, Brand-QA, Agenten
Schriften, Zeichen, Logosassets/alle Oberflächen, lokal ausgeliefert

Die Reihenfolge

Jeder Bereich entsteht in derselben Folge. So steht das Fundament, bevor jemand eine Fläche sieht.

  1. Schema und RLS. Die Tabelle mit household_id, Index und vier Policies, in einer Migration.
  2. Tests. pgTAP für alle fünf Rollen: owner, adult, child, guest, service.
  3. Domänenlogik. Reine Funktionen ohne Oberfläche, mit eigenen Tests.
  4. Oberfläche. Aus Bauteilen des Systems, gegen den Seed von Familie Sonntag.

Gegen leere Screens wird nie gebaut. Der Seed-Haushalt hat eine echte Woche: Mo 1. bis So 7. September, heute ist Mittwoch.

Der Stack je Oberfläche

Web-App und HQ

apps/web ist Next.js 16 mit App Router. Die Tokens kommen als CSS-Variablen direkt aus dem Paket, im Layout per Import von tokens/colors.css und den übrigen Token-Dateien. Tailwind dient nur Layout-Hilfen wie Raster, Abstände und Umbrüche. Farbe, Schrift und Radius laufen über Rollen.

Die Bauteile in apps/web/src/bausteine sind die Produktionsfassungen der Bauteile im System. Rahmen.tsx ist LeisteMac und Kopfzeile, Zeichen.tsx ist Icon. Weicht eine Fassung ab, ist das ein Fehler, kein Stil.

Website

apps/site baut hey-albert.app aus Payload. Jeder Block im Inhaltsmodell hat genau ein Bauteil in packages/design-system/bloecke. RenderBloecke wählt nach blockType. pnpm test im Paket prüft, dass kein Block ohne Bauteil bleibt.

Apple

apps/apple wird SwiftUI Multiplatform mit Swift 6 und strikter Nebenläufigkeit. Die Rollen liegen in swift/Tokens.swift: AlbertFarbe, AlbertRaum, AlbertSchrift, AlbertForm, AlbertBewegung. Jede Farbe trägt hell und dunkel und entscheidet zur Laufzeit.

Tokens als Code

Die Quelle ist JSON im Format der W3C Design Tokens Community Group, ein Satz je Datei: farben-hell, farben-dunkel, schrift, raum, form, bewegung. Style Dictionary 5 erzeugt daraus drei Ausgaben, ohne Werte umzurechnen.

cd packages/design-system
pnpm tokens        # erzeugen und gegen die eingefrorene Referenz prüfen
pnpm tokens:diff   # nur prüfen

tokens-diff vergleicht jedes Paar aus Name und Wert mit tokens/referenz/. Weicht ein Wert ab, bricht der Lauf ab. Neue Rollen stehen mit Begründung in tokens/referenz/ergaenzungen.txt.

Die erzeugten Dateien tragen in der ersten Zeile „Erzeugt aus tokens/quelle“. Niemand ändert sie von Hand. Der GitHub-Lauf design.yml erzeugt sie neu und prüft, dass nichts abweicht.

Regeln im Code

  • Kein Hex-Wert in einem Bauteil. Farbe läuft über Rollen (--grund, --karte, --tinte, --akzent).
  • Keine Schatten, nirgends. Tiefe kommt aus Schleier, stärkerer Kontur und Kippung.
  • Bedeutungen werden nicht getauscht: Rosa = Akzent und Jetzt, Gelb = Familie und Ritual, Blau = Fahrt, Offen-Rosa nur als gestrichelter Rand für „ohne Zuständigen“. Rosa heißt nie „Fehler“.
  • Farbe ist nie der einzige Träger. Initiale oder Name steht dabei.
  • Inaktiv ist eine gerechnete Rolle, keine Deckkraft.
  • Text und Bedienelemente mindestens 4,5:1, Flächen und Konturen mindestens 3:1.
  • Zielflächen: Zeiger 28, Finger 44, Kind 56 px — nie darunter.
  • Fokus immer über :focus-visible: 2 px Ring in Offen-Rosa mit 2 px Abstand.
  • 120 ms Zustände, 200 ms Einblendungen, 300 ms Atem. Kein Federn, kein Kreisel. Bei reduzierter Bewegung steht alles still.
  • Skelett statt Kreisel. Das Skelett hat die Form des Inhalts.
  • Jede Änderung ist optimistisch und hat „Rückgängig“.
  • Schriften werden lokal ausgeliefert, nie von Google-Servern.
  • Kein Emoji, keine Unicode-Zeichen als Icon-Ersatz.
  • Fehlt ein Zeichen, wird es aus dem Satz geholt, nicht erfunden.

React mit Tailwind

Das Tailwind-Theme kennt nur unsere Rollen. Tailwinds eigene Palette, Schatten und Radien sind abgeschaltet. bg-red-500 oder shadow-md gibt es deshalb gar nicht.

Inaktiv ist eine gerechnete Rolle: disabled:bg-knopf-inaktiv-flaeche disabled:text-knopf-inaktiv-text. Deckkraft multipliziert sich mit dem Untergrund. Dann stimmt keine gerechnete Kontrastzahl mehr.

SwiftUI

Schriften lokal

Die vier Schriften liegen als woff2 für das Web und als TTF für die App im Paket. Nichts wird von Google-Servern geladen. Sonst ginge die IP-Adresse jedes Besuchers in die USA. Das LG München I hat das 2022 als Rechtsverletzung gewertet.

Fokus

Fokus zeigt sich immer über :focus-visible, nie über :focus. Der Ring ist 2 px breit, in --rand-fokus, mit 2 px Abstand. So sieht ihn, wer mit der Tastatur arbeitet, und niemand sonst.

Prüfer

PrüferWas er findetBefehl
Brand-QAHex-Wert außerhalb der Quelle, Schatten, freie Radien, verbotene Wörter, Ausrufezeichen, Bild ohne altpnpm qa im Paket
Token-DiffWerte, die von der eingefrorenen Referenz abweichenpnpm tokens:diff
BlöckeBlock im Inhaltsmodell ohne Bauteilpnpm test
StorybookTokens, Primitive, jeder Block in de, en, tr, hell und dunkel, Handy und Tischpnpm storybook (Port 3112)
Bildvergleichjede Story hell und dunkel, Handy und Tisch, Schwelle 0,1 %pnpm vr, Referenzen neu: pnpm vr:update
KontrastPflichtpaarungen nach WCAG in beiden Modipython3 tooling/check-kontrast.py
SpracheSatzlänge, Register, Wortlistenpython3 tooling/check-sprache.py
Agent design-prueferToken-Verstöße und Definition of Done einer Ansicht, nur lesendin Claude Code vor jedem „fertig“
Kapitel dieser SeiteDirektiven, Argumente, Sprachenode apps/brand/skripte/pruefen.ts

Der GitHub-Lauf design.yml startet bei jeder Änderung unter packages/design-system. Er erzeugt die Tokens, prüft die Referenz, testet die Blöcke, läuft Brand-QA und Typen, baut Storybook und vergleicht die Bilder.

Fertig ist eine Ansicht erst mit

  • leerer Zustand
  • Skelett statt Kreisel
  • Tastatur und :focus-visible
  • Handy und Tisch
  • hell und dunkel als Token-Umschaltung
  • optimistisches Update mit „Rückgängig“
  • richtiges Register
  • kein Hex-Wert
  • Zielflächen 28/44/56

Auf dem Mac gehört Tastaturbedienung dazu, auch für Ziehen und Ablegen. In der App gehören Dynamic Type und VoiceOver dazu. Konflikte sind sichtbar, aber sie blockieren nicht.

Ein neues Bauteil

Kein Bauteil entsteht nur in einer App. Was in apps/web, in der Swift-App oder auf der Website gebaut wird, kommt zuerst oder spätestens im selben Commit ins System.

  1. components/<gruppe>/<Name>.jsx mit allen Zuständen: Standard, gedrückt, fokussiert, inaktiv, leer, hell und dunkel, Kind-Größe, wo Kinder bedienen.
  2. <Name>.d.ts mit deutschen Props.
  3. <Name>.prompt.md: wofür, welches Register, ein Beispiel mit Familie Sonntag, die Grenzen.
  4. Eine @dsCard-Karte im Ordner und ein Eintrag in _ds_manifest.json.
  5. Die Produktionsfassung in der App, mit gleichem Namen und gleichen Props.
  6. pnpm qa, Storybook-Story, Bildvergleich.

Ein bestehendes Bauteil ändern heißt: erst .prompt.md lesen, dann das JSX, dann die Fassung in der App.

Einen Token ändern

  1. Den Wert in tokens/quelle/*.json ändern, bei Farben hell und dunkel.
  2. pnpm tokens laufen lassen. Der Diff bricht ab und zeigt die Abweichung.
  3. Die Änderung mit Datum, Kontext und Grund in docs/entscheidungen.md eintragen.
  4. Die Referenz in tokens/referenz/ neu einfrieren.
  5. Kontrast und Bildvergleich prüfen, dann die erzeugten Dateien mit einchecken.

Eine neue Rolle braucht keine Entscheidung, aber eine Zeile in ergaenzungen.txt mit Grund. Eine bestehende Rolle ändert sich nur mit Entscheidung.

Git und Veröffentlichen

Commits schreibt das Konto guido77-EnP, auf Deutsch, der Betreff als Satz. Vor jedem git push wird gefragt. Danach prüft tooling/deploy-pruefen.sh die Bauten von albert-web, albert-site und den GitHub-Lauf. Ein roter Bau bleibt nie stehen.

Screens, Stories und Beispiele zeigen immer Familie Sonntag. Echte Familiendaten gehören nie ins Repository. Der Seed ist zugleich der Zugang für Apples App-Review.