Konde Design Framework

الـ i18n عشان الترجمة.
والـ KDF عشان التصميم.
والاتنين بيعيشوا في JSON.

طبقة تنظيم للتصميم مبنية على JSON لتطبيقات الويب اللي بتشتغل على السيرفر وواجهات المستخدم اللي بيساعد فيها الذكاء الاصطناعي. القرارات المتكررة — التخطيط، المسافات، الخطوط، وتنسيق المكونات — موجودة في مكان واحد بيقراه وكلاء الذكاء الاصطناعي بدل ما يتوهوا بين الملفات والصفحات القديمة.

شوف بيشتغل إزاي
kdf / homepage.json → مُصيَّر
kdf/homepage.json
{
  "$layout": ["hero", "footer"],
  "hero": {
    "wrapper": "mx-auto max-w-6xl px-6 py-20",
    "title":   "@typography.h1",
    "cta-primary": "@button.cta"
  }
}
data-kdf="hero.title"
ابني وأطلق بالذكاء الاصطناعي.
data-kdf="hero.body"

مصدر واحد للحقيقة بيخلي كل صفحة، مكوّن، وجلسة مع الذكاء الاصطناعي متناسقة جداً.

data-kdf="hero.cta-primary"
ابدأ دلوقتي →

الـ JSON بيعرف · الكود بيصيّر · data-kdf بيربطهم ببعض

الرخصة
MIT
الـ Runtime
Node Filesystem
الـ Dependencies
Zero Runtime
متجرب مع
Next · Astro · Hono
01 — المشكلة

التصميم بيبدأ يفلت
في مكوناتك.

لما أسماء الكلاسات تعيش بس جوة ملفات الـ .tsx، كل صفحة بتبدأ تختلف عن التانية. الموضوع بيمشي لو مبرمج واحد اللي شغال — بس بيبوظ أول ما وكلاء الذكاء الاصطناعي تبدأ تعدل في الـ UI.

من غير kdf · الدنيا متلخبطة بين الملفات
<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

نفس الزرار بيطلعله خمس أشكال فجأة. المسافات بتتغير من صفحة للتانية. وكل جلسة جديدة مع الذكاء الاصطناعي بتضطر تكتشف القواعد من الصفر.

النتيجة
  • وكلاء الذكاء الاصطناعي بيألفوا ألوان، مسافات، خطوط، وتخطيط من دماغهم.
  • المستخدمين بيضطروا يصلحوا النتيجة في الشات، في كل مرة.
  • أي تعديل معناه إنك تدور في ملفات المكونات كلها.
  • الجلسات المتكررة بتضيع الهدف الأساسي للتصميم.

→ تعديلات "أكبر" · "أزرق شوية" · "هاته شمال" مابتخلصش

02 — الحل

خلي التصميم واضح وصريح.

الـ KDF بيعمل للتصميم نفس اللي الـ i18n بيعمله للنصوص: بياخد القرارات المتكررة بره ملفات المكونات ويحطها في JSON. واجهة المستخدم النهائية لسة بتستخدم CSS عادي — اللي اتغير هو مين اللي بيتحكم.

1 — عرّفه في الـ json
{
  "hero": {
    "title": "text-5xl font-semibold tracking-tight"
  }
}
2 — صيّره في الكود
const d = getDesign("homepage");

<h1 data-kdf="hero.title" className={d("hero.title")}>
الـ JSON بيعرّف
ملف واحد بس اللي بيتحكم في اتجاه التصميم. المستخدمين بيعدلوا فيه دايركت لما يبقوا محتاجين تحكم دقيق.
الكود بيصيّر
المكونات بتاعتك بتقرا الـ tokens وتطلّع التصميم المعتمد بـ CSS عادي جداً — مفيش أي سحر في الموضوع.
الوكلاء بتنفذ
وكلاء الذكاء الاصطناعي بتبني الـ UI من الـ JSON بدل ما تخمن. مفيش تأليف في المسافات، الألوان، الخطوط أو ترتيب الأقسام.
المستخدم بيعدل الـ JSON
بتعدل المصدر مرة واحدة بدل ما تقعد توصف نفس التعديل في الشات كل مرة.
03 — مش مكتبة مكونات

