- ابدأ الآن
- البيئة المحلية
- البنية المعمارية
- الهيكل
- الأنماط
- الحزمة التقنية
- قاعدة البيانات
- تعدّد المستأجرين
- الفهرس (Catalog)
- العمل دون اتصال
- المصادقة
- التهيئة (Onboarding)
- تدفق التكامل (Integration Flow)
- التهيئة (Provision)
- القبول
- الحضور
- الامتثال التنظيمي
- الملف الشخصي
- الاجتماعات
- إدارة الرسوم
- الفاتورة
- التدويل
- الترجمة
- دليل الترجمة
- أمان قاعدة البيانات
- المساهمة
- الإلهام
- المالية
- النقل
الفهرس هو مخزن المنهج المشترك للمنصّة. توجد نسخة واحدة من كل مادة وفصل ودرس داخل
جداول عامة بلا schoolId؛ وكل مدرسة تشير إلى نفس المحتوى عبر صفوف جسر (bridge)
صغيرة بدل استنساخه. والمحتوى الذي يساهم به المعلّمون والمدارس (فيديوهات، مواد،
أسئلة، كتب) يمرّ بمراجعة فريق SaaS ثم يُثري الفهرس للجميع.
هذه الصفحة هي المرجع الموحّد للفهرس. المرجع الكامل لشبكة التوصيل (CDN) والأصول يوجد منفصلاً في CDN & Assets.
نظرة عامة
يقوم النظام كلّه على نموذج ذهني واحد: هناك جداول فهرس عامة (مشتركة، بلا
مستأجر) وصفوف جسر مُنطَقة بـschoolId تربط المستأجر بذلك المحتوى المشترك. لا
تستنسخ المدرسة الفهرس قطّ — بل تشير إليه.
prisma/models/— catalog data modelcatalog.prisma— Subject — content rootchapter.prisma— Chapterlesson.prisma— Lessoncurriculum.prisma— Curriculumvideo.prisma— Video, VideoPurchase, Attachmentqbank.prisma— Question, ExamQuestionexam.prisma— Exam, ExamTemplatematerial.prisma— Materialassignment.prisma— Assignmentbook.prisma— Booktextbook.prisma— Textbookdocument.prisma— Documentproposal.prisma— Proposalbridge.prisma— SubjectSelection, ContentOverride, InstructorPreference, BookSelectionenrollment.prisma— Enrollment, LessonProgress, SubjectCertificateacademic.prisma— AcademicLevel, AcademicGrade, AcademicStreamprisma/seeds/catalog/— load content into the DBindex.ts— orchestrator: seedCatalog (US + full SD) + seedFullCatalogengine.ts— seedSubjectsOnly — the shallow nationals' shared seederregistry.ts— all 12 Curriculum records + curriculumId backfillus.ts— US — the US-curriculum source backbonetree.ts— the catalog repo (../catalog) → sd · gb · cbse · ib-dp · caie-igcse: subjects, chapters, lessons, questions, exams — ids preservedsa.ts · eg.ts · ae.ts · qa.ts · kw.ts · jo.ts— subjects-only nationals (split from world.ts; graduate to deep trees)concepts.ts— concept images to S3banners.ts— concept banners to S3 (owned, shared)lesson-covers.ts— per-lesson/chapter covers to S3 (US, legacy)books.ts— global catalog bookscontent.ts— materials, exams, questionsvideos.ts— lesson videosexam-templates.ts— exam blueprints + templatesdemo.ts— demo-school structure + bridgessrc/components/catalog/— shared core — every surface imports from hereconcepts-data.ts— 23 concepts, colors, nearestConcept, exact-match maps + pools — single sourcesetup.ts— provisions a school onto the catalogprovision.ts— schedule/sections/timetable/library provisioning + the repair doctorimage.ts— Sharp pipeline + S3 uploadimage-url.ts— resolve image URLs (CloudFront)src/components/saas-dashboard/catalog/— platform authoring (DEVELOPER)src/components/school-dashboard/listings/subjects/catalog/— school adoption + contributionsrc/components/lumos/data/catalog/— LMS read queries../catalog/— github.com/databayt/catalog — the curriculum repo; mirrors cdn.databayt.org/catalog/sd/ · gb/ · us/ · cbse/ · ib-dp/ · caie-igcse/— <cur>/<grade>/<subject>/{structure,qbank,exams}.json, c<N>/l<N>/ — read by tree.ts (us is not adopted)scripts/migrate/renames.json— pre-catalog slug → catalog id (tree.ts adopts rows by it)public/subjects/concepts/— 23 source concept imagesscripts/us-curriculum/us-inventory.json— US source datasudan-data/— Sudan source data + TOC + PDFs- الفهرس العام (جداول
catalog_*، بلاschoolId) — هرم المنهج (Subject→Chapter→Lesson) إضافةً إلى المحتوى المرتبط به (Exam،Question،Material،Assignment،Video،Book،Quiz،Document،Image،Textbook) وسجلّاتCurriculum. - صفوف الجسر (جداول
school_*، تحملschoolId) —SubjectSelection،ContentOverride،InstructorPreference،BookSelection. تربط المستأجر بالمحتوى المشترك؛ وكل ما يخصّ المدرسة يقرأ من خلالها. - لماذا — عند 1,000 مدرسة يخزّن النموذج المشترك ~240 مادة بدل 220k، وكل مساهمة تُثري كل المدارس.
| الأسلوب | بيانات 1,000 مدرسة × ~240 مادة | المشاركة |
|---|---|---|
| نسخة لكل مدرسة | 220k مادة، 800k فصل، 4M درس | لا شيء |
| فهرس مشترك | ~240 مادة، ~800 فصل، ~4k درس + سجلّات الجسر | كل مساهمة تُثري كل المدارس |
الحالة باختصار
| القدرة | الحالة |
|---|---|
| نموذج الفهرس العام + الجسر | موصول — في الإنتاج |
| اتّساع المناهج | 12 منهجاً عرضاً، 6 بعمق (US، SD، GB، CAIE-IGCSE، IB-DP، CBSE) |
| البنية الأكاديمية لكل منهج | موصولة — academic-config.ts (ثغرة "السوداني-للجميع" القديمة أُصلِحت) |
التهيئة (setupCatalogForSchool) | موصولة — استنتاج + تراجع 4 خطوات + إصلاح ذاتي كسول |
| الاقتراح → الموافقة (اختياري) | موصول هذه الجلسة — اقتراح، طابور المُشغِّل، نشر، إشعار، مُنتقي مُثبَّت |
| الموافقة تنشر المحتوى | مُصلَح — الموافقة تضبط الآن status: PUBLISHED (كانت ثغرة DRAFT غير مرئية) |
| الفيديوهات المدفوعة | موصولة — VideoPurchase، CloudFront مُوقَّع، حجب الرابط null |
| الاختبارات/الأسئلة المدفوعة | مؤجّل — الحقول موجودة، تدفّق الشراء غير مبني |
| مصغّرات المواد | مكتملة — كل المناهج الـ12 عبر المفاهيم المشتركة |
| البانرات / أغلفة الكتب | جزئي / مفقود (راجع CDN & Assets) |
| تكرارية بذرة المحتوى (idempotency) | مُصلَحة هذه الجلسة — إعادة التشغيل تتخطّى الصفوف الموجودة |
المعمارية
نماذج الفهرس تستخدم أسماء مجرّدة مربوطة بجداول catalog_*؛ ونماذج الجسر مربوطة
بجداول school_*. مُوصِّل عميل Prisma هو صيغة camelCase من اسم النموذج
(db.subject، db.subjectSelection).
نماذج الفهرس العام
| النموذج | الجدول (@@map) | المُوصِّل | يحمل |
|---|---|---|---|
Subject | catalog_subjects | db.subject | جذر الهرم؛ slug (فريد)، curriculum، concept، أعداد مُزال تطبيعها |
Chapter | catalog_chapters | db.chapter | مفتاح أجنبي subjectId، sequenceOrder |
Lesson | catalog_lessons | db.lesson | مفتاح أجنبي chapterId، sequenceOrder، durationMinutes |
Video | lesson_videos | db.video | videoUrl، provider، visibility، price، الموافقة |
Exam | catalog_exams | db.exam | اختبار الفهرس (≠ SchoolExam المدرسي) |
ExamQuestion | catalog_exam_questions | db.examQuestion | جدول وصل Exam ↔ Question مع order/points |
Question | catalog_questions | db.question | بنك أسئلة الفهرس (≠ QuestionBank المدرسي) |
Material | catalog_materials | db.material | كتب/مناهج/أوراق عمل على أي مستوى |
Assignment | catalog_assignments | db.assignment | قوالب واجبات/مشاريع قابلة لإعادة الاستخدام |
Book | catalog_books | db.book | كتب المكتبة (≠ SchoolBook المدرسي) |
Quiz | catalog_quizzes | db.quiz | مُعرَّف؛ لا يُبذَر |
Document | catalog_documents | db.document | سجلّ ملفات موحّد (PDF/PPTX/DOCX/صوت) |
Image | catalog_images | db.image | نسخ صور المفاهيم (راجع المفاهيم) |
Textbook | catalog_textbooks | db.textbook | بيانات الكتاب الوصفية (مفتاح S3 لملف PDF على Subject.pdf) |
Curriculum | catalog_curricula | db.curriculum | سجلّات المناهج الـ12؛ هدف مفتاح curriculumId |
نماذج الجسر (تحمل schoolId)
| النموذج | الجدول (@@map) | المُوصِّل | الغرض |
|---|---|---|---|
SubjectSelection | school_subject_selections | db.subjectSelection | صفّ لكل مادة+صفّ مُتبنّى؛ isActive يُفعّل/يُعطّل المادة |
ContentOverride | school_content_overrides | db.contentOverride | تجاوز فصل/درس/فيديو لكل مدرسة؛ isHidden يُخفي المحتوى |
InstructorPreference | school_instructor_preferences | db.instructorPreference | ترتيب معلّم/فيديو لكل مدرسة |
BookSelection | school_book_selections | db.bookSelection | يجسر Book من الفهرس إلى مكتبة مدرسة |
مرايا المدرسة (مفتاح أجنبي للفهرس → catalogXxxId)
نموذج الفهرس ونظيره المُنطَق للمدرسة هما نموذجان مختلفان. عند قراءة Exam راجع
الجدول لتعرف أيّهما المقصود. مرآة المدرسة ترتبط بالفهرس عبر مفاتيح أجنبية اختيارية
catalogSubjectId / catalogChapterId / catalogLessonId.
| الفهرس (عام) | مُنطَق للمدرسة (لكل مستأجر) |
|---|---|
Exam → catalog_exams | SchoolExam → exams |
Book → catalog_books | SchoolBook → books |
Assignment → catalog_assignments | SchoolAssignment → assignments |
Question → catalog_questions | QuestionBank → question_bank |
ExamTemplate → catalog_exam_templates | SchoolExamTemplate → exam_templates |
// QuestionBank, SchoolExam — link to catalog hierarchy
catalogSubjectId String?
catalogChapterId String?
catalogLessonId String?
// SchoolAssignment — link to catalog lesson
catalogLessonId String?التعدادات (Enums)
ContentStatus DRAFT, REVIEW, PUBLISHED, ARCHIVED, DEPRECATED
ApprovalStatus PENDING, APPROVED, REJECTED
ContentVisibility PRIVATE, SCHOOL, PUBLIC, PAID
SchoolLevel ELEMENTARY, MIDDLE, HIGH
StreamType GENERAL, SCIENCE, ARTS, COMMERCE, TECHNICAL, RELIGIOUS
MaterialType TEXTBOOK, SYLLABUS, REFERENCE, STUDY_GUIDE, PROJECT, WORKSHEET,
PRESENTATION, LESSON_NOTES, VIDEO_GUIDE, LAB_MANUAL, OTHER
QuestionType MULTIPLE_CHOICE, TRUE_FALSE, SHORT_ANSWER, ESSAY, FILL_BLANK,
MATCHING, ORDERING, MULTI_SELECT
QuestionSource MANUAL, AI, IMPORTED
DifficultyLevel EASY, MEDIUM, HARD
BloomLevel REMEMBER, UNDERSTAND, APPLY, ANALYZE, EVALUATE, CREATE
ProposalType SUBJECT, CHAPTER, LESSON, VIDEO
ProposalStatus DRAFT, SUBMITTED, IN_REVIEW, APPROVED, REJECTED, PUBLISHED
EnrollmentStatus PENDING, ACTIVE, COMPLETED, CANCELLED, EXPIRED
ContentVisibility هو البوّابة التي يحملها كل عنصر مُساهَم به: PRIVATE (مدرسة
المُنشئ فقط)، SCHOOL (المدارس التي تستخدم تلك المادة، مجاناً)، PUBLIC (أي
شخص، مجاناً)، PAID (أي شخص، محجوب بالشراء). راجع
الرؤية والمحتوى المدفوع.
تفصيل نماذج المحتوى
Material (الجدول catalog_materials) — كتب ومناهج وأوراق عمل على أي مستوى:
| الحقل | النوع | ملاحظات |
|---|---|---|
catalogSubjectId / catalogChapterId / catalogLessonId | String? | أحدها مضبوط (مفتاح أجنبي إلى هرم الفهرس) |
title / lang | String | lang افتراضي "ar" |
type | MaterialType | TEXTBOOK، SYLLABUS، WORKSHEET، … |
fileUrl / fileKey / fileSize / mimeType / pageCount | متنوّع | مُخزَّن على S3 |
externalUrl | String? | للموارد غير المرفوعة |
contributedBy / contributedSchoolId | String? | النسب |
approvalStatus / visibility | تعدادات | المراجعة + الحجب |
Assignment (الجدول catalog_assignments) — نفس بنية Material بالإضافة إلى
instructions/rubric (String?)، وtotalPoints (Decimal?)، وestimatedTime
(Int?، بالدقائق)، وassignmentType (homework/project/lab/essay/presentation).
ExamQuestion (الجدول catalog_exam_questions) — جدول وصل يربط Exam ↔
Question مع order وتجاوز points لكل اختبار. الفهارس:
@@unique([catalogExamId, order])، @@unique([catalogExamId, catalogQuestionId]).
يحلّ محلّ حقل JSON القديم Exam.questions.
Video، Attachment — المخطّطات الكاملة في prisma/models/video.prisma
(lesson_videos، lesson_attachments). أهم حقول Video: videoUrl،
provider (youtube/vimeo/self-hosted)، visibility، price،
approvalStatus، إضافةً إلى التفاعل (viewCount، likeCount، averageRating،
isFeatured). الفيديوهات المدفوعة تُحجَب عبر VideoPurchase.
التهيئة (Provisioning)
لا تستنسخ المدرسة الفهرس قطّ. عند انتهاء الإعداد، يستدعي completeOnboarding
(src/components/onboarding/legal/actions.ts) الدالة setupCatalogForSchool
(src/components/catalog/setup.ts): فهي تستنتج المنهج، وتجد المواد
المطابقة عبر تراجع تدريجي، وتبني المراحل/الصفوف/المسارات الأكاديمية من إعدادات
المنهج، وتكتب صفّ جسر SubjectSelection واحداً لكل مادة وصفّ مُتبنّى.
import { setupCatalogForSchool } from "@/components/catalog/setup"
await setupCatalogForSchool(schoolId, { country: "US", curriculum: "US" })
await setupCatalogForSchool(schoolId, { country: "AE", curriculum: "IB-DP" })
await setupCatalogForSchool(schoolId, { country: "GB", curriculum: "GB" })inferCurriculum + تراجع findSubjects
صفّ المدرسة لا يخزّن رمز المنهج — inferCurriculum() يشتقّه من البلد + النوع
وقت التشغيل. ثم يحلّ findSubjects() المواد عبر تراجع تدريجي من 4 خطوات، فتحصل
المدرسة دوماً على شيء ما:
| الخطوة | المُرشِّح |
|---|---|
| 1 | country + curriculum + schoolType |
| 2 | country + curriculum |
| 3 | country="*" + curriculum (عالمي) |
| 4 | US (تراجع أساسي) |
المواد المخصّصة لصف بعينه تُنتج ربطاً 1:1 — "Math Grade 3" يُربَط مباشرةً بالصف الثالث في المدرسة.
ensureSubjectSelections — إصلاح ذاتي كسول
تعمل التهيئة بأسلوب fire-and-forget عبر after() في Next.js. إن غابت صفوف الجسر،
يُصلِحها ensureSubjectSelections بشكل كسول عند أول قراءة، فيُصحَّح فشل التهيئة
الجزئي ذاتياً — لاختيارات المواد فقط.
طبيب التهيئة — repairProvisioning
كانت الاختيارات هي المرحلة الوحيدة التي تُصلَح ذاتياً؛ انقطاع serverless كان لا
يزال قادراً على ترك مدرسة بلا حصص أو شُعَب أو خانات جدول. الطبيب في
src/components/catalog/provision.ts يغلق هذه الثغرة:
getProvisioningStatus(schoolId)— جولة عدّ واحدة مُجمَّعة عبر كل مرحلة (الافتراضات، البنية الأكاديمية، الاختيارات، الجدول الزمني، الشُّعَب، خانات الجدول، رمز الانضمام) مع تقارير إضافية للعرض فقط (المسارات، كتب المكتبة).repairProvisioning(schoolId)— يشغّل المراحل الناقصة فقط بترتيب الاعتمادية، وكل مرحلة معزولة بحيث لا يُوقف فشلُ واحدة البقيةَ. كل خطوة أساسية قابلة لإعادة التنفيذ — إعادة تشغيله على مدرسة سليمة لا تفعل شيئاً.
ثلاثة مستدعين يلتقون عليه: خطّاف after() في الإعداد الأولي، ومسار
publishSchool اليدوي، وجدول مدارس المُشغِّل (إجراء Repair Provisioning).
applyTimetableStructureForNewSchool صار هو الآخر قابلاً لإعادة التنفيذ — إعادة
تشغيله لم تعد تكرّر حصص المدرسة.
البنية الأكاديمية لكل منهج (الثغرة المُصلَحة)
كان setup.ts القديم يُضمِّن النموذج السوداني — مراحل عربية 6+3+3، أسماء صفوف
عربية، مسارات علمي/أدبي مفروضة على الصفوف 10–12 — ويطبّقه على كل مدرسة، فكانت
مدرسة أمريكية/بريطانية/IB تحصل على أسماء صفوف عربية ومسارات لا تخصّها. هذا
مُصلَح الآن. التهيئة تحلّ رمز منهج المدرسة إلى CurriculumAcademicConfig في
src/components/catalog/academic-config.ts (CURRICULUM_ACADEMIC_CONFIG،
يُختار عبر getAcademicConfig). مدخل SD يحفظ الثوابت الأصلية بايتاً ببايت، فتُهيَّأ
المدارس السودانية تماماً كما كانت.
| رمز/رموز المنهج | البنية | تسمية الصفوف | المسارات |
|---|---|---|---|
SD، SA، EG، AE، QA، KW، JO | عربي 6+3+3 | الصف الأول … | علمي / أدبي من الصف 10 |
US، CAIE-IGCSE، IB-DP | إنجليزي 5+3+4 | Grade N | لا شيء |
GB | مراحل رئيسية (خريطة 6+3+3) | Year N | لا شيء |
CBSE | 5+3+4 (ابتدائي/متوسط/ثانوي) | Class N | لا شيء |
| (غير معروف) | إنجليزي عام 6+3+3 | Grade N | لا شيء (GENERIC_FALLBACK) |
معرّفات (slugs) الصفوف غير قابلة للضبط عمداً — تبقى
grade-${n}في كل مكان لأن ربطYearLevelفيsetup.tsيطابق على شكل ذلك المعرّف. الاسم المعروض، وحدود المراحل، وسياسة المسارات فقط هي ما يتغيّر لكل منهج.
الاقتراحات والموافقة
يمكن للمدرسة أن تقترح محتوى فهرس جديداً، وعند الموافقة تتبنّاه اختيارياً. هذا هو تدفّق الطلب الذي شُحِن هذه الجلسة — لاحظ أن الموافقة تنشر إلى الفهرس فقط؛ لا جسر تلقائي (المدرسة تضيفه صراحةً).
School proposes a subject/chapter/lesson
→ Proposal { status: SUBMITTED } (requireProposer: ADMIN / DEVELOPER / TEACHER)
Operator queue at /catalog/proposals (sidebar badge shows SUBMITTED count)
→ approveProposal → creates Subject/Chapter/Lesson (status PUBLISHED) in the catalog
→ proposal PUBLISHED, catalogEntityId set
→ NO auto-bridge (opt-in)
→ notifies proposer + school ADMINs (in_app + email, school-language aware)
School catalog picker pins the new subject ("Requested by your school — now ready")
→ one-time reminder dialog + Add CTA
→ pin clears once the subject is added (SubjectSelection exists)
→ rejectProposal → notifies proposer + ADMINs with the rejection reason
الاقتراح (جانب المدرسة)
تكتب submitSubjectProposal / submitChapterProposal / submitLessonProposal
(src/components/school-dashboard/listings/subjects/catalog/proposal-actions.ts)
صفّ Proposal (catalog_proposals) بحالة status: SUBMITTED. مُصرَّح به عبر
requireProposer — ADMIN أو DEVELOPER أو TEACHER ممّن لديه schoolId. حقل
Proposal.data (JSON) يحمل حقول الكيان؛ واقتراحات الفصل/الدرس تشير إلى
parentSubjectId / parentChapterId. يمكن تحرير اقتراح DRAFT أو REJECTED وإعادة
إرساله (updateProposal).
طابور المُشغِّل
/catalog/proposals (لـDEVELOPER فقط) يسرد الاقتراحات عبر getProposalsForReview،
مع ضبط المُرشِّح افتراضياً على SUBMITTED. يحسب تخطيط الفهرس أعداد الشارة —
db.proposal.count({ where: { status: "SUBMITTED" } }) — ويعرض تسمية التنقّل
بصيغة Proposals (N) عند وجود معلّق.
الموافقة → الفهرس فقط
تُشغِّل approveProposal التدفّق كاملاً في معاملة واحدة (فحص حالة متفائل داخل
المعاملة، وإعادة محاولة عند تضارب المعرّف، والأسماء العربية تحصل على لاحقة معرّف
عشوائية). تُنشئ Subject/Chapter/Lesson بحالة status: PUBLISHED، وتعلّم
الاقتراح PUBLISHED مع catalogEntityId، ولا تُنشئ SubjectSelection —
المدرسة تتبنّاه اختيارياً. تنطلق الإشعارات بعد المعاملة (فشل الإشعار لا يتراجع
عن الموافقة أبداً):
- لغة المدرسة تُحلّ عبر
resolveSchoolLang(schoolId)(عنوان/متن ثنائي اللغة). - يُعاد استخدام
NotificationTypedocument_sharedللموافقة، و**system_alert** للرفض. metadataيحمل{ entityType: "proposal", kind: "proposal_approved" | "proposal_rejected", catalogEntityId, url: "/subjects/catalog" }.- يُسلَّم إلى المقترِح (يُتخطّى إن كان المقترِح ADMIN — توزيع الجمهور حسب الدور
يغطّيه أصلاً، تفادياً للتكرار) وكل ADMIN في المدرسة، على
in_app+email. rejectProposalيتطلّب سبباً ويضمّنه في الإشعار.
مُثبَّت في مُنتقي المدرسة
مُنتقي فهرس المدرسة (subject-picker.tsx) يأخذ pinnedSubjectIds — المواد المُوافَق
عليها التي طلبتها هذه المدرسة ولم تُضِفها بعد. تُعرَض في قسم مُثبَّت "Requested by
your school — now ready" مع زرّ Add، ويعلن عنها مرّةً واحدة حوار
CatalogReadyReminder (يُخزَّن الصرف في localStorage تحت
catalog-ready-dismissed:${schoolId}). يُرشِّح التثبيت أي مادة لها اختيار بالفعل،
فيُمسَح تلقائياً بمجرّد إضافة المادة.
الرؤية والمحتوى المدفوع
كل عنصر مُساهَم به يحمل ContentVisibility إضافةً إلى price/currency اختيارية.
دورة حياة المساهمة:
Teacher/School creates content
→ approvalStatus: PENDING, visibility: PRIVATE, status: DRAFT
SaaS admin reviews (/catalog/approvals)
→ APPROVED → status set to PUBLISHED, visibility set by reviewer
PRIVATE — only creator's school
SCHOOL — schools using that subject (free)
PUBLIC — anyone (free)
PAID — anyone, gated by purchase (priceable types only)
→ REJECTED → reason sent to creator
الموافقة تنشر الآن (الثغرة المُصلَحة)
مساهمات المدرسة المُوافَق عليها تُنشأ بحالة status: DRAFT، لكن مسارات تصفّح المدرسة
لا تُظهر إلا الصفوف PUBLISHED + APPROVED — فكانت المساهمة المُوافَق عليها تبقى
سابقاً DRAFT غير مرئية. الآن تضبط approveContent
(saas-dashboard/catalog/approval-actions.ts) أيضاً status: PUBLISHED لـ
Question وMaterial وAssignment (لا ContentStatus لـVideo؛ والكتاب يُنشَر +
يُختار تلقائياً في مكتبة المساهِم).
الفيديوهات المدفوعة (موصولة)
الفيديوهات محجوبة بالكامل عبر Stripe: صفّ VideoPurchase يسجّل الشراء، والرابط
يُقدَّم عبر CloudFront مُوقَّع، والفيديو PAID غير المُشترى يُعيد رابطاً null
فلا يستطيع المشغّل جلبه. ضبط فيديو على PAID عند الموافقة يتطلّب سعراً موجباً وعملة
من 3 أحرف.
الاختبارات / الأسئلة المدفوعة (مؤجّل)
يحمل Question وExam حقلَي price/currency ويقبلان رؤية PAID، لكن تدفّق
الشراء غير مبني — الحقول موجودة لمتجر اختبارات/أسئلة مدفوع مستقبلاً.
إدارة أعلام المُشغِّل
updateContentFlags (+ الحوار content-flags-dialog) يتيح لـDEVELOPER ضبط
الرؤية / الحالة / السعر لكل نوع محتوى، مستقلاً عن الموافقة/الرفض. يفرض الحوار قائمة
بيضاء لكل نوع:
| الحقل | مسموح على |
|---|---|
visibility | كل نوع |
status | كل نوع عدا Video (لا ContentStatus) |
price / currency | Question، Video، Exam فقط |
PAID | الأنواع القابلة للتسعير فقط — تتطلّب سعراً + عملة 3 أحرف |
ضوابط جانب المدرسة
SubjectSelection.isActive— يُفعّل/يُعطّل مادة مُتبنّاة للمدرسة.ContentOverride.isHidden— يُخفي فصلاً/درساً/فيديو. هذا الآن يُرشِّح فعلاً صفحة تفاصيل المادة للأدوار غير الإدارية (get-course.tsيقرأContentOverrideويُسقِط العُقَد المخفيّة؛ وإن فشل استعلام التجاوز يُظهر كل شيء بدل خطأ 500). الإداريون يستخدمونadmin-get-course.tsالذي يُعيد كل المحتوى موسوماً بـ_isHiddenفيستطيع لوح Customize إدارة الرؤية.- البحث العام يُرشِّح الآن إلى المواد المنشورة فقط
(
atom/generic-command-menu/server/global-search.ts) — تسريب سابق لمحتوى غير منشور أُصلِح.
هندسة المنهج
هرم الفهرس ثلاثة جداول عامة، كلّها بلا نطاق؛ والمدارس تشير إليها عبر الجسر.
slug هو مفتاح الـupsert الأساسي — يُرمِّز البلد + الصفّ + المادة (sd-g5-math،
us-g5-math)، فلا حاجة لقيد فريد مركّب على (country, curriculum, grade, name).
model Subject { // table catalog_subjects
country String @default("SD") // ISO 3166-1 alpha-2
curriculum String @default("SD") // canonical code: bare ISO (US, SD, GB) or BODY-PROGRAMME (IB-DP, CAIE-IGCSE, CBSE)
curriculumId String? // optional FK → Curriculum
concept String? // shared image key
thumbnail String? @map("thumbnailKey") // S3 key for WebP variants
grades Int[] @default([]) // [5] = grade 5 only
levels SchoolLevel[] // [ELEMENTARY]
slug String @unique // sd-g5-math, us-g5-math
totalChapters Int // denormalized counts
totalLessons Int
}مستودع الكتالوج — databayt/catalog
لم تعد المناهج العميقة تعيش في هذا المستودع. مصدر الحقيقة هو
github.com/databayt/catalog، يُستنسخ بجوار
هذا المستودع في ../catalog، وهو مرآة مطابقة لشبكة التوزيع:
../catalog/sd/g6/math/structure.json == cdn.databayt.org/catalog/sd/g6/math/structure.json
../catalog/sd/g6/math/c1/l3/qbank.json == cdn.databayt.org/catalog/sd/g6/math/c1/l3/qbank.json
<curriculum>/<grade>/<subject>/
structure.json # id، title {ar,en}، المصدر، الفصول c<N> ← الدروس l<N>
qbank.json · exams.json # مستوى المادة
c<N>/qbank.json · exams.json # الفصل N (بترتيب الكتاب)
c<N>/l<N>/… # الدرس N داخل الفصل
textbook.pdf · textbook.md · cover/thumbnail/banner.jpg · pages/<N>.webp
معرّف المادة هو <curriculum>-<grade>-<subject> (sd-g12-biology) — المقاطع
الثلاثة نفسها التي في المسار، فلا جدول تحويل بين المجلّد والمعرّف. يعيش السؤال مرة
واحدة في مجلّد نطاقه، وتحمل الامتحانات مفردات examType في هوغوورتس (final،
midterm، chapter_test، practice، quiz، diagnostic). تعديلات المحتوى تذهب
إلى مستودع الكتالوج (ويتحقّق منها هناك pnpm validate)، لا إلى هذا المستودع.
tree.ts — بذرة الكتالوج الوحيدة
prisma/seeds/catalog/tree.ts (seedCatalogTree) يقرأ النسخة المحلية لـsd وgb
وcbse وib-dp وcaie-igcse (شجرة us في الكتالوج هي نسخة الدار الأمريكية
ولا تُعتمد — يبقى us.ts لمنهج US K-12). لكل مادة يُحدِّث Subject ثم يتبنّى
الفصول والدروس بدل إعادة بنائها:
- تُوجد المادة بمعرّف الكتالوج، وإلا بمعرّفها السابق (
scripts/migrate/renames.jsonفي الكتالوج) فيُعاد تسميتها في مكانها — المعرّف الداخلي نفسه واختيارات المدارس نفسها؛ ويحوّلproxy.tsالروابط القديمة بـ308 (src/components/catalog/legacy-slugs.ts)؛ - تُطابَق الفصول والدروس بمعرّفها السابق (أو
c<N>/l<N>الحالي) وتُسمّى بموضعها — فتبقى المعرّفات، وتحتفظ الحصص المباشرة وتقدّم الطلاب بدروسها؛ - ما لم يعد في الكتالوج يصبح
ARCHIVEDببادئةarchived-، ولا يُحذف أبداً.
مفاتيح الأصول تشير إلى المسار القانوني catalog/<cur>/<grade>/<subject>/… متى وُجد
الملف في assets.lock.json بالكتالوج. تُعاد بناء الأسئلة والامتحانات لكل مادة من
الملفات، والنطاق من المجلّد (أسئلة مستوى الفصل تُوزَّع على دروس ذلك الفصل لاختبار
التدريب). بلا نسخة محلية لا تفعل البذرة شيئاً ولا تحذف شيئاً، فبذور وقت النشر آمنة.
CATALOG_DIR / CATALOG_CURRICULA / CATALOG_CONCURRENCY تضبطها.
المناهج والرموز
المناهج الوطنية تستخدم رمز دولة ISO 3166-1 المجرّد — البلد هو المُعرِّف؛
والبرامج الدولية تستخدم رمز {body}-{programme}. الصفوف الموجودة رُحِّلت من
الرموز القديمة (national / us-k12 / ib) عبر ترحيل
canonicalize_curriculum_codes (المُفعَّل الآن). يحتفظ Curriculum.slug بقيمه
الخاصّة (sd-national، ib-diploma).
| المنهج | الرمز | النوع |
|---|---|---|
| السودان | SD | وطني |
| السعودية | SA | وطني |
| مصر | EG | وطني |
| الولايات المتحدة | US | وطني |
| إنجلترا | GB | وطني |
| الإمارات | AE | وطني |
| قطر | QA | وطني |
| الكويت | KW | وطني |
| الأردن | JO | وطني |
| بكالوريا IB | IB-DP | دولي |
| كامبريدج IGCSE | CAIE-IGCSE | دولي |
| الهندي CBSE | CBSE | دولي |
التغطية
كل المناهج الاثني عشر لها مواد. ستة بعمق (فصول ودروس حقيقية) — US، والسودان،
وإنجلترا (gb في الكتالوج)، وكامبريدج IGCSE، وIB-DP، والهندي CBSE. أما المناهج
العربية الوطنية الستة فتبقى مواد فقط حتى تُؤلَّف بنية كتبها الوزارية.
| المنهج | الرمز | الصفوف | مواد | فصول | دروس | المصدر | البذرة |
|---|---|---|---|---|---|---|---|
| الولايات المتحدة | US | 1–12 | ~240 | ~750 | ~3,993 | US-inventory | us |
| السودان | SD | 1–12 | 135 | 812 | 4,144 | الكتالوج sd | sd |
| إنجلترا | GB | 1–12 | 184 | 363 | 730 | الكتالوج gb | gb |
| كامبريدج IGCSE | CAIE-IGCSE | 10 | 8 | 76 | 76 | الكتالوج caie-igcse | caie-igcse |
| بكالوريا IB | IB-DP | 12 | 9 | 49 | 49 | الكتالوج ib-dp | ib |
| الهندي CBSE | CBSE | 10 | 7 | 58 | 58 | الكتالوج cbse | cbse |
| السعودية | SA | 1–12 | ~132 | — | — | sa.ts المضمّن | sa |
| مصر | EG | 1–12 | ~140 | — | — | eg.ts المضمّن | eg |
| الإمارات | AE | 1–12 | ~144 | — | — | ae.ts المضمّن | ae |
| قطر | QA | 1–12 | ~122 | — | — | qa.ts المضمّن | qa |
| الكويت | KW | 1–12 | ~139 | — | — | kw.ts المضمّن | kw |
| الأردن | JO | 1–12 | ~150 | — | — | jo.ts المضمّن | jo |
المناهج العابرة للحدود العميقة (كامبريدج، IB، CBSE) تغطّي صفّاً تمثيلياً حتى الآن؛ وتوسعتها لكل صفّ آليّة (تأليف مزيد من
structure.jsonفي الكتالوج). أما شجرةusفي الكتالوج (الدار الأمريكية، 128 مادة) فهي غير مُدمَجة — تتصادم على فضاء المعرّفus-g{N}-*؛ تبقى طبقة مرجعية.
قارئ الكتاب المدرسي — الكتاب صفحاتٍ (2026-09-07)
يفتح المسار /{lang}/subjects/{slug}/textbook الكتاب كما يفتحه تطبيق Books على
iOS: الغلاف أولاً (خلفية مصبوغة من لون الغلاف، العنوان والطبعة وعدد الصفحات
والوحدات والدروس، زرّا المحتويات وابدأ القراءة، وورقة عن الكتاب)، ثم
صفحة محتويات مصمَّمة تحمل أرقام صفحات الكتاب المطبوعة، ثم النص شاشةً لكل صفحة.
كل وحدة تدفّق أعمدة CSS عرضُ عموده عرضُ الشاشة، فتصبح أعمدة المتصفح صفحات؛
تنزلق الصفحات، ويقلّبها النقر على الحافة والسحب ومفاتيح الأسهم (معكوسة
للعربية)، والنقر في الوسط يخفي الأدوات، والعدّاد يقرأ «N من T» (أو N وحده عند
إخفاء الأدوات). الزر الدائري يفتح قائمة القراءة: المحتويات — ٪، البحث في
الكتاب (يطوي التشكيل، مقتطفات برقم الصفحة المطبوع، وإبراز النتيجة في موضعها)،
السمات والإعدادات (الأصلي / ورقي / هادئ / ليلي، ثمانية أو روبِك، ستة أحجام،
ثلاثة تباعدات)، المشاركة، PDF، الصفحات الأصلية (صور pages/<N>.webp شاشةً
لكل صفحة) والإشارات المرجعية. الأرقام المطبوعة تقوم على
إزاحة «المطبوع → PDF» تؤخذ من أول مصدر يملكها: pageOffset الذي يكتبه المؤلف في
structure.json، أو ترقيم الصفحات الذي تركه OCR (الفيزياء: PDF − 8)، أو
تصويت عناوين البنية نفسها حين تُعثَر عليها في النص (ترقيم الأحياء حطام OCR،
وعناوينه تصوّت 8). وصفحات الوحدات والدروس من ملف التأليف structure.json
المنشور بجانب التوأم (catalog/textbooks/<slug>/structure.json — الفيزياء
والأحياء حتى الآن؛ بقية الكتب تعود إلى مطابقة الأسماء). الصفحة الأولى من المسح
هي شاشة الغلاف لا صفحة نص. الموضع والسمة وإعدادات النص تُحفظ في المتصفح.
الملفات: school-dashboard/listings/subjects/textbook/ (spine.ts،
engine.ts، book.tsx، sheets.tsx، cover.tsx، toc.tsx بجانب parse.ts
وarticle.tsx)؛ الاختبارات في src/tests/school-dashboard/listings/subjects/.
المحتوى الحقيقي — السودان (كل الصفوف)
بنوك أسئلة السودان وامتحاناته تأتي مع بذرة الشجرة: 7,395 سؤالاً فريداً و1,533
امتحاناً عبر الصفوف 1–12، وكل سؤال محفوظ في مجلّد فصله/درسه في الكتالوج (قواعد
تحليل المعرّفات التي كانت في sd-content.ts وضعته مرة واحدة أثناء ترحيل الكتالوج).
وأُزيل هناك 3,754 سؤالاً قالبياً حشواً. الصفوف موسومة ["sd", "<grade>", "<subject>"]؛
ويتخطّى content.ts المحتوى الاصطناعي لأي مادة لها أسئلة موسومة "sd".
دروس السودان بلا صفوف Video عمداً — مشغّل الدرس في lumos يعود إلى مقطع
story.mp4 المشترك في كل درس سوداني، فلا يظهر مشغّل فارغ ولا رابط لكائن مفقود
على CDN.
المحتوى المُولَّد
catalog/content.ts يقرأ الهرم المنشور ويُولِّد صفوفاً اصطناعية بالجملة:
اختبارات (لكل مادة/فصل/درس)، وبنك أسئلة (~10/مادة، 6/فصل، 4/درس)، ومواد (بيانات
وصفية فقط — fileUrl يكون null)، وواجباً واحداً لكل درس. المنهج مواد-فقط يحصل على
صفوف لكل مادة فقط. المواد التي تحمل محتوى حقيقياً مُدمَجاً (أسئلة موسومة "sd")
تُتخطّى، والصفوف الاصطناعية اليتيمة (مفاتيح نطاق أفرغتها إعادة بناء الفصول)
تُحذَف في كل تشغيل. والاستثناء هو catalog/exam-templates.ts الذي يكتب مخطّطات +
قوالب حقيقية مؤلَّفة يدوياً (قابلة لإعادة التنفيذ، لكل مادة). نموذج Quiz لا يُبذَر.
content.ts قابل لإعادة التنفيذ — راجع العمليات.
جودة استخراج جدول المحتويات
كثير من ملفات السودان (خاصّةً الصفوف 6–8 و10–12) أنتجت مخرجات pdftotext مشوّهة أو
فارغة، فبقيت فصول بـ0 دروس:
| نطاق الصفوف | بدروس | بـ0 دروس |
|---|---|---|
| 1–5 | 31 (89%) | 4 (11%) |
| 6–9 | 8 (40%) | 12 (60%) |
| 10–12 | 14 (29%) | 34 (71%) |
الأولويات: تمريرة OCR (Tesseract عربي) على الملفات الممسوحة، ثم إدخال يدوي للصفوف 10–12 عبر طبقة المحتوى / تدفّق الاقتراح.
خريطة الملفات
../catalog/ # github.com/databayt/catalog — المحتوى (مرآة شبكة التوزيع)
prisma/
models/catalog.prisma # Subject, Chapter, Lesson + shared enums
seeds/catalog/
tree.ts # بذرة الكتالوج: sd · gb · cbse · ib-dp · caie-igcse
engine.ts # seedSubjectsOnly (المناهج الوطنية الضحلة)
registry.ts # 12 Curriculum records + curriculumId backfill
index.ts # seedCatalog + seedFullCatalog
us.ts # US (240, us-inventory.json)
{sa,eg,ae,qa,kw,jo}.ts # 6 subjects-only nationals
concepts.ts / banners.ts # shared image upload + backfill
content.ts / books.ts / videos.ts / exam-templates.ts / demo.ts
single.ts # CLI registry
src/components/catalog/
catalog-key.ts # باني مفاتيح CDN (مطابق لـ @databayt/catalog)
legacy-slugs.ts # معرّف المادة السابق ← معرّف الكتالوج (تحويل في proxy)
setup.ts # findSubjects(), inferCurriculum()
academic-config.ts # per-curriculum CurriculumAcademicConfig
image.ts / image-url.ts # Sharp pipeline + URL resolution
concepts-data.ts # single source of concepts + nearestConcept
منهج الولايات المتحدة
مصدر US هو جرد محتوى K-12: scripts/us-curriculum/us-inventory.json. تتوسّع 62
مادة أساسية إلى ~240 صفّ Subject مخصّص لصف عبر بذرة us. تصنيف US وصوره بذرا
أصول المفاهيم المشتركة، وهو المرجع الذي تُحسَّن منه بقية المناهج.
| المقياس | العدد |
|---|---|
| المواد | 62 |
| مجموعات المواضيع | 201 |
| المواضيع الفرعية | 986 |
| الفيديوهات | 22,289 |
| الموارد | 43,075 |
| المستوى | مواد | مجموعات | مواضيع | فيديوهات | موارد | الصفوف |
|---|---|---|---|---|---|---|
| Elementary | 18 | 49 | 346 | 8,130 | 17,233 | K-5 |
| Middle | 21 | 73 | 276 | 5,490 | 10,754 | 6-8 |
| High | 23 | 79 | 364 | 8,669 | 15,088 | 9-12 |
كل موضوع فرعي في الجرد مفتاحه slug:
type SourceTopic = {
slug: string // kebab-case identifier
name: string // display name
videos: number
resources: number
coverId: string
subject: string
topicGroup: string
}# list every sub-topic for a tier
jq '.tiers.elementary.subjects[] | .topics[]' scripts/us-curriculum/us-inventory.json
jq '.tiers.middle.subjects[] | .topics[]' scripts/us-curriculum/us-inventory.json
jq '.tiers.high.subjects[] | .topics[]' scripts/us-curriculum/us-inventory.jsonمنهج السودان
يغطّي السودان الصفوف 1–12 في بنية 6+3+3 (Elementary، Middle، Secondary)، مُستخرَجة
من ملفات الكتب المدرسية المنشورة من المركز القومي للمناهج والبحث التربوي (بخت
الرضا). المواد والفصول والدروس تعيش في الفهرس بـcountry: "SD" وcurriculum: "SD".
نمط المعرّف sd-g{N}-{subject} (مثل sd-g5-math)؛ بادئة المعرّف تجميلية، ورمز
curriculum هو مفتاح الربط القانوني.
| الصف | المستوى | مواد | فصول | دروس | ملاحظات |
|---|---|---|---|---|---|
| 1 | Elementary | 4 | 17 | 173 | العربية، الإنجليزية (SMILE Starter 1)، التربية الإسلامية، الرياضيات — سلسلة 2020 |
| 2 | Elementary | 4 | 22 | 131 | المجموعة نفسها، SMILE Starter 2 |
| 3 | Elementary | 6 | 36 | 176 | + الجغرافيا، العلوم (سلسلة 2020، حُدِّث 2026-09)؛ الإنجليزية = كتاب التلميذ SMILE Book 1 |
| 4 | Elementary | 8 | 40 | 232 | + التربية الفنية، تكنولوجيا المعلومات، التاريخ، العلوم (أُضيف 2026-09)؛ ملف الرياضيات أُضيف 2026-09 |
| 5 | Elementary | 14 | 66 | 406 | + ملبسنا، المورد، الأرض بيئة الحياة، الاقتصاد المنزلي، التقنية |
| 6 | Elementary | 9 | 44 | 176 | + التربية الفنية، العلوم (أُضيفا 2026-09)؛ الإنجليزية ما زالت كتاباً خاطئاً (SMILE Book 4 غير متاح) |
| 7 | Middle | 9 | 67 | 309 | المجموعة كاملة بما فيها SMILE Book 7 (2024) |
| 8 | Middle | 10 | 66 | 361 | المجموعة كاملة؛ الجغرافيا استُبدلت والتربية الوطنية أُضيفت 2026-09؛ التربية الفنية غير متاحة |
| 9 | Middle | 9 | 106 | 668 | طبعات 2024 النهائية، SMILE Book 9 |
| 10 | Secondary | 18 | 110 | 488 | المنهج القومي الجديد (المركز القومي للمناهج 2025) — انظر أدناه |
| 11 | Secondary | 19 | 119 | 382 | المنهج القديم، كل المسارات (الطبعات الجديدة متوقعة 2026/27 ولم تُنشر بعد) |
| 12 | Secondary | 25 | 192 | 870 | سنة الشهادة — كل المسارات؛ 13 بنية أُعيد بناؤها من فهارس الكتب و5 مواد أُضيفت 2026-09 |
انتقل الصف الأول الثانوي إلى المنهج القومي السوداني الجديد في 2025/26 (طبعات
أولى من المركز القومي للمناهج مؤرَّخة 2025). منذ 2026-09-04 يحمل sd/g10/ في الكتالوج
تلك المجموعة: أربع مواد جديدة (التربية الوطنية، ريادة الأعمال، الفيزياء، وكتاب
اللغة العربية الموحَّد الذي يحلّ محلّ كتب المطالعة/البلاغة/النحو القديمة)، وثماني
مواد استُبدلت في مكانها (الأحياء، الكيمياء، التاريخ، الرياضيات ط3، العلوم الهندسية،
التربية الإسلامية — كانت الدراسات الإسلامية، التربية الفنية — كانت الفنون والتصميم،
وتكنولوجيا المعلومات والاتصالات — كانت علوم الحاسوب). الطبعات القديمة أُرشفت قبل
الانتقال إلى مستودع الكتالوج (تبقى في الأرشيف المحلي السابق، لا في الكتالوج). صفوف قاعدة البيانات الخاصة بها (sd-g10-literature،
sd-g10-rhetoric، sd-g10-arabic-advanced) تبقى منشورة حتى تُؤرشَف بقرار. البنى
مأخوذة من جداول محتويات الكتب نفسها (structure.json، source.basis: official-toc-2026-09)؛
السجل الكامل في docs/history/sd-textbook-audit.md بالكتالوج.
ولحق الصف الحادي عشر في 2026-09-05: أُعيد بناء بناه القديمة الثماني عشرة (وحدات
عامة بلا دروس تقريباً) من جداول محتويات الكتب نفسها (19 مادة، 122 وحدة، 511 درساً)،
وصار لكل كتاب في الصفين الحادي عشر والثاني عشر توأمٌ بصيغة Markdown بجوار ملف PDF على
شبكة التوزيع (catalog/sd/<grade>/<subject>/textbook.md، تُنتجه الكلمة المفتاحية
textbook: MarkItDown ثم إصلاح اتجاه العربية ثم OCR احتياطي بـ tesseract، مع درجة
جودة A–C في ترويسة الملف).
مسارات الثانوي (10–12) تُوجَّه بأنماط في setup.ts:
const SCIENCE_ONLY_PATTERNS = [
"physics",
"chemistry",
"فيزياء",
"كيمياء",
"أحياء",
]
const ARTS_ONLY_PATTERNS = [
"philosophy",
"فلسفة",
"أدب",
"بلاغة",
"مطالعة",
"نحو",
"عربية خاصة",
"رياضيات أساسية",
]خطّ معالجة البيانات
~/SD/*.pdf (260 raw, ~112 unique textbooks)
→ organize → scripts/sudan-data/pdfs/grade-{N}/sd-g{N}-{subject}.pdf
→ pdftotext → raw Arabic TOC text
→ parse TOC → scripts/sudan-data/toc/sd-g{N}-{subject}.json (97 files)
→ assemble-sudan-curriculum.ts → scripts/sudan-data/sudan-curriculum.json (master)
→ prisma/seeds/catalog/sd.ts → Subject + Chapter + Lesson (upsert)
ثغرات معروفة (2026-09-04): إنجليزية الصف 3 يُفترض أن تكون SMILE Starter 3 وإنجليزية الصف 6 SMILE Book 4 (كلاهما غير متاح على الشبكة)، التربية الفنية للصف 8 غير متاحة، كتب المنهج الجديد للصف الأول الثانوي في القرآن والفرنسية والعلوم الأسرية والعلوم العسكرية والإنجليزية والتربية المسيحية لم تُنشر بعد، والمواد الإحدى عشرة التي استُبدلت كتبها ما زالت تحمل بنوك أسئلة المنهج القديم على مستوى المادة (إعادة التأليف معلَّقة).
إضافة منهج وطني
المنهج الوطني الجديد (مثل مصر EG) يُؤلَّف في مستودع الكتالوج ثم يُعتمد هنا:
- في github.com/databayt/catalog: أضف
egإلىvocab/curricula.jsonوألِّفeg/curriculum.jsonوeg/g{N}/<subject>/structure.json(pnpm validate). - أضف
eg: { country: "EG", code: "EG", sortBase: … }إلىCURRICULAفيprisma/seeds/catalog/tree.ts(ومدخلاً فيsingle.tsإن أردت). - أضف
EG → "EG"إلىinferCurriculum()وCOUNTRY_CURRICULUM(src/lib/timetable-reference.ts). - أضف الأسماء العربية إلى
SUBJECT_CONCEPT_BY_NAMEفيconcepts-data.ts. - (اختياري) أضف مدخل
EGإلىCURRICULUM_ACADEMIC_CONFIGإن اختلف عن الافتراضي العربي المشترك 6+3+3. - شغّل
pnpm db:seed:single egثمpnpm db:seed:single concepts.
المفاهيم (Concepts)
المفهوم (concept) مُعرِّف مستقلّ عن المنهج يربط كل مادة بأصول بصرية مشتركة.
العربية (السودان) واللغات العالمية (US) تتشاركان نفس مفهوم languages ونفس صور S3.
كانت الرسومات تُشار إليها أصلاً من مكتبة خارجية أثناء النمذجة الأوّلية؛ وتلك الأصول
الآن مملوكة، ومُعاد رسمها، ومشتركة عبر كل منهج — راجع الأصول.
Subject (any curriculum)
└── concept: "math"
├── thumbnail: catalog/concepts/g{grade}-math/thumbnail-{size}.webp
├── banner: catalog/concepts/g{grade}-math/banner-{size}.webp
└── cover: catalog/concepts/math/cover
المفاهيم الـ23
arts، biology، career-tech، celebrations، chemistry، civics،
computer-science، earth-science، economics، english، geography،
health، history، languages، life-skills، math، pe، physics،
psychology، religion، science، sociology، teacher-pd.
صور المصدر تعيش في public/subjects/concepts/{concept}.jpg. بذرة concepts تعالج
كلاً منها إلى 4 نسخ WebP (sm/md/lg/original) وترفعها إلى S3 لكل الصفوف الـ12. كل
المناهج الـ12 تربط موادها بأحد هذه المفاهيم الـ23؛ ونموذج Image (catalog_images)
يخزّن السجلّات لكل نسخة.
مصدر واحد للحقيقة — concepts-data.ts
كل ما يخصّ المفاهيم يعيش في src/components/catalog/concepts-data.ts: المفاهيم
الـ23 وألوانها، وخرائط المطابقة الدقيقة (SUBJECT_CONCEPT_BY_SLUG،
SUBJECT_CONCEPT_BY_NAME)، وأحواض التدوير (CONCEPT_POOL)، وخوارزمية كلمات مفتاحية
nearestConcept() (إنجليزي + عربي) كي لا تبقى أي مادة بلا صورة (اللون المسطّح
هو الملاذ الأخير). كل بذرة (us.ts، sd.ts، engine.ts، concepts.ts) تستورد
منه — ولا تبقى نسخ لكل بذرة.
أحواض تدوير الفصول
الفصول داخل المادة تدور عبر حوض من 5 مفاهيم مرتبطة للتنوّع البصري (تُدوَّر بـ
sequenceOrder % poolSize): مثلاً math → math، science، computer-science،
physics، economics؛ وscience → science، biology، chemistry، physics،
earth-science. بذرة الكتالوج (tree.ts) ترث هذا؛ وللمناهج مواد-فقط،
تأتي صور الفصل/الدرس مجاناً بمجرّد توفّر العمق.
النسخ (Variants)
| النسخة | العرض | الجودة | الاستخدام |
|---|---|---|---|
-sm.webp | 200px | 95 | مصغّرات الشبكة |
-md.webp | 600px | 97 | صور البطاقات |
-lg.webp | 1200px | 100 | بانرات البطل |
-original.webp | كامل | بلا فقد | الدقّة الكاملة |
image.ts (خادم فقط — processAndUploadCatalogImage، deleteCatalogImage) يشغّل
Sharp؛ وimage-url.ts (آمن للعميل — getCatalogImageUrl) يبني {key}-{size}.webp
وقت القراءة. حلّ الرابط: CloudFront من thumbnailKey → تراجع ثابت قائم على المفهوم
→ null (خلفية لونية).
CDN والأصول
أصول الفهرس تتبع اصطلاح مفاتيح صارماً وتُقدَّم من S3 عبر CloudFront. المرجع الكامل
لشبكة توصيل المنصّة (الحاوية، مساعد asset()، أدلّة أصول الواجهة المسطّحة الخمسة)
يوجد في CDN & Assets — هذا القسم يغطّي قصّة الأصول الخاصّة بالفهرس
فقط.
يحمل Subject أربعة حقول مفاتيح S3 — thumbnail (@map("thumbnailKey"))،
banner (@map("bannerUrl"))، cover (غلاف الكتاب)، pdf (ملف الكتاب). يميّز
الاصطلاح بين *Key (مفتاح S3 خام، تُلحَق النسخ وقت القراءة) و***Url** (رابط
كامل التكوين، مثل أغلفة الكتب الخارجية). تخطيط S3:
catalog/concepts/g{n}-{concept}/thumbnail-{sm,md,lg,original}.webp
catalog/concepts/g{n}-{concept}/banner-{sm,md,lg,original}.webp
catalog/concepts/{concept}/cover
catalog/textbooks/{slug}/textbook.pdf
catalog/subjects/{slug}/…/thumbnail-{size}.webp # US lesson/chapter covers
جدول ثغرات الأصول الصادق
| الأصل | يُنتجه | الحالة |
|---|---|---|
| مصغّرات المواد | concepts.ts | مكتمل — كل المناهج الـ12، كل الصفوف الـ12 |
| البانرات | banners.ts | مُغطّى ذاتياً — ~10 من 23 مفهوماً لها بانر خاص؛ البذرة تستعير الآن بانر أقرب جار في CONCEPT_POOL للبقية (23/23 بعد التشغيل القادم) |
| أغلفة الكتب | — | مفقود — مفتاح cover مضبوط على كل مادة، لكن الكائن لم يُرفَع قطّ (تتراجع البطاقة إلى أيقونة) |
| ملفات الكتب (PDF) | assets push بالكتالوج | السودان + علوم CBSE ص10 — مثبّتة في assets.lock.json بالكتالوج |
| مصغّرات الدروس / الفصول | lesson-covers.ts | US فقط — تُسحَب من CDN وقت البذرة |
| الفيديوهات | videos.ts / مُساهَم به | مُتحقَّق بالفحص — البذرة تفحص كل .mp4 برأسية HEAD ولا تسجّل إلا الصفوف ذات الكائن الموجود (وتحذف الصفوف القديمة)؛ الرفع الفعلي ما زال معلّقاً |
| الكتب | books.ts | خارجي — 51 كتاباً على covers.openlibrary.org؛ السكربت scripts/snapshot-book-covers.ts يوطّنها إلى CDN لدينا (يعمل ببيانات AWS الإنتاج) |
| المواد | content.ts | بيانات وصفية فقط — fileUrl يكون null؛ بطاقات المواد تصبح قابلة للنقر تلقائياً فور وصول fileUrl/externalUrl |
العمليات
أوامر البذر
seedFullCatalog (بذرة full) يشغّل كل شيء بالترتيب القانوني — كل المناهج الـ12 →
registry → صور المفاهيم. وبذرة catalog الافتراضية هي المجموعة الفرعية السريعة: US
- السودان الكامل، مُسجَّلة. كل منهج آخر هو تشغيل صريح خاصّ به. استخدم دوماً
pnpm db:seed:single <name>— لا البذرة الكاملة قطّ (فهي يدوية فقط؛ راجع القاعدة أدناه).
البذرة (pnpm db:seed:single …) | المحتوى |
|---|---|
full | seedFullCatalog — كل المناهج الـ12 → registry → صور المفاهيم (قاعدة جديدة) |
catalog | الافتراضي السريع: US (~240) + السودان الكامل + registry |
us / sd | US (الجرد) / السودان من مستودع الكتالوج (tree.ts) |
gb / cbse / caie-igcse / ib / catalog-tree | المناهج العميقة من مستودع الكتالوج (tree.ts؛ catalog-tree = الكل) |
sa / eg / ae / qa / kw / jo | المناهج الوطنية الستة مواد-فقط (seedSubjectsOnly) |
registry | كل سجلّات Curriculum الـ12 + ملء Subject.curriculumId |
concepts / banners | مصغّرات المفاهيم والبانرات → Sharp → S3/CloudFront |
lesson-covers | مصغّرات دروس/فصول US (تعتمد على CDN) |
books / content / videos / exam-templates | كتب، محتوى مُولَّد، فيديوهات، مخطّطات/قوالب اختبارات |
demo | البنية الأكاديمية + صفوف الجسر للمدرسة التجريبية |
pnpm db:seed:single --list # list available seeds
pnpm db:seed:single catalog # fast default: US + full Sudan + registry
pnpm db:seed:single gb # British — deep, from the catalog repo
pnpm db:seed:single sa # Saudi Arabia — subjects-only national
pnpm db:seed:single registry # (re)link all 12 Curriculum records
pnpm db:seed:single concepts # thumbnails → S3/CDN
cd ../catalog && pnpm assets push --apply # textbook PDFs / art → CDN (catalog repo)التكرارية (Idempotency)
أغلب البذور آمنة للـupsert (بذور الصور تعيد الرفع إلى مفاتيح ثابتة، آمنة أيضاً).
بذرة المحتوى الآن قابلة لإعادة التنفيذ كذلك (مُصلَحة هذه الجلسة): content.ts
يحسب seedKey حتمياً من نطاق كل صفّ + عنوانه، ويحمّل المفاتيح الموجودة مسبقاً،
ويُسقِط المرشّحين الموجودين بالفعل — فإعادة تشغيله لم تعد تكرّر
الاختبارات/الأسئلة/المواد/الواجبات. نموذج Quiz ما زال لا يُبذَر.
مزامنة قاعدة البيانات الحيّة المؤجّلة للنشر
الرموز القانونية حيّة، لكن اتّساع المناهج العميقة مشحون في الكود وليس في قاعدة البيانات الحيّة بعد. الدليل التشغيلي كله صار أمراً واحداً:
pnpm tsx scripts/catalog-deploy-sync.ts # خطة — تقرير للقراءة فقط
pnpm tsx scripts/catalog-deploy-sync.ts --execute # تطبيق (مرهون بالنشر)يجرد السكربت صفوف مواد-فقط القديمة التي حلّت محلّها الأشجار العميقة
(gb-national-g* ~156 وib-diploma-g* ~114)، ويحذف فقط ما لا تشير إليه أي
مدرسة — لأن SubjectSelection/Enrollment تُحذَف تتابعياً مع حذف المادة،
فالصفوف المُشار إليها تُدرَج للترحيل اليدوي بدل حذفها — ثم يبذر
registry → gb → cbse → caie-igcse → ib → concepts → banners.
(كامبريدج IGCSE وCBSE بلا صفوف في قاعدة البيانات الحيّة بعد.) شغّله فقط بعد
أن يصبح نشر الكود حيّاً، مع فرع Neon احتياطاً. ومعه في البيئة نفسها:
scripts/snapshot-book-covers.ts (أغلفة OpenLibrary → S3 لدينا) و
scripts/snapshot-covers.ts (مصادر أغلفة دروس US).
لا تشغّل البذرة الكاملة قطّ
وفق قاعدة المشروع، لا تشغّل pnpm db:seed قطّ — البذرة الكاملة يدوية فقط.
استخدم دوماً pnpm db:seed:single <name>. العمليات المدمّرة لقاعدة البيانات (إعادة
تشغيل SQL الترحيل، وdb push --accept-data-loss، وmigrate reset) ممنوعة بلا
موافقة صريحة.
الأصول (Origins)
تصنيف منهج US (مواد → فصول → دروس) ورسومات المفاهيم الأصلية استُلهِما من ClickView، نظام التعلّم الأمريكي الذي أُشير إليه أولاً. تلك الأصول الآن مملوكة، ومُعاد رسمها، ومشتركة عبر كل منهج، وفهرس US هو المرجع الذي تُحسَّن منه البقية — ClickView يُنسَب إليه الفضل هنا مع الشكر؛ وهو لم يعد اعتمادية وقت تشغيل.
اطّلع أيضاً
On This Page
نظرة عامةالحالة باختصارالمعماريةنماذج الفهرس العامنماذج الجسر (تحملschoolId)مرايا المدرسة (مفتاح أجنبي للفهرس → catalogXxxId)التعدادات (Enums)تفصيل نماذج المحتوىالتهيئة (Provisioning)inferCurriculum + تراجع findSubjectsensureSubjectSelections — إصلاح ذاتي كسولطبيب التهيئة — repairProvisioningالبنية الأكاديمية لكل منهج (الثغرة المُصلَحة)الاقتراحات والموافقةالاقتراح (جانب المدرسة)طابور المُشغِّلالموافقة → الفهرس فقطمُثبَّت في مُنتقي المدرسةالرؤية والمحتوى المدفوعالموافقة تنشر الآن (الثغرة المُصلَحة)الفيديوهات المدفوعة (موصولة)الاختبارات / الأسئلة المدفوعة (مؤجّل)إدارة أعلام المُشغِّلضوابط جانب المدرسةهندسة المنهجمستودع الكتالوج — databayt/catalogtree.ts — بذرة الكتالوج الوحيدةالمناهج والرموزالتغطيةقارئ الكتاب المدرسي — الكتاب صفحاتٍ (2026-09-07)المحتوى الحقيقي — السودان (كل الصفوف)المحتوى المُولَّدجودة استخراج جدول المحتوياتخريطة الملفاتمنهج الولايات المتحدةمنهج السودانخطّ معالجة البياناتإضافة منهج وطنيالمفاهيم (Concepts)المفاهيم الـ23مصدر واحد للحقيقة — concepts-data.tsأحواض تدوير الفصولالنسخ (Variants)CDN والأصولجدول ثغرات الأصول الصادقالعملياتأوامر البذرالتكرارية (Idempotency)مزامنة قاعدة البيانات الحيّة المؤجّلة للنشرلا تشغّل البذرة الكاملة قطّالأصول (Origins)اطّلع أيضاً