كل الأعمال
عربيEN
MS-01 · مشروع لعميل · المملكة العربية السعودية

غدق الخير

بوابة خاصة لأسرة الشبانة

منصة لتوثيق مشجرة الأسرة وإدارة العضويات وطلبات الانضمام والرسائل والمحتوى. الزائر يرى صفحة تعريفية فقط، والعضو يدخل إلى المشجرة والوثائق والأخبار، والمشرف يعمل بصلاحيات محددة بدقة.

زيارة الموقع
المواصفات
الواجهة
Next.js 16 · React 19 · TypeScript · Tailwind 4
البيانات
PostgreSQL 16، وRedis اختياري لحدود الطلبات
الملفات
Google Drive، برفع مجزأ للوثائق حتى 250MB
الدخول
جلسات JWT في cookie، وbcryptjs، وإلغاء فوري للجلسات
التشغيل
Docker خلف Traefik وCloudflare، مع نسخ احتياطي يومي
دوري
المشروع كاملاً، بمفردي
~2,000فرد في المشجرة
81مسار API
14صفحة
12وحدة في لوحة الإدارة
4مستويات وصول

01المشكلة

أسرة كبيرة تحتاج مشجرة واحدة موثوقة، يحدّثها الأعضاء بأنفسهم عبر طلبات يراجعها المشرفون، وفيها بيانات حساسة مثل أرقام الجوال والهوية لا يجوز أن يراها إلا من له صلاحية.

والتطبيق وقاعدة البيانات مستضافان داخل المملكة.

02كيف يعمل النظام

كل طلب يمر أولاً على طبقة الحماية (Proxy)، ولا يصل إلى البيانات إلا بجلسة صالحة وصلاحية مناسبة.

تطبيق الأعضاءتطبيق PWA عربيبإشعارات فورية
طبقة الحمايةفحص CSRF وJWTوحجب البوتات
81 مسار APIعلى Next.js4 مستويات وصولنحو 20 صلاحية دقيقةسجل تدقيق يسمح بالتراجع
PostgreSQLالأعضاء والعلاقات
Google Driveوثائق حتى 250MB
Web Pushإشعارات للأعضاء
Redisاختياري

03ثلاثة قرارات هندسية

A

حساب الأجيال عبر الأصهار

أبناء الزوج من خارج الأسرة يأخذون جيلهم من الأم. الجيل يُحسب باستعلام تكراري في PostgreSQL، ومصفوفة المسار تمنع الدخول في حلقة.

src/lib/db/generation.ts — مقتطف
WITH RECURSIVE maternal_tree AS (
  SELECT child.id, mother.generation + 1 AS generation,
         ARRAY[mother.id, child.id]::text[] AS path
  FROM family_members child
  JOIN family_members father ON father.id = child.parent_id
  JOIN family_members mother ON mother.id = child.mother_id
  WHERE father.is_external = TRUE
    AND mother.is_external = FALSE
  UNION ALL …
B

البيانات الحساسة بالصلاحية، لا بالدور

رقم الجوال والهوية لا يدخلان الاستعلام أصلاً إلا لمن يملك صلاحية تعديل الأعضاء. الصلاحية تُقرأ من القاعدة في كل طلب، فسحبها يسري فوراً. والوثائق خاصة افتراضياً إلا إذا جعلها صاحبها مرئية للأسرة.

src/app/api/family-data/route.ts — مقتطف
const canSeeSensitive =
  await hasAdminPermission(session, 'members:update');

const columns = canSeeSensitive
  ? `${PUBLIC_COLUMNS}, ${ADMIN_ONLY_COLUMNS}`
  : PUBLIC_COLUMNS;
C

الاسم الكامل يُعاد بناؤه تلقائياً

عند تعديل اسم أحد الأجداد، يُعاد بناء الأسماء الكاملة بصيغة «فلان بن/بنت فلان» لكل الذرية، حتى 25 مستوى.

src/lib/members/lineage.ts — مقتطف
const connector = member.gender === '⁨أنثى⁩' ? '⁨بنت⁩' : '⁨بن⁩';
return `${firstName} ${connector} ${fatherName}`;

04الأمان والتشغيل

  • فحوص في CInpm audit، وgitleaks للأسرار، وOSV للثغرات، ثم lint وفحص الأنواع والبناء.
  • نسخ احتياطيpg_dump يومي إلى تخزين متوافق مع S3، مع اختبار للاستعادة.
  • مراقبةفحص للموقع كل 5 دقائق، مع تنبيه على Telegram.
  • حاوية مقفلةصورة Docker متعددة المراحل، تعمل بمستخدم غير root.

05حدود معروفة

L-01التطبيق وقاعدة البيانات داخل المملكة، لكن الملفات على Google Drive. القرار موثّق ومفتوح: إما قبوله رسمياً أو نقل الملفات لتخزين داخل المملكة.
L-02اختبارات الوحدة ما زالت قليلة: 23 حالة في ملفين.

06دوري في المشروع

بنيت المشروع كاملاً بمفردي: الواجهة، والخادم، وقاعدة البيانات، والصلاحيات، والنشر والتشغيل. ويخدم اليوم مشجرة فيها قرابة 2,000 فرد.

الكود مرفوع على حساب صاحب التطبيق في GitHub، لذلك تظهر التعديلات (commits) باسمه.

© 2026 · القاهرة، مصر