Konde Design Framework

i18n ist für deine Übersetzungen.
KDF ist für dein Design.
Beides lebt in JSON.

Ein JSON-basierter Design-Coordination-Layer für server-seitige Web-Apps und agentengestützte UIs. Wiederkehrende Entscheidungen — Layout, Spacing, Typografie, Komponenten-Styling — leben in einer einzigen Source of Truth. Deine Agenten lesen sie, anstatt sie immer wieder neu aus Dateien, Seiten und vergangenen Sessions zusammenzusuchen.

Sieh dir an, wie es funktioniert
kdf / homepage.json → gerendert
kdf/homepage.json
{
  "$layout": ["hero", "footer"],
  "hero": {
    "wrapper": "mx-auto max-w-6xl px-6 py-20",
    "title":   "@typography.h1",
    "cta-primary": "@button.cta"
  }
}
data-kdf="hero.title"
Bauen und shippen mit KI.
data-kdf="hero.body"

Eine einzige Source of Truth hält jede Seite, jede Komponente und jede Agenten-Session konsistent.

data-kdf="hero.cta-primary"
Loslegen →

JSON definiert · Code rendert · data-kdf mappt zurück

Lizenz
MIT
Runtime
Node Filesystem
Dependencies
Zero Runtime
Getestet mit
Next · Astro · Hono
01 — Das Problem

Design verliert sich
in deinen Komponenten.

Wenn Class-Namen nur in .tsx-Dateien leben, driftet jede Seite langsam ab. Für einen menschlichen Entwickler mag das noch funktionieren — aber sobald Agenten das UI anfassen, wird es extrem fragil.

ohne KDF · über Dateien verstreut
<section className="mx-auto max-w-6xl px-6 py-20">
  <h1 className="text-5xl font-semibold tracking-tight">
  // …and again, slightly different, on the next page

Derselbe Button bekommt unbemerkt fünf verschiedene Varianten. Die Abstände ändern sich von Seite zu Seite. Bei jeder neuen Agenten-Session müssen die Regeln wieder komplett von vorn herausgefunden werden.

DAS ERGEBNIS
  • Agenten improvisieren bei Farben, Spacing, Typografie und Layout.
  • Nutzer müssen das Ergebnis jedes Mal im Chat korrigieren.
  • Änderungen bedeuten endloses Suchen in Komponenten-Dateien.
  • Wiederholte Sessions verlieren die ursprüngliche Design-Intention aus den Augen.

→ endlose "größer" · "blauer" · "weiter nach links" Iteration

02 — Die Lösung

Mach Design explizit.

KDF macht für das Design genau das, was i18n für Texte macht: Es lagert wiederkehrende Entscheidungen aus den Komponenten-Dateien in eine JSON aus. Das gerenderte UI nutzt immer noch normales CSS — was sich ändert, ist nur die Ownership.

1 — in JSON definieren
{
  "hero": {
    "title": "text-5xl font-semibold tracking-tight"
  }
}
2 — im Code rendern
const d = getDesign("homepage");

<h1 data-kdf="hero.title" className={d("hero.title")}>
JSON definiert
Eine einzige Datei gibt die Design-Richtung vor. User können sie direkt bearbeiten, wenn sie volle Kontrolle brauchen.
Code rendert
Deine Komponenten lesen die Tokens und rendern das freigegebene Design mit ganz normalem CSS — keine Magic unter der Haube.
Agenten implementieren
Agenten bauen UIs auf Basis der JSON, anstatt blind zu raten. Keine erfundenen Abstände, Farben, Typografien oder Section-Reihenfolgen mehr.
Nutzer passen die JSON an
Ändere die Quelle ein einziges Mal, anstatt dem Agenten in jeder Session aufs Neue dieselbe visuelle Korrektur im Chat erklären zu müssen.
03 — Keine Komponenten-Library

Eine Library sagt dir das Was.
KDF sagt dir welches.

Eine Design-Library gibt dir einen Button. KDF sagt dir, dass das hier homepage.hero.cta-primary ist, gerendert als Button, gestylt mit genau diesem Token. Es liefert das entscheidende Mapping, das Libraries oft auslassen — das Mapping vom Element zur eigentlichen Design-Entscheidung.

 Design-LibraryKDF
Was sie aussagt"Das hier ist ein Button.""Das hier ist hero.cta-primary auf homepage."
MappingGenerische Komponente, unzählige Override-Möglichkeiten.Ein Element mappt genau auf einen Design-Key.
RückverfolgbarkeitKein exaktes Mapping vom Element zur Entscheidung.data-kdf verlinkt jeden DOM-Node direkt mit seinem JSON-Pfad.
Sitzt eine Ebene über shadcn · Bootstrap · Chakra · Tailwind · plain CSS · deinem eigenen System — KDF ist kein Ersatz für all diese Tools.
04 — Das Vokabular

Sechs Symbole.
Eine Grammatik.

KDF speichert Class-Namen, Shared References, die Reihenfolge von Sections und CSS Custom Properties. Was es niemals speichert: Business-Logik, Event-Handler, Data Fetching, Permissions oder Accessibility-Verhalten.

data-kdf
Die Map

Jedes Element, das ein Token verwendet, trägt einen passenden Pfad. DOM-Nodes lassen sich so direkt auf die JSON zurückführen — perfekt für Scanner, Tests und Agenten-Reviews.

data-kdf="hero.title"
d(path)
Der Accessor

Löst einen Pfad zu seinem className-String auf. d.css() gibt das CSS Custom Properties Objekt zurück.

className={d("hero.title")}
@
Shared Reference

Verweist auf ein wiederverwendbares Token in shared/. Refs können verkettet und mit extra Klassen erweitert werden.

"@button.cta" shadow-xl
$layout
Reihenfolge & Sichtbarkeit