المكتبة بتقولك إيه ده.
بس KDF بيقولك أنهي واحد.

مكتبة التصميم بتديك زرار (Button). لكن KDF بيقولك إن ده الـ homepage.hero.cta-primary، وبيظهر كزرار متنسق بالـ token ده. هو بيضيف الربط اللي المكتبات التانية بتنساه — من العنصر لقرار التصميم.

 مكتبة التصميمKDF
بتقول إيه"ده زرار.""ده hero.cta-primary في الـ homepage."
الربطمكون عام، تقدر تعمل عليه overrides براحتك.عنصر واحد بيتربط بـ key تصميم واحد.
التتبعمفيش ربط دقيق بين العنصر والقرار.الـ data-kdf بيشاور لكل عنصر في الـ DOM على مساره في الـ JSON.
بيشتغل فوق shadcn · Bootstrap · Chakra · Tailwind · CSS العادي · نظامك الخاص — KDF مش بديل لأي حاجة فيهم.
04 — المصطلحات

ست رموز.
وقواعد واحدة.

الـ KDF بيخزن أسماء الكلاسات، الـ references المشتركة، ترتيب الأقسام، ومتغيرات الـ CSS. وعمره ما بيخزن logic، ولا event handlers، ولا data fetching، ولا صلاحيات، ولا حاجات خاصة بالـ accessibility.

data-kdf
الخريطة (The map)

أي عنصر بيستخدم token بيبقى معاه مسار متطابق. عناصر الـ DOM بترجعك مباشرة للـ JSON — مفيد للـ scanners، الـ tests، ومراجعة الوكلاء.

data-kdf="hero.title"
d(path)
الـ Accessor

بيترجم المسار لاسم الكلاس كـ string. الـ d.css() بيرجعلك أوبجيكت بمتغيرات الـ CSS.

className={d("hero.title")}
@
الـ Shared reference

بيشاور على token ممكن تعيد استخدامه في /shared. الـ refs ممكن تتربط ببعض وتتوسع بكلاسات زيادة.

"@button.cta" shadow-xl
$layout
الترتيب والظهور

مصفوفة فيها مفاتيح الأقسام. الأقسام المكتوبة بتظهر بالترتيب؛ واللي مش موجودة التطبيق بيخفيها.

["hero", "features", "footer"]
$
هوية المكون

معلومات (Metadata) للوكلاء والأدوات — مين المكون اللي بيرندر الـ token ده، زائد تلميحات عن الشكل والمقاس.

"$": "Button"
css
متغيرات الـ CSS

القيم اللي ماينفعش تعبر عنها بكلاسات قابلة لإعادة الاستخدام، بتطبق كـ inline style variables عن طريق d.css().

{ "--kdf-accent": "#4F46E5" }
05 — الهيكلة

إعدادات مشتركة.
وتعديلات لكل صفحة.

الـ 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
Cascade متعدد المستويات

لو فيه مرجع زي @button.cta بيترجم من الـ shared/ بتاع الصفحة، بعدين الـ shared/ الأب، وبعدين الـ tokens بتاعة الصفحة. القوالب بتعدل الأجزاء اللي محتاجاها بس وبتورث الباقي.

خفيف بطبعه

التصميم بيتحلل على السيرفر؛ والمتصفح بيستلم الكلاسات جاهزة. الـ Critical CSS بينزل في الـ first paint، والباقي بيحمل بعدين — مفيش أي حمل في الريندر على الأجهزة الضعيفة.

ملفين CSS للمستخدم · ولحظتين تحميل
konde-server.css
أساسي · first paint

بيتعمله import في التطبيق عشان متغيرات التصميم والـ overrides تنزل في أول paint — قبل ما أي حاجة تلغوش.

