i18n es tu traducción.
KDF es tu diseño.
Ambos en JSON.
Una capa para coordinar diseños basados en JSON para apps backend e interfaces armadas por agentes. Tus decisiones clave (layouts, márgenes, fuentes) viven en una sola fuente de verdad para que los agentes la usen sin tener que adivinar qué hiciste antes.
{ "$layout": ["hero", "footer"], "hero": { "wrapper": "mx-auto max-w-6xl px-6 py-20", "title": "@typography.h1", "cta-primary": "@button.cta" } }
Una única fuente de verdad mantiene todo tu proyecto —y a tus agentes— súper consistentes.
JSON define · el código renderiza · data-kdf mapea de vuelta
El diseño se pierde
en tus componentes.
Cuando los nombres de clases viven solo dentro de archivos .tsx, cada página se va desalineando poco a poco. Esto funciona para un dev, pero es súper frágil cuando los agentes empiezan a tocar la 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
El mismo botón de la nada ya tiene cinco versiones distintas. El margen cambia en cada vista. Cada vez que abres una sesión nueva con un agente, le toca redescubrir las reglas desde cero.
- — Los agentes inventan colores, espaciados y layouts.
- — Te pasas corrigiéndolos por chat a cada rato.
- — Si quieres cambiar algo, tienes que buscar en mil componentes.
- — Se pierde la intención original del diseño.
→ iteraciones sin fin de "más grande" · "más azul" · "muévelo a la izquierda" sin fin
Haz explícito tu diseño.
KDF hace por el diseño lo mismo que i18n por los textos: saca tus decisiones repetitivas de los componentes y las pone en un JSON. Al final, la app sigue usando tu CSS normal, lo único que cambia es de dónde salen las clases.
{ "hero": { "title": "text-5xl font-semibold tracking-tight" } }
const d = getDesign("homepage"); <h1 data-kdf="hero.title" className={d("hero.title")}>
Una librería dice qué.
KDF dice cuál..
Una librería te da el Botón. KDF te dice que esto de aquí es tu homepage.hero.cta-primary, renderizado como un Botón con ese estilo específico. KDF conecta directamente tu elemento con la decisión de diseño.
Seis símbolos.
Una gramática.
KDF guarda classNames, referencias compartidas, el orden de tus secciones y custom properties de CSS. Pero ojo: nunca maneja lógica de negocio, fetches ni accesibilidad.
Cada elemento lleva su propia ruta. Los nodos del DOM se conectan directito al JSON (súper útil para testing y agentes).
Resuelve la ruta a su string de className correspondiente. d.css() devuelve las variables CSS.
Para apuntar a un token reusable en shared/. Puedes encadenar y meter más clases sobre las referencias.
Un array de tus secciones. Lo que esté listado se renderiza en ese orden, y lo que no, se oculta.
Metadatos para agentes y herramientas. Dice qué componente va con qué token y te pasa hints sobre variantes y tamaños.
Esos valores que no quedan bien como clases se aplican como variables de estilo en línea con d.css().
Defaults compartidos.
Overrides por página.
Los tokens viven en dos partes: defaults reusables en shared/ y overrides específicos por página. Tienes dos CSS base que manejan el renderizado crítico y te dan escapatorias.
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 referencia como @button.cta resuelve en cascada desde la página local al shared/ global. Sobrescribe sólo lo que ocupes.
El diseño se resuelve en el servidor; el browser sólo ve strings normales. El CSS crítico entra en el first paint sin trabar los clientes de baja gama.
Para que las variables de diseño base lleguen desde el render inicial y evitar esos flasheos raros (FOUC).
/* konde-server.css */ :root { --kdf-primary: #1F8F47; } [data-kdf="hero.slider"] { display: none; }
Se carga después del CSS del framework para esos ajustes manuales que no necesitan bloquear la página al inicio.
/* konde.css */ [data-kdf="hero.title"] { letter-spacing: -0.02em; } [data-kdf="hero.wrapper"] { gap: 3rem; }
→ KDF crea estos dos y ya, no te sobrescribe nada. Tú decides cómo y dónde importarlos.
Cambia el diseño
como cambias el idioma.
KDF te permite cambiar el template visual enterito con la misma lógica de i18n. Misma app, misma lógica, solo apuntas KDF_DIR a otro diseño y listo.
designs/ lander/ shared/ homepage.json newlander/ shared/ homepage.json
// next.config.ts withKDF({ dir: "./designs/lander" })(nextConfig);
Resuelve en el servidor.
Manda strings al cliente.
Al correr en el servidor, KDF lee de disco (Next.js SC, Astro, Hono). Resuelve todo el relajo del lado del servidor y le entrega strings limpios a tus componentes del cliente.
import { getDesign, cn } from "@kondeio/kdf"; const d = getDesign("homepage"); <button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
→ string resuelto con classNames
→ objeto con tus CSS custom properties
Junta clases, filtra falsos, quita duplicados (sin meter semántica extra).
Cacheo inteligente en prod; en dev usa tiempos y tamaños de archivo.
Funciona por encima de
tu stack.
ESTILOS — GUARDA CLASSNAMES, NO CSS
KDF no compila CSS. Sus tokens solo guardan los strings que tu herramienta ya entienda. Si tu framework escanea tu repo (como Tailwind), ponlo a escanear tus JSON también: @source "../kdf/**/*.json".
RUNTIME — JAVASCRIPT EN EL SERVIDOR
Instalas una vez.
Init hace el setup.
Con init se crea tu carpeta kdf/ base si no la tienes, sin machacar los archivos que ya tengas.
import withKDF from "@kondeio/kdf/plugin"; export default withKDF({ dir: "./designs" })(nextConfig);