i18n er din oversættelse.
KDF er dit design.
Begge bor i JSON.
Et JSON-baseret designkoordineringslag til server-side web-apps og agent-assisteret UI. Gentagne beslutninger — layout, spacing, typografi og komponent-styling — bor i én fælles source of truth, som agenter kan læse, i stedet for at skulle genopdage dem på tværs af filer, sider og tidligere sessioner.
{ "$layout": ["hero", "footer"], "hero": { "wrapper": "mx-auto max-w-6xl px-6 py-20", "title": "@typography.h1", "cta-primary": "@button.cta" } }
Én fælles source of truth sikrer konsistens på tværs af alle sider, komponenter og agent-sessioner.
JSON definerer · kode renderer · data-kdf mapper tilbage
Design begynder at skride i
dine komponenter.
Når dine class names udelukkende bor i .tsx-filer, vil hver side langsomt udvikle sig i sin egen retning. Det fungerer fint for én enkelt udvikler — men det bliver skrøbeligt i det øjeblik, agenter begynder at pille ved dit UI.
<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
Den samme knap får pludselig fem uofficielle varianter. Spacing ændrer sig fra side til side. Hver ny agent-session er nødt til at gætte sig frem til reglerne helt fra bunden.
- — Agenter improviserer farver, spacing, typografi og layout.
- — Brugere skal rette resultatet i chatten, hver eneste gang.
- — Ændringer kræver, at man roder igennem utallige komponentfiler.
- — Gentagne sessioner mister blikket for det oprindelige design.
→ uendelig "større" · "mere blå" · "ryk til venstre" iteration
Gør designet eksplicit.
KDF gør for design, hvad i18n gør for tekst: det flytter gentagne beslutninger ud af dine komponentfiler og over i JSON. Det renderede UI bruger stadig helt almindelig CSS — det, der ændrer sig, er ejerskabet.
{ "hero": { "title": "text-5xl font-semibold tracking-tight" } }
const d = getDesign("homepage"); <h1 data-kdf="hero.title" className={d("hero.title")}>
Et bibliotek siger hvad.
KDF siger hvilken.
Et designbibliotek giver dig en knap. KDF fortæller dig, at dette er homepage.hero.cta-primary, renderet som en knap, og stylet med dette token. Det tilføjer den ene mapping, som biblioteker mangler — fra element til designbeslutning.
Seks symboler.
Én grammatik.
KDF gemmer class names, delte referencer, sektionsrækkefølge og CSS custom properties. Det gemmer aldrig forretningslogik, event handlers, data fetching, rettigheder eller accessibility-opførsel.
Ethvert element, der bruger et token, bærer en matchende sti. DOM-nodes peger direkte tilbage på JSON — super smart til scannere, tests og når agenter skal reviewe kode.
Resolveler en sti til sin className-streng. d.css() returnerer objektet med CSS custom properties.
Peg på et genanvendeligt token i shared/. Referencer kan chaines og udvides med ekstra klasser.
Et array af sektionsnøgler. Oplistede sektioner renderes i rækkefølge; dem der mangler, skjules af host-appen.
Metadata til agenter og host tooling — hvilken komponent renderer dette token, plus variant- og størrelseshints.
Værdier, der ikke kan udtrykkes som genanvendelige klasser, men tilføjes som inline style-variabler via d.css().
Delte defaults.
Side-overrides.
Design tokens bor to steder: genanvendelige defaults i shared/, og page composition der kun overrider det, der er brug for. To bruger-ejede CSS-filer tager sig af first paint og escape hatches.
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
En reference som @button.cta resolveler først fra sidens shared/, derefter en parent shared/ og til sidst sidens tokens. Skabeloner overrider kun det nødvendige og arver resten.
Designet resolveler på serveren; browseren modtager færdige class strings. Critical CSS lander i first paint, mens resten loades bagefter — ingen render-belastning på langsomme enheder.
Importeres af appen, så designvariabler og overrides (uden FOUC) ankommer i selve first paint — før noget som helst blinker på skærmen.
/* konde-server.css */ :root { --kdf-primary: #1F8F47; } [data-kdf="hero.slider"] { display: none; }
Loades efter frameworkets og appens egen CSS. Perfekt til småjusteringer, eksperimenter og escape hatches — finjusteringer, der aldrig behøver blokere paint.
/* konde.css */ [data-kdf="hero.title"] { letter-spacing: -0.02em; } [data-kdf="hero.wrapper"] { gap: 3rem; }
→ KDF opretter begge én gang og overskriver dem aldrig. Plugin'et eksponerer deres stier via env - din app sætter imports op; intet bliver injiceret magisk for dig.
Skift design
ligesom at skifte sprog.
Præcis som i18n skifter sprog, kan KDF skifte designskabeloner. Samme app, samme komponenter, samme kode — peg KDF_DIR på en anden designmappe, og hele looket ændrer sig.
designs/ lander/ shared/ homepage.json newlander/ shared/ homepage.json
// next.config.ts withKDF({ dir: "./designs/lander" })(nextConfig);
Resolve på serveren.
Send strings ned.
KDF's kerne læser JSON fra disken, så det kører server-side: Next.js Server Components, Astro renders og Hono handlers. Resolve klasser dér, og giv derefter helt almindelige strings videre til dine client components.
import { getDesign, cn } from "@kondeio/kdf"; const d = getDesign("homepage"); <button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
→ resolved className streng
→ objekt med CSS custom-properties
Sæt betingede klasser sammen, fjern falsy værdier og dedupliker — fuldstændig uden semantik som standard.
Produktion bruger cache; dev re-evaluerer ud fra mtime & størrelse.
Ligger ovenpå
dit stack.
STYLING — GEMMER CLASS NAMES, IKKE CSS
KDF er ikke en CSS engine. Tokens gemmer præcis de class strings, dit styling-system forstår. Hvis dit framework scanner dine source filer, peger du bare også den mod JSON: @source "../kdf/**/*.json".
RUNTIME — SERVER-SIDE JAVASCRIPT
Installer én gang.
Init opsætter resten.
Installationen opretter også automatisk en kdf/ startmappe, hvis den mangler. Eksisterende filer overskrives aldrig.
import withKDF from "@kondeio/kdf/plugin"; export default withKDF({ dir: "./designs" })(nextConfig);