i18n è per le traduzioni.
KDF è per il design.
Entrambi vivono nel JSON.
Un layer per coordinare il design basato su JSON per web app server-side e UI fatte assieme agli agenti. Le scelte di design ricorrenti — layout, spaziature, tipografia, stili — vivono in un'unica source of truth che i tuoi agenti possono leggere, così smettono di rincorrerle tra i vari file, le pagine e le sessioni passate.
{ "$layout": ["hero", "footer"], "hero": { "wrapper": "mx-auto max-w-6xl px-6 py-20", "title": "@typography.h1", "cta-primary": "@button.cta" } }
Una singola source of truth tiene allineate tutte le pagine, i componenti e le sessioni degli agenti.
Il JSON definisce · il codice renderizza · data-kdf fa da mappa
Il design va alla deriva
nei tuoi componenti.
Quando i nomi delle classi vivono solo nei file .tsx, pagina dopo pagina tutto inizia a sfaldarsi. Finché c'è solo un dev umano va bene — ma il castello crolla non appena ci mettono mano gli agenti.
<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
Lo stesso bottone si ritrova silenziosamente con cinque varianti diverse. Le spaziature ballano da una pagina all'altra. Ogni volta che apri una nuova sessione, l'agente deve re-impararsi le regole da capo.
- — Gli agenti si inventano colori, spaziature, tipografia e layout.
- — Devi stare lì a correggere i risultati in chat, ogni singola volta.
- — Ogni modifica ti costringe a spulciare i file dei componenti.
- — Sessione dopo sessione, si perde l'intento originale del design.
→ un'infinita iterazione a botte di "fammelo più grande" · "più sul blu" · "sposta a sinistra" senza fine
Rendi il design esplicito.
KDF fa per il design quello che i18n ha fatto per i testi: tira fuori le decisioni ripetitive dai componenti e le piazza nel JSON. Sotto il cofano la UI usa ancora del normalissimo CSS — cambia solo chi lo comanda.
{ "hero": { "title": "text-5xl font-semibold tracking-tight" } }
const d = getDesign("homepage"); <h1 data-kdf="hero.title" className={d("hero.title")}>
Una libreria ti dice cosa.
KDF ti dice quale..
Una libreria di design ti dà un Button. KDF ti dice che quel Button è l'homepage.hero.cta-primary, e che va stilizzato con quel token preciso. Va a colmare proprio quel buco che le librerie lasciano aperto: la mappa tra elemento e decisione di design.
Sei simboli.
Una grammatica.
KDF salva classi, reference condivise, ordine delle sezioni e custom properties CSS. Non ci troverai mai business logic, event handler, fetch di dati, permessi o robe di accessibilità.
Ogni elemento con un token si porta dietro il suo path. I nodi del DOM li riconduci diretti al JSON — una manna per gli scanner, i test e le review degli agenti.
Risolve un path sputando fuori la stringa className. d.css() invece ti ritorna l'oggetto con le custom properties CSS.
Punta dritto a un token riutilizzabile in shared/. Le ref puoi concatenarle ed estenderle con altre classi.
Un array di chiavi di sezione. Le sezioni in lista vengono renderizzate in quell'ordine; se mancano, l'app semplicemente le nasconde.
Metadati utili per gli agenti e i tool — ti dice quale componente renderizza il token, dandoti anche un hint sulle varianti e le size.
Quei valori che non riesci a esprimere con classi riutilizzabili e che applichi come variabili di stile inline usando d.css().
Default condivisi.
Override di pagina.
I design token vivono in due posti: i default riutilizzabili in shared/, e la roba specifica per pagina che sovrascrive solo il necessario. Hai due file CSS in croce per gestire first paint e scappatoie.
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
Una reference tipo @button.cta viene risolta partendo dallo shared/ della pagina, poi risale a uno shared/ padre, per poi finire sui token di pagina. I template sovrascrivono solo le robe che servono ed ereditano il resto.
Il grosso del design viene risolto sul server; al browser arrivano le stringhe delle classi già belle pronte. Il CSS critico lo spariamo al first paint, il resto lo fai caricare dopo — così non affoghi i client lenti.
Lo importi nell'app in modo che variabili di design e override per evitare FOUC arrivino al primissimo paint — zero flash strani a schermo.
/* konde-server.css */ :root { --kdf-primary: #1F8F47; } [data-kdf="hero.slider"] { display: none; }
Caricato dopo il CSS del framework e dell'app. È per i tweak, le prove e gli override sporchi — insomma, tutte robe di fino che non ha senso facciano blocking sul paint.
/* konde.css */ [data-kdf="hero.title"] { letter-spacing: -0.02em; } [data-kdf="hero.wrapper"] { gap: 3rem; }
→ KDF li genera una volta e poi non te li tocca più. Il plugin ti espone i path via env - è l'app a gestire gli import; non ti iniettiamo roba di nascosto.
Switcha design
come switchi lingua.
Nello stesso modo in cui i18n cambia lingua, KDF cambia i template di design. Stessa app, stessi componenti, stesso codice — tu fagli puntare KDF_DIR su un'altra cartella e ti cambia tutto il look.
designs/ lander/ shared/ homepage.json newlander/ shared/ homepage.json
// next.config.ts withKDF({ dir: "./designs/lander" })(nextConfig);
Risolvi sul server.
Passa giù le stringhe.
Il core di KDF si spazzola il JSON dal disco, quindi vive rigorosamente server-side: Next.js Server Components, render di Astro, handler di Hono. Tu ti risolvi le classi lì, per poi passare normalissime stringhe ai 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>
→ stringa className pronta all'uso
→ oggetto con le custom-properties CSS
Mixa classi condizionali, sega via i falsy, deduplica — per default è semantic-free.
In prod ti cacha tutto; in dev si smazza la revalidation su mtime e size.
Sta seduto sopra
al tuo stack.
STYLING — SALVA CLASSI, MICA CSS
KDF non fa mica da motore CSS. Nei token ci metti le stringhe di classi che il tuo sistema di styling preferito riesce a digerire. Se usi un framework che fa scanning dei sorgenti, basta fargli parsare pure il JSON: @source "../kdf/**/*.json".
RUNTIME — JAVASCRIPT LATO SERVER
Installi una volta.
L'init ti impalca il resto.
L'installazione ti spara giù anche una cartella starter kdf/ se non la trova. E vai tranquillo che i file esistenti non vengono mai sovrascritti.
import withKDF from "@kondeio/kdf/plugin"; export default withKDF({ dir: "./designs" })(nextConfig);