


Eine CSS-in-JS-Bibliothek pflegen, die im Browser, auf dem Server und nativ funktioniert
Für die Arbeit eines KI-Coding-Assistenten an einer standardorientierten CSS-in-JS-Bibliothek. Erlaubt nur Standard-CSS, hält den Code in jeder Laufzeitumgebung lauffähig, schreibt Tests zuerst nach der Spezifikation und regelt Release Notes, Doku und Demos mit echtem Code.
Diese KI-Regeln verwenden
## Nur Standard-CSS in Styles annehmen und konfigurierte Standardwerte vorgehen lassen
Die verfasste Style-Oberfläche muss sich an echtem, standardkonformem CSS orientieren. Das hält das mentale Modell übertragbar und verhindert, dass die API in einen eigenwilligen Dialekt abdriftet.
- In verfassten Styles nur standardisierte Eigenschaftsnamen, Schreibweisen und Werte akzeptieren. Niemals nicht-standardisierte Aliase erfinden (zum Beispiel Kebab-Case-Namen für plattformspezifische Props). Plattformspezifische Style-Schlüssel gehören in ein explizites Ausweichventil (ein Inline-Style-Objekt oder vorgelagerte Plattformunterstützung), nicht in die Template-Sprache.
- Die Aufgabe der nativen Schicht besteht darin, idiomatisches CSS auf gleichwertige Plattform-Primitive abzubilden und das, was möglich ist, per Polyfill nachzubilden, bis die native Laufzeitumgebung aufholt. Sie ist nicht dazu da, die akzeptierte Eingabegrammatik zu erweitern.
### Vorrang konfigurierter Standardwerte
- Vom Autor konfigurierte Attribut-Standardwerte haben grundsätzlich Vorrang vor den vom Aufrufer übergebenen Props. Das ist ein bewusst gestalteter Vertrag, kein Fehler.
- Das Ausweichventil ist die Funktionsform der Standardwert-Konfiguration: Sie erhält die eingehenden Props und kann bedingt zurückfallen (den Wert des Aufrufers beibehalten oder einen Standardwert liefern).
- Ausnahme: Übergibt ein Aufrufer für eine Prop explizit `undefined`, wird der konfigurierte Standardwert für diese Prop unterdrückt.
## Den Paketmanager und das Commit-Format des Projekts nutzen
- Zu Beginn jeder Sitzung die aktuelle, für Endnutzer bestimmte Funktionsübersicht lesen, damit auf Basis des heute unterstützten Funktionsumfangs gearbeitet wird und nicht auf Basis erinnerten Verhaltens.
- Den für das Projekt festgelegten Paketmanager und die zugehörigen Befehle verwenden; keinen anderen einsetzen.
- Den Entwicklungsserver niemals selbst starten. Falls einer benötigt wird, den Maintainer bitten, ihn zu starten.
- Konventionelle Commit-Präfixe verwenden (`feat|fix|chore|refactor|test|docs|style|perf|build|ci`). Standardmäßig kurze Nachrichten: nur ein Titel oder ein Titel plus ein knapper Satz.
- Für den gesamten Fließtext (Kommentare, Dokumentation, Testtitel, für Nutzer sichtbare Zeichenketten) eine einheitliche englische Schreibweisenkonvention beibehalten. Die ursprüngliche Schreibweise nur innerhalb wörtlicher Zitate aus Spezifikationen oder Standards bewahren.
## Server, Browser und nativ unterscheiden und DOM-Code aus dem nativen Build heraushalten
Code, der für mehrere Laufzeitumgebungen ausgeliefert wird, darf keine einzelne Umgebung voraussetzen. Die Umgebung anhand mehrerer unabhängiger Signale erkennen und inkompatiblen Code an der Einstiegspunktgrenze isolieren.
- Die Umgebungserkennung nicht auf ein einziges universelles Flag reduzieren. Mindestens folgende Fälle unterscheiden: eine Build-Zeit-Serverkonstante (nur im Server-Build wahr), eine Laufzeit-Bedingung für Serverkomponenten (manche Frameworks liefern einen Build ohne clientseitige Context-APIs aus) sowie ein pro Anfrage gesetztes Server-Flag, das vom SSR-Einstiegspunkt gesetzt wird. Jede Entscheidung stützt sich nur auf die minimal notwendige Teilmenge an Signalen, die die jeweils relevanten Szenarien abdeckt. Häufige Falle: Wird DOM-Arbeit ausschließlich anhand der Build-Zeit-Serverkonstante unterdrückt, bricht der Testpfad für den Server-Build unter jsdom, bei dem DOM-Mutationen weiterhin stattfinden. DOM-Entscheidungen stattdessen anhand der Laufzeit-/SSR-Signale steuern.
- Der native Einstiegspunkt darf DOM-/Browser-Code niemals transitiv über Value-Imports importieren. Statt `instanceof` nur-Typ-Imports und mit Marken versehene Laufzeit-Tags (eine gemeinsame Symbol-Registry) verwenden. Mit einem Grep überprüfen, dass es im gebauten nativen Bundle null Referenzen auf `document.` gibt; manche native Laufzeitumgebungen scheitern bereits bei der Modulauswertung an jeder `document`-Referenz.
- Framework-Hooks, die nicht in jeder Laufzeitumgebung existieren (zum Beispiel ein Ref-Hook, der in Serverkomponenten undefiniert ist), müssen zur Dead-Code-Elimination hinter der Build-Zeit-Serverkonstante abgesichert werden. Sie niemals mit einer Laufzeitprüfung wie `typeof hook === 'function'` absichern, da dies zu einem bedingten Hook-Aufruf wird.
- Einen einzigen kanonischen Ausgabepfad beibehalten. Bei Änderungen an der Ausgabe die Test-Suites für Ausgabe sowie Parser/Compiler erweitern, statt einen parallelen Pfad hinzuzufügen.
## Code mit Build-Zeit-Konstanten entfernen und das Einstiegspunkt-Mapping mit Tests festlegen
Das, was der Bundler zur Build-Zeit eliminieren kann, von dem trennen, was erst zur Laufzeit existiert, und beim Mapping der Einstiegspunkte bewusst vorgehen.
- Build-Zeit-Konstanten (Server-Build, nativer Build, native-Web-Variante, Entwicklungsmodus) werden durch Literale ersetzt, damit Bundler den toten Zweig per Dead-Code-Elimination entfernen können. Bevorzugt den äußersten zusammenhängenden reinen Entwicklungsbereich in eine einzige Dev-Guard-Klausel einschließen; sich nicht allein auf einen Warnhelfer verlassen, um Arbeit zu überspringen, und niemals Meldungstexte oder Warnargumente außerhalb der Dev-Guard-Klausel erzeugen.
- Eine Laufzeitprüfung wie `typeof window !== 'undefined'` kann nicht per Tree-Shaking entfernt werden. Build-Zeit-Konstanten statt Laufzeitprüfungen verwenden, wenn Code physisch aus einem Bundle entfernt werden muss.
- Das Mapping von Einstiegspunkten und Unterpfaden ist eine häufige Quelle stiller Fehlfunktionen. Die Auflösung über Plattform-Dateiendungen (bei der der native Bundler eine plattformspezifische Datei wählt) ist sicherer als eine `browser`-Objektzuordnung, die manche native Bundler auf jeder Plattform anwenden und die dabei still eine Web-Bridge auf die native Umgebung leiten kann. Ein `.js`-Fallback sollte die sichere plattformübergreifende Bridge sein, niemals die plattformspezifische Engine. Diese Auflösungen mit einem Auflösungs-/Tree-Shake-Test absichern.
- Ein `browser`-Feld gegenüber bedingten `exports` bevorzugen, wenn letztere die Typauflösung in zusammengesetzten Projekten (Composite Projects) beeinträchtigen. Jedes veröffentlichte Unterpfad-Verzeichnis in die `files`-Liste des Pakets aufnehmen.
## Zuerst einen fehlschlagenden Test schreiben und Optimierungen mit echter Last messen
- Strikte testgetriebene Entwicklung ist im gesamten Repository verpflichtend. Vor jeder Änderung an Produktionscode einen fehlschlagenden Test hinzufügen oder erweitern, der den gewünschten Vertrag abbildet, und anschließend nur so viel implementieren, dass er besteht. Kein für Nutzer sichtbares Verhalten wird ausgeliefert, ohne dass es einen Test gibt, der ohne die Änderung fehlschlagen würde. Für Arbeiten ohne neue Funktionen gilt dieselbe Rot-Grün-Disziplin.
- Optimierungen stets per Mikrobenchmark gegen eine realistische Arbeitslast prüfen, nicht gegen einen synthetischen Bestfall. Jede Änderung zurücknehmen, die den von echten Aufrufern genutzten Pfad verschlechtert, selbst wenn sie isoliert betrachtet einen Vorteil bringt.
- Auf geringen Speicherdruck und monomorphe Funktionen hin optimieren.
- Jedes spezifikationsgestützte Verhalten auf den aktuellen Editor-Entwurf der maßgeblichen Spezifikation stützen, nicht auf Zusammenfassungen, Referenzseiten oder das Gedächtnis. Den relevanten Abschnitt für die Sitzung neu abrufen, die normative Klausel wörtlich als Kommentar über dem sie absichernden Test zitieren und pro Regel einen Test innerhalb eines klar benannten Spezifikationskonformitäts-Blocks schreiben. Ist die Spezifikation dazu still oder mehrdeutig, die Abweichung neben dem Test dokumentieren und das zugehörige Tracking-Issue verlinken. Dies gilt für jede Änderung, die eine Spezifikation berührt.
## Jede Spezifikationsregel als Test schreiben, bevor ein nativer Polyfill entsteht
Wenn die Style-Engine der nativen Laufzeitumgebung ein CSS-Feature nicht versteht, wird es per Polyfill nachgebildet — das Verhalten aber zunächst anhand der Spezifikation absichern, bevor interne Strukturen refaktoriert werden.
Vorgehen für einen neuen oder überarbeiteten Polyfill (ebenso für jeden spezifikationsgestützten Validierungsblock):
1. Den aktuellen Editor-Entwurf für die Sitzung abrufen. Klauselnummern und Formulierungen ändern sich, daher niemals einen alten Auszug als maßgeblich behandeln.
2. Jede Regel der Spezifikation in genau einen Test übersetzen, mit dem wörtlichen Spezifikationstext als Zitat darüber, innerhalb eines benannten Spezifikationskonformitäts-Blocks in der jeweiligen Test-Suite.
3. Die Tests zuerst schreiben und festhalten, welche davon aktuell fehlschlagen.
4. So lange implementieren, bis die Tests bestehen. Bestehende Tests nicht an die Implementierung anpassen; die Spezifikation ist die maßgebliche Quelle.
5. Die vollständigen nativen und die Haupt-Test-Suites auf Regressionen laufen lassen.
Sobald der Spezifikationsblock grün ist, dürfen die internen Strukturen (Tokenisierung, AST, Evaluator) frei refaktoriert werden; der Block sichert das für Nutzer beobachtbare Verhalten ab.
- Die für Endnutzer bestimmte Übersicht zur nativen Kompatibilität stets aktuell halten, sobald neue Laufzeitversionen ausgeliefert werden, sich die Unterstützung ändert oder Polyfills hinzugefügt, entfernt oder angepasst werden.
- Ein Feature ohne tragfähige native Umgehungslösung muss eine deduplizierte Warnung mit einem stabilen Code ausgeben, der das betroffene Konstrukt, den Grund für die Nichtausführbarkeit und eine konkrete Alternative benennt, und anschließend die Deklaration verwerfen (Rückfall auf null), statt Unsinn auszuliefern.
- Varianten-Parität: Liefert der Browser ein Feature bereits aus, das rohe CSS unverändert durchreichen; niemals eine Eigenschaft ausgeben, die der Browser noch nicht unterstützt; ausschließlich native Prop-Erweiterungen und Enum-Erweiterungen hinter der nur-nativ-Build-Konstante absichern. Jedem Polyfill-Spezifikationsblock eine Paritäts-Unter-Suite geben, die die Web-Variante umschaltet und deren sichtbare Ausgabe absichert, und jede normative Regel, die auf eine bestimmte Variante nicht zutrifft, explizit mit derselben Sorgfalt wie einen Abweichungskommentar ausschließen.
## In Release Notes nur für Nutzer Sichtbares beschreiben und jede Doku am richtigen Ort ablegen
Register und Inhalt jedes Dokuments an seine Zielgruppe anpassen.
- Für Endnutzer bestimmte Texte (Release Notes, Changelog-Einträge, PR-Beschreibungen, öffentliche Dokumentation) benennen ausschließlich für Nutzer beobachtbares Verhalten, in Worten, die auch jemand versteht, der den Quellcode nicht gelesen hat. Benennen, was unterstützt wird und was nicht, sowie die Grenzen der jeweiligen Änderung; dabei die Kompatibilitätsmatrix verlinken, statt unabhängige Lücken aufzulisten. Keine internen API-Namen, Mechanismen oder Codepfade; diese gehören in den Commit-Text und den Leitfaden für Mitwirkende.
- Verhalten so beschreiben, wie es aktuell ist. Verlaufsschilderungen ("bisher", "nicht mehr", "jetzt", "ersetzt") für Zustände vermeiden, die keine veröffentlichte Version je auslieferte; einen Fix an einem noch unveröffentlichten Feature in die Release Note dieses Features einarbeiten.
- Release Notes nur für Änderungen erstellen, die für Nutzer sichtbar sind (Fehlerbehebungen, neue Funktionen, Breaking Changes). Interne Refaktorierungen, Tooling, Tests sowie Korrekturen an Code, der in derselben noch unveröffentlichten Version eingeführt wurde, auslassen.
- Automatisch generierte Dateien (Changelogs, generierte Fehler-Zuordnungen) nicht von Hand bearbeiten; sie über das jeweilige Tool neu generieren.
- Konkrete Namen von KI-Anbietern aus der für Mitwirkende bestimmten Dokumentation heraushalten; stattdessen neutrale Formulierungen wie „ein KI-gestützter Coding-Assistent" verwenden.
- Fließtext in PR-Beschreibungen, Issue-Beschreibungen oder Kommentaren nicht manuell umbrechen; einzeilige Absätze fließen sich automatisch neu, während manuelle Umbrüche in mobilen und zitierten Ansichten fehlerhaft wirken. Commit-Message-Texte dürfen weiterhin die 72-Zeichen-Konvention einhalten.
### Platzierung der Dokumentation
- Der Leitfaden für Mitwirkende enthält übergreifende Regeln, Invarianten und erarbeitetes Wissen, das in Quellcode-Kommentaren keinen natürlichen Platz hat; gut beschriebene Mechanismen gehören dort nicht hin.
- Eigenständige Wissensdokumente halten Fallstricke und erarbeitetes Wissen fest, nicht Schritt-für-Schritt-Erklärungen zu Feature-Mechanismen; für den Mechanismus ist der Quellcode maßgeblich.
- Das „Warum" auf Quellcode-Ebene steht in Kommentaren bzw. JSDoc direkt neben dem Code. Spezifikationszitate nicht im Produktionscode oder in Warnmeldungen wiederholen; Anker, normative Zitate und Begründungen gehören in den absichernden Test. Warnmeldungen benennen ausschließlich das betroffene Konstrukt und die konkrete Alternative, sonst nichts.
## Gemessene Performance-Muster nutzen und Demos bauen, die echten Code ausführen
Durch Mikrobenchmarks auf einer verbreiteten JavaScript-Engine validierte Muster (als Ausgangshypothesen behandeln; im jeweiligen Kontext erneut messen):
- String-Verkettung mit `+=` schlägt `array.push()` + `join()` bei jeder Größenordnung.
- Das Spreaden mit `{...props, extra}` schlägt `Object.assign` oder eine Kopie per `for..in`.
- `for..in` schlägt `Object.keys()` in Kombination mit einer Schleife.
- Kompilierte reguläre Ausdrücke in einer Map zwischenspeichern; eine vorgeschaltete `indexOf`-Prüfung, die Arbeit komplett überspringt, bringt einen größeren Vorteil.
- Manuelle Verkettung mit `+` schlägt Template-Literale in eng getakteten Schleifen.
- Das direkte Erzeugen roher Element-Objekte (mit dem Element-Tag des Frameworks) ist deutlich schneller als die Element-Factory des Frameworks.
- `new Array(n)` erzeugt lückenhafte Arrays, die das Type-Feedback verfälschen; bei performancekritischen Arrays keine Vorab-Größenfestlegung vornehmen.
Engine- und Sprach-Fallstricke:
- Ein `private`-Modifikator ist bei einem anonymen Klassenausdruck, der einer Konstante zugewiesen wird, nicht zulässig.
- Ein nur-Typ-Sternimport kann weiterhin die Modulauflösung des Bundlers auslösen, obwohl das Typsystem ihn entfernt.
Integrität von Demos und visueller Qualitätssicherung (für jede Showcase, die Verhalten belegen will):
- Null Toleranz für vorgetäuschte Demos. Jedes Widget muss den echten Laufzeitpfad durchlaufen, den es zu demonstrieren behauptet. Kann ein Feature auf einer Plattform nicht ausgeführt werden, soll die betreffende Zelle sichtbar fehlschlagen (defektes Layout, Warnung, fehlendes Glyph); dieses Scheitern ist die Demo. Niemals ein Mock einsetzen, das die Spezifikation nur nachahmt, und niemals eine Bestanden/Fehlgeschlagen-Farbe fest codieren als Ersatz dafür, dass der echte Pfad tatsächlich ausgelöst wird.
- In der Showcase plattformübergreifende Komponenten ohne Plattformverzweigungen verwenden; Workarounds für Plattformabweichungen gehören in die Bibliothek, nicht in die App.
- Funktionierend gegenüber defekt soll auf einen Blick aus der Distanz erkennbar sein, anhand grober Unterschiede (Layoutverschiebungen, Farbflächen, Vorhandensein/Fehlen), und jedes Widget muss sowohl im hellen als auch im dunklen Modus korrekt lesbar sein.
