الـ i18n عشان الترجمة.
والـ KDF عشان التصميم.
والاتنين بيعيشوا في JSON.
طبقة تنظيم للتصميم مبنية على JSON لتطبيقات الويب اللي بتشتغل على السيرفر وواجهات المستخدم اللي بيساعد فيها الذكاء الاصطناعي. القرارات المتكررة — التخطيط، المسافات، الخطوط، وتنسيق المكونات — موجودة في مكان واحد بيقراه وكلاء الذكاء الاصطناعي بدل ما يتوهوا بين الملفات والصفحات القديمة.
{ "$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. واجهة المستخدم النهائية لسة بتستخدم 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، وبيظهر كزرار متنسق بالـ token ده. هو بيضيف الربط اللي المكتبات التانية بتنساه — من العنصر لقرار التصميم.
ست رموز.
وقواعد واحدة.
الـ KDF بيخزن أسماء الكلاسات، الـ references المشتركة، ترتيب الأقسام، ومتغيرات الـ CSS. وعمره ما بيخزن logic، ولا event handlers، ولا data fetching، ولا صلاحيات، ولا حاجات خاصة بالـ accessibility.
أي عنصر بيستخدم token بيبقى معاه مسار متطابق. عناصر الـ DOM بترجعك مباشرة للـ JSON — مفيد للـ scanners، الـ tests، ومراجعة الوكلاء.
بيترجم المسار لاسم الكلاس كـ string. الـ d.css() بيرجعلك أوبجيكت بمتغيرات الـ CSS.
بيشاور على token ممكن تعيد استخدامه في /shared. الـ refs ممكن تتربط ببعض وتتوسع بكلاسات زيادة.
مصفوفة فيها مفاتيح الأقسام. الأقسام المكتوبة بتظهر بالترتيب؛ واللي مش موجودة التطبيق بيخفيها.
معلومات (Metadata) للوكلاء والأدوات — مين المكون اللي بيرندر الـ token ده، زائد تلميحات عن الشكل والمقاس.
القيم اللي ماينفعش تعبر عنها بكلاسات قابلة لإعادة الاستخدام، بتطبق كـ inline style variables عن طريق d.css().
إعدادات مشتركة.
وتعديلات لكل صفحة.
الـ Design tokens بتبقى في مكانين: حاجات قابلة لإعادة الاستخدام في الـ shared/، وتركيبة لكل صفحة بتعدل بس اللي هي محتاجاه. فيه ملفين CSS خاصين بيك بيظبطوا الـ first paint وأي 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
لو فيه مرجع زي @button.cta بيترجم من الـ shared/ بتاع الصفحة، بعدين الـ shared/ الأب، وبعدين الـ tokens بتاعة الصفحة. القوالب بتعدل الأجزاء اللي محتاجاها بس وبتورث الباقي.
التصميم بيتحلل على السيرفر؛ والمتصفح بيستلم الكلاسات جاهزة. الـ Critical CSS بينزل في الـ first paint، والباقي بيحمل بعدين — مفيش أي حمل في الريندر على الأجهزة الضعيفة.
بيتعمله import في التطبيق عشان متغيرات التصميم والـ overrides تنزل في أول paint — قبل ما أي حاجة تلغوش.
/* konde-server.css */ :root { --kdf-primary: #1F8F47; } [data-kdf="hero.slider"] { display: none; }
بيحمل بعد الـ CSS بتاع الفريمورك والتطبيق عشان أي تظبيطات، تجارب، أو escape hatches — تعديلات دقيقة مش محتاجة توقف الـ paint.
/* konde.css */ [data-kdf="hero.title"] { letter-spacing: -0.02em; } [data-kdf="hero.wrapper"] { gap: 3rem; }
→ الـ KDF بيكريت الملفين دول مرة واحدة ومش بيمسحهم أبدًا. الإضافة بتعرض مساراتهم من خلال الـ env - تطبيقك بيعمل الـ imports بنفسه؛ مفيش حاجة بتتزرع غصب عنك.
غيّر التصميم
كأنك بتغير اللغة.
زي ما الـ i18n بيغير اللغات، الـ KDF بيغير قوالب التصميم. نفس التطبيق، نفس المكونات، ونفس الكود — بس وجه الـ KDF_DIR لفولدر تصميم تاني وشكل الموقع كله هيتغير.
designs/ lander/ shared/ homepage.json newlander/ shared/ homepage.json
// next.config.ts withKDF({ dir: "./designs/lander" })(nextConfig);
حلل على السيرفر.
وابعت الـ strings للكلاينت.
الـ KDF الأساسي بيقرا الـ JSON من الديسك، فبيشتغل server-side: في Next.js Server Components، تصيير Astro، و Hono handlers. بيحلل الكلاسات هناك، وبعدين يبعت نصوص عادية للمكونات على الكلاينت.
import { getDesign, cn } from "@kondeio/kdf"; const d = getDesign("homepage"); <button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
→ string جاهز لاسم الكلاس
→ أوبجيكت بمتغيرات الـ CSS custom-properties
بتدمج الكلاسات الشرطية، بتشيل القيم الـ falsy، وبتشيل التكرار — من غير semantic بشكل افتراضي.
في الـ Production بيعمل كاش؛ في الـ dev بيحدث نفسه بناءً على وقت التعديل والحجم (mtime & size).
بيشتغل فوق
الـ stack بتاعك.
التنسيق — بيخزن أسماء كلاسات، مش CSS
الـ KDF مش محرك CSS. الـ tokens بتشيل أي strings نظام التنسيق بتاعك بيفهمها. لو الفريمورك بتاعك بيعمل سكان لملفات السورس، خليه يشوف الـ JSON كمان: @source "../kdf/**/*.json".
الـ RUNTIME — جافاسكريبت على السيرفر
سطّب مرة واحدة.
والـ Init هيكمل الباقي.
التسطيب بيكريت فولدر kdf/ مبدئي لو مش موجود. والملفات اللي موجودة قبل كده مش بتتمسح ولا بتتعدل.
import withKDF from "@kondeio/kdf/plugin"; export default withKDF({ dir: "./designs" })(nextConfig);