i18n זה לתרגומים שלכם.
KDF זה לעיצוב שלכם.
שניהם חיים ב-JSON.
שכבת תיאום עיצוב מבוססת JSON לאפליקציות ווב בשרת (server-side) ול-UI שבנוי בעזרת סוכנים. החלטות שחוזרות על עצמן — כמו לייאאוט, ריווח, טיפוגרפיה ועיצוב — יושבות במקור אמת אחד שהסוכנים קוראים, במקום לנחש כל פעם מחדש.
{ "$layout": ["hero", "footer"], "hero": { "wrapper": "mx-auto max-w-6xl px-6 py-20", "title": "@typography.h1", "cta-primary": "@button.cta" } }
מקור אמת אחד ששומר על כל עמוד, קומפוננטה וסשן של סוכן מסונכרנים.
ה-JSON מגדיר · הקוד מרנדר · data-kdf ממפה חזרה
העיצוב מתפזר בין
הקומפוננטות שלכם.
כששמות של קלאסים יושבים רק בתוך קבצי .tsx, כל עמוד מקבל חיים משלו. זה עוד איכשהו עובד עם מפתח אחד — אבל נשבר לגמרי ברגע שסוכנים מתחילים לכתוב לכם 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
אותו כפתור בדיוק מייצר חמש גרסאות חדשות. הריווחים זזים מעמוד לעמוד. כל סשן חדש של סוכן אומר ללמוד את החוקים מאפס.
- — סוכנים מתחילים לאלתר צבעים, ריווחים, טיפוגרפיה ולייאאוטים.
- — משתמשים צריכים לתקן כל פיפס בצ'אט, כל פעם מחדש.
- — כל שינוי קטן אומר לשוטט בין מיליון קבצים של קומפוננטות.
- — סשנים חוזרים מפספסים את כוונת העיצוב המקורית.
→ איטרציות שנגמרות ב-"יותר גדול" · "יותר כחול" · "שמאלה" בלי סוף
תעשו לעיצוב אקספורט.
KDF עושה לעיצוב מה ש-i18n עושה לטקסט: הוא מושך החלטות שחוזרות על עצמן החוצה מקבצי הקומפוננטות ישר לתוך JSON. ה-UI עצמו עדיין מפונדר עם CSS רגיל — מה שמשתנה זו השליטה.
{ "hero": { "title": "text-5xl font-semibold tracking-tight" } }
const d = getDesign("homepage"); <h1 data-kdf="hero.title" className={d("hero.title")}>
ספרייה אומרת מה.
KDF אומר איזה..
ספריית עיצוב נותנת לכם Button. לעומת זאת, KDF יודע להגיד לכם שזה ה-homepage.hero.cta-primary, שמרונדר כ-Button ומעוצב ספציפית דרך הטוקן הזה. הוא סוגר את הפינה שהרבה ספריות מפספסות — המיפוי בין האלמנט להחלטה העיצובית.
שישה סמלים.
דקדוק אחד.
KDF מכיל שמות קלאסים (class names), רפרנסים משותפים (shared), סדר של אזורים (sections), והגדרות CSS custom properties. הוא לעולם לא שומר לוגיקה עסקית, handlers של אירועים, שליפות דאטה, הרשאות או חוקי נגישות.
כל אלמנט שניגש לטוקן מקבל נתיב תואם. ה-DOM ממופה ישירות ל-JSON — בול לסקריפטים, טסטים וסוכני AI שמנתחים את העמוד.
מתרגם נתיב לסטרינג של className. הפונקציה d.css() מחזירה את ה-CSS custom properties.
מפנה לטוקן מתוך תיקיית shared/. אפשר לשרשר ולהוסיף קלאסים לרפרנס.
מערך keys שמייצגים סקשנים. רשימה שמרונדרת לפי סדר; מה שלא נמצא שם פשוט מוסתר אוטומטית.
מטא-דאטה בשביל סוכנים וכלים מסביב — איזו קומפוננטה מרנדרת את הטוקן הזה, פלוס רמזים על variant ו-size.
ערכים שלא מתאימים לקלאס מיושמים ישירות כ-inline style variables דרך פונקציית d.css().
ברירות מחדל ב-shared.
דריסות של העמוד.
טוקנים לעיצוב יושבים בשני מקומות: ברירות מחדל לשימוש חוזר ב-shared/, והרכבה פר-עמוד שדורסת (override) רק מה שחייב. שני קבצי CSS כלליים דואגים לרינדור הראשון (first paint) ולמקרי קצה.
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
רפרנס כמו @button.cta מפוענח קודם כל מה-shared/ של העמוד, אחר כך מה-shared/ של קומפוננטת האב, ורק אז מהטוקנים של העמוד עצמו. טמפלייטים דורסים רק מה שרלוונטי ויורשים את השאר.
העיצוב חושב בשרת; הדפדפן מקבל רק שרשראות (strings) פשוטות של קלאסים מוכנים. CSS קריטי נוחת כבר ב-first paint, והשאר נטען אחר כך — הלקוח לא סופג שום עומס רינדור נוסף.
מיובא על ידי האפליקציה כדי שמשתני העיצוב ודריסות חסינות-FOUC יגיעו ב-paint הראשון — עוד לפני שאפילו פיקסל מספיק להבהב.
/* konde-server.css */ :root { --kdf-primary: #1F8F47; } [data-kdf="hero.slider"] { display: none; }
נטען אחרי הקוד של ה-framework וה-CSS הכללי לטובת ניסויים, טריקים קטנים ומקרי קצה — תיקונים עדינים שבחיים לא אמורים לעכב את הרינדור הראשוני.
/* konde.css */ [data-kdf="hero.title"] { letter-spacing: -0.02em; } [data-kdf="hero.wrapper"] { gap: 3rem; }
← KDF מייצר את שניהם פעם אחת ולא דורס לעולם. הפלאגין מגדיר להם נתיבים ב-env - האפליקציה שלכם דואגת לייבא אותם; אף אחד לא מזריק לכם קוד בסתר.
להחליף את הלוק
בדיוק כמו שמחליפים שפה.
כמו ש-i18n מחליף בין שפות, ככה KDF מחליף בין טמפלייטים של עיצוב. הכל נשאר זהה: האפליקציה, הקומפוננטות והקוד — פשוט מכוונים את ה-KDF_DIR לתיקיית עיצוב חדשה וכל הלוק מתעדכן במקום.
designs/ lander/ shared/ homepage.json newlander/ shared/ homepage.json
// next.config.ts withKDF({ dir: "./designs/lander" })(nextConfig);
מפענחים בשרת.
מעבירים מחרוזות למטה.
הליבה של KDF קוראת את ה-JSON ישר מהדיסק, ככה שזה עובד מראש בשרת: ב-Next.js Server Components, רינדור ב-Astro, או בהנדלרים של Hono. שם למעלה מפענחים קלאסים, ומעבירים מחרוזות (strings) נקיות ופשוטות ל-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>
← סטרינג מפוענח של className
← אובייקט חתיך של CSS custom-properties
לשרשר קלאסים מותנים, לזרוק משתנים falsy, ולנקות כפילויות — הכל בלי להיות כבדים על סמנטיקה.
בפרודקשן הכל שמור בקאש; בסביבת פיתוח הכל מתרענן לפי mtime וגודל קובץ.
הוא יושב מעל
הסטאק הקיים שלכם.
עיצוב — שומר שמות של CLASSES, לא CSS עצמו
KDF הוא ממש לא מנוע CSS. הטוקנים מחזיקים רק string של class שמובן ע"י המערכת שלכם. אם ה-framework שלכם יודע לסרוק קבצים, שווה להראות לו גם את ה-JSON: @source "../kdf/**/*.json".
זמן ריצה — JAVASCRIPT בצד שרת
מתקינים פעם אחת.
ה-init בונה את כל השאר.
תהליך ההתקנה גם מייצר תיקיית kdf/ ראשונית במידה והיא לא קיימת. קבצים שכבר קיימים אף פעם לא ידרסו.
import withKDF from "@kondeio/kdf/plugin"; export default withKDF({ dir: "./designs" })(nextConfig);