مرحبًا بالجميع ![]()
لقد كنت أبني واجهة أمامية مخصصة باستخدام Discourse كخلفية منفصلة (بنية قائمة على Next.js)، وأود مشاركة بعض الفجوات العملية التي واجهتها في تصميم الـ API الحالي من منظور التكامل في العالم الحقيقي.
هذا ليس نقدًا لـ Discourse نفسه (فهو قوي ومرن)، بل هو تغذية راجعة لتحسين تجربة المطور (DX) في البنيات الحديثة التي تعتمد على الواجهات الأمامية والـ API-driven.
1. الترقيم الهيكلي للمواضيع والمشاركات
المشكلة الحالية:
-
الترقيم (Pagination) ليس متسقًا دائمًا عبر نقاط النهاية (endpoints).
-
مشاركة المواضيع (
/t/{id}.json) تخلط بين:-
المنشور الأصلي
-
الردود
-
البيانات الوصفية الداخلية
-
وهذا يجعل بناء التمرير اللانهائي النظيف أو الحالة الموحدة (مثل Redux/Zustand/React Query) أكثر صعوبة.
الاقتراح:
-
توفير فصل أوضح أو أعلام استعلام اختيارية مثل:
-
?include_first_post=true|false -
?posts_only=replies -
دعم الترقيم القائم على المؤشر (Cursor-based pagination) بدلاً من الاعتماد على الترقيم القائم على الصفحات فقط.
-
2. الردود مقابل هيكل الموضوع
حاليًا:
-
الردود مدمجة داخل استجابة الموضوع.
-
لا يوجد فصل واضح بين:
-
“بيانات الموضوع الوصفية”
-
“تدفق المنشورات”
-
وهذا يتسبب في:
-
منطق تحليل إضافي في الواجهة الأمامية.
-
تكرار عند توحيد الحالة (normalizing state).
الاقتراح:
-
تقديم نقاط نهاية مخصصة مثل:
-
/t/{id}/posts -
/t/{id}/replies -
أو دعم التصفية داخل
/t/{id}.json.
-
3. نقص توثيق الحقول على مستوى الاستجابة
على سبيل المثال في استجابة الموضوع:
-
created_at -
bumped_at -
last_posted_at -
updated_at
هذه الحقول لا يتم دائمًا التمييز بينها بوضوح.
المشكلة:
-
غالبًا ما يساء تفسير المطورون لـ:
-
الفرق بين
bumped_atوupdated_at -
ما الذي يُعدّ “نشاطًا للموضوع”
-
الاقتراح:
-
إضافة توثيق مضمن للمخطط (schema) أو بيانات وصفية بأسلوب OpenAPI:
-
معنى كل حقل
-
شرح دورة الحياة
-
4. عدم اتساق الإحصائيات والتخزين المؤقت
المشاكل:
-
أرقام
posts_count،reply_count،participants_countتتأخر أحيانًا عن البيانات في الوقت الفعلي. -
الاعتماد الكبير على عدادات التخزين المؤقت.
الأثر:
-
واجهة مستخدم غير دقيقة (خاصة في لوحات التحكم / صفحات التحليلات).
-
يتطلب مكالمات API إضافية للتحقق من الحالة.
الاقتراح:
-
إضافة مؤشر “الوقت الفعلي مقابل التخزين المؤقت” أو نسخة بديلة من نقطة النهاية.
-
أو توفير تحديثات قائمة على الويب هوك (webhook) أو الأحداث للأرقام.
5. فجوات في خريطة الموقع + تحسين محركات البحث (SEO) + تكامل الأطر
عند التكامل مع أطر العمل الحديثة (مثل Next.js، Nuxt، إلخ):
المشاكل:
-
لا توجد واجهة API موحدة لـ:
-
المواضيع المحدثة لتوليد خريطة الموقع
-
تتبع آخر تغيير على مستوى الفئة
-
دعم فهرسة المنشورات بالكامل
-
ينتهي المطورون بالقيام بـ:
-
مكالمات API متعددة لكل فئة.
-
مقارنة يدوية لـ
updated_at. -
التصفح عبر الترقيم للكشف عن التحديثات.
الاقتراح:
-
إضافة نقاط نهاية مخصصة:
-
/categories/updated -
/topics/changes?since=timestamp -
/sitemap.json(تغذية خريطة موقع مدفوعة بالـ API).
-
6. غياب مقاييس المستخدم والتجميعات
البيانات المطلوبة عادةً:
-
إجمالي الإعجابات المستلمة لكل مستخدم.
-
إجمالي الإعجابات الممنوحة.
-
تفصيل ردود الفعل لكل منشور/مستخدم.
-
إحصائيات التفاعل لكل فئة.
المشكلة الحالية:
- تتطلب نقاط نهاية متعددة + تجميع في الواجهة الأمامية.
الاقتراح:
-
إضافة نقاط نهاية مجمعة مثل:
-
/users/{id}/stats -
/topics/{id}/stats
-
7. مرونة صور المستخدمين (Avatars)
القيد الحالي:
- صور المستخدمين مرتبطة ارتباطًا وثيقًا بنظام رفع Discourse.
الطلب:
-
السماح بروابط صور خارجية (S3 / CDN / موفري المصادقة الخارجيين).
-
دعم:
external_avatar_url
وهذا سيساعد في:
-
أنظمة الدخول الموحد (SSO).
-
موفري الهوية في البنيات المنفصلة (headless).
8. مفاتيح الـ API: مفاتيح المسؤول مقابل مفاتيح المستخدم
توضيح مطلوب في الوثائق:
الفرق بين:
-
مفتاح API الخاص بالمسؤول.
-
مفتاح API الخاص بالمستخدم (المُنشأ عبر
/admin/api/keysأو نقاط نهاية المستخدم).
الأسئلة:
-
قواعد دورة الحياة والانتهاء.
-
قواعد الإلغاء لكل مستخدم مقابل العالمية.
-
قيود نطاق الأمان حسب النوع.
هذا أمر حاسم عند بناء تكاملات جاهزة للإنتاج.
أفكار ختامية
إن واجهة Discourse API قوية بالفعل، لكنها تبدو مُحسَّنة لاستخدام “المنتديات المعروضة بواسطة الخادم” أكثر من “البنية المنفصلة / المدفوعة بالواجهة الأمامية”.
الأطر الحديثة (مثل Next.js، Remix، إلخ) تستفيد كثيرًا من:
-
عدد أقل من الرحلات ذهابًا وإيابًا.
-
حدود بيانات أوضح.
-
قواعد تخزين مؤقت قابلة للتنبؤ.
-
نقاط نهاية تجميع أفضل.
أرحب بالتعليقات من المطورين الأساسيين أو أي شخص آخر يبني إعدادات Discourse منفصلة.
شكرًا ![]()