Ein Array von Section-Keys. Aufgelistete Sections werden in genau der Reihenfolge gerendert; fehlende werden von der Host-App einfach ausgeblendet.

["hero", "features", "footer"]
$
Komponenten-Identität

Metadaten für Agenten und Host-Tooling — welche Komponente dieses Token rendert, inklusive Varianten- und Größen-Hinweisen.

"$": "Button"
css
Custom Properties

Werte, die sich nicht als wiederverwendbare Klassen ausdrücken lassen, werden über d.css() als Inline-Style-Variablen angewendet.

{ "--kdf-accent": "#4F46E5" }
05 — Architektur

Shared Defaults.
Page Overrides.

Design-Tokens leben an zwei Orten: wiederverwendbare Defaults in shared/, und Page-spezifische Kompositionen, die nur das überschreiben, was wirklich nötig ist. Zwei vom User verwaltete CSS-Dateien kümmern sich um First-Paint und eventuelle Escape-Hatches.

Projekt-Struktur
kdf/
  shared/
    button.json      ← reusable defaults
    card.json
    color.json
    typography.json
  homepage.json      ← page composition
  konde-server.css   ← critical, first paint
  konde.css          ← non-critical tweaks
Multi-level Cascade

Eine Referenz wie @button.cta wird zuerst in den shared/-Tokens der Seite, dann im übergeordneten shared/ und schließlich in den Page-Tokens aufgelöst. Templates überschreiben nur die Teile, die sie wirklich ändern müssen, und erben den Rest.

Standardmäßig schlank

Das Design wird auf dem Server aufgelöst; der Browser bekommt nur die fertigen Class-Strings. Kritisches CSS ist schon beim First-Paint da, der Rest lädt danach — keine Render-Kosten für Low-Spec-Clients.

ZWEI USER-CSS-DATEIEN · ZWEI LADEZEITPUNKTE
konde-server.css
critical · first paint

Wird direkt von der App importiert, damit Design-Variablen und No-FOUC-Overrides schon beim ersten Paint verfügbar sind — bevor überhaupt etwas aufblitzt.

/* konde-server.css */
:root { --kdf-primary: #1F8F47; }
[data-kdf="hero.slider"] { display: none; }
konde.css
non-critical · after app css

Lädt nach dem Framework- und App-CSS und ist perfekt für Tweaks, Experimente und Escape-Hatches — Feintuning, das den initialen Paint nicht blockieren muss.

/* konde.css */
[data-kdf="hero.title"] { letter-spacing: -0.02em; }
[data-kdf="hero.wrapper"] { gap: 3rem; }

→ KDF erstellt beide Dateien nur ein einziges Mal und überschreibt sie nie wieder. Das Plugin stellt ihre Pfade per Env-Variable bereit – deine App kümmert sich um den Import; es wird dir nichts ungefragt reingedrückt.

06 — Multi-Template

Design switchen,
als wäre es die Sprache.

Genauso wie du mit i18n die Sprache wechselst, kannst du mit KDF Design-Templates austauschen. Gleiche App, gleiche Komponenten, gleicher Code — lass KDF_DIR einfach auf einen anderen Design-Ordner zeigen und der komplette Look ändert sich.

designs/ — zwei Templates, eine App
designs/
  lander/
    shared/
    homepage.json
  newlander/
    shared/
    homepage.json
// next.config.ts
withKDF({ dir: "./designs/lander" })(nextConfig);
$layout Reihenfolge ändern oder Sections ausblenden, komplett ohne Komponenten-Code anzufassen.
@button Über ein einziges Shared-Token jeden CTA im Projekt auf einmal ändern.
KDF_DIR Das komplette Design-Template als bewusste Entscheidung auf Host-Ebene austauschen.
07 — Runtime-API

Auf dem Server auflösen.
Strings nach unten reichen.

Der KDF-Core liest JSON von der Disk, läuft also server-seitig: in Next.js Server Components, Astro-Renders und Hono-Handlern. Löse die Klassen dort auf und reiche einfache Strings an die Client-Komponenten weiter.

Server-Component
import { getDesign, cn } from "@kondeio/kdf";

const d = getDesign("homepage");

<button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
d("hero.title")

→ aufgelöster className-String

d.css("hero.title")

→ CSS Custom Properties Objekt

cn · cx · dedupeClasses

Verbindet bedingte Klassen, entfernt Falsy-Werte und Duplikate — standardmäßig komplett frei von zusätzlicher Semantik.

cache: auto · always · none

In Production gecacht; im Dev-Modus Revalidierung via mtime & Größe.

08 — Kompatibel by Design

Es sitzt eine Ebene über
deinem Stack.

STYLING — SPEICHERT CLASS-NAMEN, KEIN CSS

TailwindshadcnBootstrapChakraCSS ModulesPlain CSSYour own system

KDF ist keine CSS-Engine. Die Tokens speichern einfach nur die Class-Strings, die dein Styling-System versteht. Wenn dein Framework Source-Dateien scannt, richte es einfach zusätzlich auf die JSON: @source "../kdf/**/*.json".

RUNTIME — SERVER-SEITIGES JAVASCRIPT

Next.js getestet · plugin
Astro getestet
Hono getestet
Loslegen

Einmal installieren.
Init scaffoldet den Rest.

Die Installation scaffoldet auch direkt einen initialen kdf/-Ordner, falls noch keiner existiert. Bereits vorhandene Dateien werden niemals überschrieben.

$npm install @kondeio/kdf
$pnpm add @kondeio/kdf
$bun add @kondeio/kdf
$npm exec -- kdf init # manueller Scaffold
next.config.ts
import withKDF from "@kondeio/kdf/plugin";

export default withKDF({ dir: "./designs" })(nextConfig);