/* konde-server.css */
:root { --kdf-primary: #1F8F47; }
[data-kdf="hero.slider"] { display: none; }
konde.css
مش أساسي · بعد الـ app css

بيحمل بعد الـ CSS بتاع الفريمورك والتطبيق عشان أي تظبيطات، تجارب، أو escape hatches — تعديلات دقيقة مش محتاجة توقف الـ paint.

/* konde.css */
[data-kdf="hero.title"] { letter-spacing: -0.02em; }
[data-kdf="hero.wrapper"] { gap: 3rem; }

→ الـ KDF بيكريت الملفين دول مرة واحدة ومش بيمسحهم أبدًا. الإضافة بتعرض مساراتهم من خلال الـ env - تطبيقك بيعمل الـ imports بنفسه؛ مفيش حاجة بتتزرع غصب عنك.

06 — قوالب متعددة

غيّر التصميم
كأنك بتغير اللغة.

زي ما الـ i18n بيغير اللغات، الـ KDF بيغير قوالب التصميم. نفس التطبيق، نفس المكونات، ونفس الكود — بس وجه الـ KDF_DIR لفولدر تصميم تاني وشكل الموقع كله هيتغير.

designs/ — قالبين تصميم لتطبيق واحد
designs/
  lander/
    shared/
    homepage.json
  newlander/
    shared/
    homepage.json
// next.config.ts
withKDF({ dir: "./designs/lander" })(nextConfig);
$layout رتب أو اخفي الأقسام من غير ما تلمس أي مكون.
@button غيّر كل الـ CTAs مرة واحدة عن طريق token مشترك.
KDF_DIR بدّل قالب التصميم بالكامل كقرار واضح من التطبيق نفسه.
07 — الـ Runtime API

حلل على السيرفر.
وابعت الـ strings للكلاينت.

الـ KDF الأساسي بيقرا الـ JSON من الديسك، فبيشتغل server-side: في Next.js Server Components، تصيير Astro، و Hono handlers. بيحلل الكلاسات هناك، وبعدين يبعت نصوص عادية للمكونات على الكلاينت.

server component
import { getDesign, cn } from "@kondeio/kdf";

const d = getDesign("homepage");

<button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
d("hero.title")

→ string جاهز لاسم الكلاس

d.css("hero.title")

→ أوبجيكت بمتغيرات الـ CSS custom-properties

cn · cx · dedupeClasses

بتدمج الكلاسات الشرطية، بتشيل القيم الـ falsy، وبتشيل التكرار — من غير semantic بشكل افتراضي.

cache: auto · always · none

في الـ Production بيعمل كاش؛ في الـ dev بيحدث نفسه بناءً على وقت التعديل والحجم (mtime & size).

08 — متوافق بطبعه

بيشتغل فوق
الـ stack بتاعك.

التنسيق — بيخزن أسماء كلاسات، مش CSS

TailwindshadcnBootstrapChakraCSS ModulesPlain CSSYour own system

الـ KDF مش محرك CSS. الـ tokens بتشيل أي strings نظام التنسيق بتاعك بيفهمها. لو الفريمورك بتاعك بيعمل سكان لملفات السورس، خليه يشوف الـ JSON كمان: @source "../kdf/**/*.json".

الـ RUNTIME — جافاسكريبت على السيرفر

Next.js متجرب · إضافة (plugin)
Astro متجرب
Hono متجرب
ابدأ دلوقتي

سطّب مرة واحدة.
والـ Init هيكمل الباقي.

التسطيب بيكريت فولدر kdf/ مبدئي لو مش موجود. والملفات اللي موجودة قبل كده مش بتتمسح ولا بتتعدل.

$npm install @kondeio/kdf
$pnpm add @kondeio/kdf
$bun add @kondeio/kdf
$npm exec -- kdf init # تسطيب يدوي
next.config.ts
import withKDF from "@kondeio/kdf/plugin";

export default withKDF({ dir: "./designs" })(nextConfig);