مرحبا بالجميع!
هذا المقال الأخير دفعني إلى كتابة هذا المنشور (رأيته بالأمس).
إعادة بيع الميزات الرئيسية لـ Headless / content-first / api-first ، إلخ. لن أكون CMS ، والمواد ممتلئة وربما يكون الكثيرون على دراية بهذا الاتجاه. وأريد أن أخبرك لماذا وكيف أكتب نظامي ولماذا لا يمكنني الاختيار من بين الأنظمة الحالية وما أفكر به في الأنظمة الأخرى التي واجهتها من قبل وما هي الاحتمالات التي أراها في كل ذلك. سيكون الخيال هائلاً (بالنسبة للمواد في غضون عامين) ، لكنني سأحاول كتابة المزيد من الاهتمام والمفيد. من يهتم ، من فضلك ، تحت القط.
بشكل عام ، القصة طويلة جدًا وسأحاول سردها أولاً. إما أن أوضح ما هي الأسباب الحقيقية لإنشاء هذا المحرك الخاص بك ، أو ببساطة لأنه بدون ذلك سيكون من الصعب على الأرض شرح سبب قيامي بذلك بهذه الطريقة ، وليس بطريقة ما.
لكن في البداية ، سأكتب بإيجاز معايير الاختيار الرئيسية لنظام Headless-CMS الحديث بالنسبة لي شخصيًا ، لماذا لا زلت غير قادر على اختيار حل جاهز لنفسي.
فقط حتى لا ينقطع الناس عن قراءة الكثير من الزان ، ولا يفهمون ما سيُقال في النهاية.باختصار: أردت أن يكون كل شيء في مكان واحد: كلا من الخلف والأمام (وليس هذا أو ذاك) ، و GraphQL-API ، وأن تتم إدارة قاعدة البيانات والمزيد ، بما في ذلك الزر "Make Beautiful". لم أجد هذا. أنا شخصياً لم أفعل هذا بعد ، لكن على العموم ، اتضح أنه كثير جدًا ، والأهم من ذلك ، أنه يسمح لي بالقيام بمشاريع حقيقية.
وهكذا ، لا يمكن وصف نهجي علميًا ومبررًا. والحقيقة هي أنني في كثير من الأحيان في كثير من الأحيان أكتب شيئا من بلدي. أحب البرنامج هنا. وقبل عامين (وقبل ذلك ثماني سنوات أخرى) جلست على MODX CMF (والتي بموجبها اخترعت أيضًا الكثير من عكازاتي). ولمدة ثلاث سنوات بدأنا مشروعًا كبيرًا إلى حدٍ ما ، بموجبه ، بدا لي أنه يمكنني استخدام MODX. لكن كما اتضح ، لم أستطع ... السبب الرئيسي هو أنه كان شركة ناشئة دون أي متطلبات فنية ، مع مجموعة من الأفكار التي تغيرت وتُكمل كل يوم (عدة مرات في اليوم). والآن ، في كل مرة عندما يكون من الضروري في إطار فكرة جديدة إضافة بعض الكيانات الجديدة ، وتسجيل / تغيير الحقول للحقول الموجودة ، وإنشاء / حذف / تغيير العلاقات بين هذه الكيانات (على التوالي ، مع تغيير في هيكل قاعدة البيانات) ، لدي في مرحلة ما بدأ الأمر يستغرق عدة ساعات لتغيير هذه الكيانات. في الواقع ، بالإضافة إلى حقيقة أنه كان من الضروري تسجيل هذه التغييرات في المخطط ، كان من الضروري تغيير قاعدة البيانات (يدويًا تقريبًا) ، وتحديث واجهة برمجة التطبيقات ، وإعادة كتابة رمز البرنامج ، إلخ ، إلخ. تبعا لذلك ، كان الجبهة لتحديثها تحت كل هذا. كنتيجة لذلك ، قررت أن نبحث عن شيء جديد وأكثر ملاءمة ، والذي من شأنه تبسيط كل هذا بطريقة أو بأخرى. سأوضح مرة أخرى أنني كنت في ذلك الوقت بمثابة خلفية php ، لذلك لا تتفاجأ أو تضحك من أنني بدأت في اكتشاف العديد من شركات الإنشاء الأمامية ، أو المعالجات الأقل ، أو npm ، وما إلى ذلك. إلخ لكن على أي حال ، ظهرت واجهة في رد فعلنا تدريجياً في رد فعلنا + أقل ، وواجهة برمجة تطبيقات على GraphQL ، وخادم على السريع.
ولكن ليس كل شيء كان وردية كما يبدو للكثيرين الآن. واسمحوا لي أن أذكرك ، كان هذا قبل أكثر من عامين. إذا كنت في شبكة JS الحديثة لمدة تقل عن عامين ، فإنني أنصحك بقراءة هذا المقال:
N أسباب لاستخدام تطبيق إنشاء رد فعل (habr). كسول جدًا ، باختصار: مع ظهور نصوص تفاعلية ، لا يمكنك أن تهتم بتكوين حزمة الويب ، إلخ. كل هذا يذهب إلى الخلفية. قام العملاء اللطفاء بتكوين حزمة الويب بالفعل بحيث تكون معظم مشاريع رد الفعل مضمونة تقريبًا للعمل عليها ، وركز المطور النهائي مباشرةً على برمجة المنتج النهائي ، بدلاً من تكوين مجموعة من التبعيات ، اللوادر ، إلخ. ولكن هذا هو في وقت لاحق. وقبل ذلك ، كان علي فقط تهيئة حزمة الويب هذه ، ومتابعة تحديث كومة كل شيء طار معه للحاق بالركب ، إلخ. إلخ لكن هذا ليس سوى جزء من العمل ، فقط في المقدمة. وتحتاج أيضًا إلى خادم. وتحتاج أيضًا إلى API. وتحتاج أيضًا إلى SSR (التقديم من جانب الخادم) ، والذي ، بالمناسبة ، لا يزال رد الفعل النصي لا يوفر ، حسب علمي. بشكل عام ، كان كل شيء أكثر تعقيدًا من ذي قبل ، لم يكن هناك الكثير ، وكان الجميع يحطمون قدر استطاعته. وكيف عكست ثم ...
فقط تخيل:
- تكوين webpack الأصلي بشكل منفصل للأمام والخادم.
- تطبيق SSR الخاص ، بحيث تعمل المزامنة بشكل طبيعي مع خادم التفاعل ، وتصل الأنماط على الفور ، ويتم فهرستها بشكل طبيعي ، وتم إعطاء حالات الخادم للصفحات التي لم يتم العثور عليها.
- عدم مسترجع. حسنا ، أنا لم أحب الإعادة على الفور. أعجبتني فكرة استخدام تدفق التفاعل الأصلي (على الرغم من أنني اضطررت إلى إعادة كتابته قليلاً لنفسي).
- مخططات GraphQL الموصوفة يدويًا والمحللات ، دون النشر التلقائي لقاعدة البيانات (تم استخدام خادم API كوسيط لموقع MODX).
- لا يوجد رد فعل أبولو / أبولو عميل ، إلخ. تتم كتابة كل شيء بشكل مستقل مع الطلبات من خلال جلب المستودعات في مستعرض يستند إلى تدفق مخصص.
ونتيجة لذلك: حتى الآن ، يحتوي أحد الإصدارات الأولى من هذا المشروع على مشروع واحد يحضر 500+ ، وفي فصل الشتاء (1000) 1000-1700 طالب فريد يوميًا. الجهوزية 2 أشهر. هذا لأنني أعدت تشغيل الخادم يدويًا بعد تحديث برنامج وقائي. وقبل إعادة التشغيل هذه ، كانت مدة التشغيل أكثر من 6 أشهر. ولكن الأكثر إثارة للاهتمام هو استهلاك الذاكرة. هناك حاليا ما يقرب من 700 ميغابايت عملية شبيبة. نعم ، نعم ، أنا أضحك معك هنا أيضًا :) بالطبع ، هذا كثير. وقبل ذلك فعلت القليل من الوقاية وتحسين هذا المؤشر. سابقا ، كان هناك ما مجموعه 1000M + لكل عملية ... ومع ذلك ، كان يعمل وكان مقبولا للغاية. وقبل أن تقوم
Google بتغيير خوارزميات PageSpeed Insights في نوفمبر ، كان لدى الموقع مقياس أداء 97/100.
برهان .
استنتاج وسيط يستند إلى هذا المشروع استنادًا إلى نظام تم تطويره بدون هذا المشروع (تم ترك المشروع خلفه):
الأشياء الجيدة- أصبحت واجهة برمجة تطبيقات المشروع أكثر مرونة من خلال استخدام GraphQL ، كما تم تقليل عدد طلبات الخادم بدرجة كبيرة.
- المشروع لديه حق الوصول إلى عدد كبير من المكونات على npm.
- أصبحت إدارة المشروع أكثر شفافية من خلال استخدام التبعيات ، بوابة ، إلخ.
- من المؤكد أن البرامج النصية والأنماط المضمّنة أكثر إرضاءً من مجموعة من النصوص المنفصلة على المواقع القديمة ، عندما لا تعرف ما يمكنك إزالته من حديقة الحيوان هذه دون عواقب (وغالبًا ما تشاهد إصدارات عديدة من الأخطاء على موقع واحد).
- أصبح الموقع أكثر تفاعلية ، فالصفحات تعمل بدون إعادة تشغيل ، ولا تتطلب العودة إلى الصفحات التي تم عرضها سابقًا مكالمات متكررة إلى الخادم.
- يتم تحرير البيانات مباشرةً على الصفحة ، على مبدأ "تحرير ما تراه وأين ترى" ، دون أي لوحة إدارة منفصلة.
سلبيات (أساسا للمطور)- كل شيء معقد جدا. حقا. من غير الواقعي ربط بعض مطوري الطرف الثالث بالمشروع. أنا شخصيا بالكاد أستطيع معرفة ماذا وكيف تعمل وأين تنمو ساقي. إذا نظرت إلى الصفحة 3 من الإيجابيات ، حيث يقال عن الشفافية ، فإن الشفافية تكون فقط إذا قمت بتعليق شيء ما في مكان ما ، يمكنك أن ترى على الفور ما تم كسره (البرامج النصية لا تبني ، وما إلى ذلك) ، ولكن من خلال الإلتزامات والفوارق يمكنك أن تجد فيها هذا مدمن مخدرات. حسنًا ، إذا تمكنت من إضافة شيء جديد وهو يعمل على الأقل ، فأنت تفهم بوضوح أنه ، كل شيء على ما يرام. لكن بشكل عام لا يزال الجحيم جهنم.
- صعوبات مع التخزين المؤقت. في وقت لاحق ، اكتشفت عميل أبولو لنفسي. وقبل ذلك ، كما قلت ، كتبت مستودعاتي القائمة على التدفق. نظرًا لهذه المخازن ، كان من الممكن الحصول على البيانات اللازمة للعرض من مكونات مختلفة ، لكن حجم ذاكرة التخزين المؤقت على جانب العميل كان كبيرًا جدًا (كل مجموعة من الكيانات النموذجية لها مستودع خاص بها). كنتيجة لذلك ، كان من الصعب التحقق مما إذا كان الكائن قد تم طلبه مسبقًا أم لا (أي ، هل يستحق الأمر تقديم طلب إلى الخادم للعثور عليه) ، وما إذا كانت جميع البيانات ذات الصلة متاحة ، وما إلى ذلك.
- صعوبات في المخططات وهيكل قاعدة البيانات والمحللات (وظائف API لاستقبال / تعديل البيانات). كما قلت ، كتبت المخططات يدويًا وحلها أيضًا. في ما حللت به في الحلول ، حاولت توفير التخزين المؤقت ، ومعالجة الطلبات المتداخلة وغيرها من التفاصيل الدقيقة. في تلك اللحظة ، كان عليّ أن أذهب إلى عمق رمز برنامج الجرافل والجوهر. الاتجاه الصعودي هو أنني أفهم بشكل عام جيدًا كيفية عمل GraphQL ، وما إيجابياته وسلبياته ، وكيفية طبخه بشكل أفضل. الجانب السلبي هو أنه ، بطبيعة الحال ، لا يمكنك كتابة كل هذه المرافق والكعك المكتوبة بواسطة أوامر مثل أبولو في واحد. نتيجة لذلك ، عندما اكتشفت أبولو ، بالطبع ، بدأت في استخدام مكوناتها بسرور كبير (ولكن بشكل أساسي في المقدمة ، سأخبرك لماذا أدناه).
بشكل عام ، فإن هذا المشروع الذي يستخدم التقنيات القديمة يعد مشروعًا شخصيًا لي بنسبة 100٪ ، لذلك يمكنني تحمله حتى يحين أوقات أفضل. ولكن هناك مشاريع أخرى اضطررت للذهاب إليها وتطوير المنصة. عدة مرات اضطررت إلى إعادة كتابة كل شيء من الصفر. علاوة على ذلك ، سأتحدث بمزيد من التفصيل عن المهام الفردية التي واجهتها وما هي الحلول التي قمت بتطويرها وتطبيقها كنتيجة لذلك.
، مخطط الأول. أولا الدائرة ، ثم كل شيء آخرالموقع (واجهة الويب ، العميل الرفيع ، وما إلى ذلك) هو كل ما يعرض المعلومات (جيدًا ، إدارة المعلومات ، إذا كان مسموحًا به والسماح بالوظائف). لكن أولاً ، كل ذلك ، قاعدة بيانات (الجداول ، الأعمدة ، إلخ). بعد أن واجهت العديد من الطرق المختلفة للعمل مع قاعدة البيانات في طريقي ، أعجبتني الطريقة الأولى للمخطط. أي أنك تصف مخطط الكيانات وأنواع البيانات (يدويًا أو عبر الواجهة) ، وتنشر المخطط ، وتطبق على الفور التغييرات الموضحة على قاعدة البيانات (يتم إنشاء / حذف الجداول / الأعمدة ، وكذلك العلاقات بينهما). بناءً على التطبيق ، ستقوم أيضًا بإنشاء جميع وظائف محلل التشغيل الضرورية لإدارة هذه البيانات. الأهم من ذلك كله في هذا الاتجاه أعجبني مشروع
prisma.io .
بعد موافقتك ، بما أنني لم أر مقالة واحدة حول المنشور ، فسألفت الانتباه إليهم قليلاً ، لأن المشروع مثير جدًا للاهتمام حقًا ، وبدونهم ، لن يكون لدي الآن مثل هذا المنبر الذي جعلني سعيدًا للغاية . في الواقع ، لهذا السبب اتصلت بالمنصة prisma-cms ، لأن prisma.io يلعب دورًا كبيرًا للغاية في ذلك.
في الواقع ، prisma.io هو مشروع SaaS ، ولكن مع تحذير كبير: يضعون كل ما يفعلونه تقريبًا على جيثب. أي أنه يمكنك استخدام الخوادم الخاصة بهم مقابل رسوم معقولة جدًا (وتكوين قاعدة البيانات الخاصة بك وواجهة برمجة التطبيقات الخاصة بك في غضون دقائق) ، أو يمكنك نشر كل شيء بالكامل في المنزل. في هذه الحالة ، يجب تقسيم المنشور منطقيًا إلى قسمين منفصلين مهمين:
- Prisma-server ، أي ، الخادم حيث تدور قاعدة البيانات أيضًا.
- بريزما العميل. إنه أيضًا خادم بشكل أساسي ، لكن بالنسبة إلى مصدر البيانات (خادم المنشور) فهو عميل.
الآن سأحاول شرح هذا الموقف المحير. بشكل عام ، فإن جوهر المنشور هو أنه باستخدام نقطة نهاية API واحدة ، يمكنك العمل مع مصادر بيانات مختلفة. نعم ، هنا سيقول أي شخص أنهم جميعا توصلوا إلى GraphQL وليس هناك حاجة إلى المنشور هنا. بشكل عام ، سيكون الجميع على صواب ، ولكن هناك نقطة خطيرة: تقوم GraphQL بتحديد المبادئ والعمل الشامل فقط ، ولكنها في حد ذاتها لا توفر العمل مع مصادر البيانات النهائية من خارج الصندوق. يقول: "يمكنك إنشاء واجهة برمجة تطبيقات لوصف الطلبات التي يمكن للمستخدمين إرسالها ، ولكن كيفية التعامل مع هذه الطلبات متروك لكم". والمنشور أيضًا ، بالطبع ، يستخدم GraphQL (بالمناسبة ، والكثير من الأشياء الأخرى ، بما في ذلك منتجات أبولو المختلفة). لكن المنشور زائد لهذا فقط يوفر العمل مع قاعدة البيانات. أي لوصف المخطط ونشره ، سيتم إنشاء الجداول والأعمدة الضرورية (وكذلك العلاقات بينهما) على الفور في قاعدة البيانات المحددة ، وحتى إنشاء جميع وظائف CRUD اللازمة على الفور. وهذا يعني ، مع المنشور ، أنك لا تحصل على خادم GraphQL فحسب ، ولكن أيضًا واجهة برمجة تطبيقات كاملة تعمل تسمح لك على الفور بالعمل مع قاعدة البيانات. لذلك ، يوفر Prisma-server قاعدة بيانات وتفاعلًا معها ، ويسمح لك prisma-client بكتابة محللاتك وإرسال الطلبات إلى خادم prisma (أو في مكان آخر ، حتى بالنسبة لبعض خوادم prisma). وهكذا اتضح أنه لا يمكنك فقط نشر prisma-client وحدك (وسيتم استخدام SaaS prisma.io كخادم prisma) ، ويمكنك نشر خادم prisma لوحدك ، وعمومًا لا تعتمد على المنشور بأي طريقة ، الخاص بك.
لقد اخترت هنا منشورًا لنفسي ، كأساس لمنصتي. ولكن بعد ذلك اضطررت إلى تدويرها بنفسي من أجل الحصول على منصة كاملة.
1. دمج المخططات
في ذلك الوقت ، لم يكن المنشور قادرًا على الجمع بين الدوائر. وهذا هو ، المهمة هي كما يلي:
لديك نموذج مستخدم موضح في وحدة واحدة
type User { id: ID! @unique username: String! @unique email: String @unique }
وفي وحدة أخرى
type User { id: ID! @unique username: String! @unique firstname: String lastname: String }
كجزء من مشروع واحد ، تريد الجمع بين هذين المخططين تلقائيًا للحصول على الإخراج
type User { id: ID! @unique username: String! @unique email: String @unique firstname: String lastname: String }
ولكن بعد هذا المنشور لا يمكن القيام به. اتضح لتنفيذ هذا باستخدام
مكتبة دمج الرسومات - graphql .
العمل مع المنشور التعسفي الخادم.
في المنشور ، تتم كتابة التكوين في ملف تهيئة خاص. إذا كنت ترغب في تغيير عنوان خادم المنشور المستخدم ، يجب عليك تحرير الملف. تافه ، ليس لطيفا. كنت أرغب في جعل عنوان URL ممكنًا لتحديده في الأمر ، على سبيل المثال نقطة النهاية = http: // end end-الغزل عنوان النشر (بدء الغزل). تم قتل ذلك لعدة أيام ... ولكن الآن يمكنك استخدام مشروع منشور واحد لأي عدد من نقاط النهاية. بالمناسبة ، تعمل prisma-cms حتى الآن بسهولة حتى مع قاعدة بيانات محلية ، حتى مع خوادم المنشور SaaS.
وحدات / الإضافات
هذا كان عموما لا يكفي. كما قلت ، فإن المهمة الرئيسية للمنشور هي توفير العمل مع مختلف قواعد البيانات. ويقومون بعمل ممتاز من هذا. بالفعل ، يدعمون العمل مع MySQL و PostgreSQL و Amazon RDS و MongoDB ، والعديد من أنواع المصادر الأخرى على الطريق. لكنها لا توفر أي بنية تحتية وحدات. لا يوجد سوق حتى الآن أو شيء من هذا القبيل. لا يوجد سوى عدد قليل من الفراغات النموذجية. ولكن لا يمكنك اختيار اثنين أو ثلاثة من عدة فراغات وتثبيت على مشروع واحد. سيكون لدينا لاختيار واحد. أردت أن يكون من الممكن تثبيت عدد مختلف من الوحدات النمطية على المشروع النهائي ، وأنه عند نشر الدوائر والمحللات ستختفي وتحصل على مثل هذا المشروع الفردي بالوظائف الكاملة. وعلى الرغم من عدم وجود واجهة رسومية حتى الآن ، إلا أن هناك بالفعل أكثر من 24 وحدة عمل ومكونات يمكن دمجها في المشروع النهائي. هنا ، سأقرر على الفور القليل حول التعريفات الشخصية: الوحدة النمطية هي ما تم تثبيته على الظهر (توسيع قاعدة البيانات وواجهة برمجة التطبيقات) ، والمكون هو ما تم تثبيته في المقدمة (لإضافة عناصر واجهة متعددة). حتى الآن ، لا توجد واجهة رسومية لربط الوحدات النمطية ، لكن ليس من الصعب علي أن أكتب بهذه الطريقة (لا يتم ذلك في كثير من الأحيان):
constructor(options = {}) { super(options); this.mergeModules([ LogModule, MailModule, UploadModule, SocietyModule, EthereumModule, WebrtcModule, UserModule, RouterModule, ]); }
بعد إضافة وحدات نمطية جديدة ، يكفي مجرد إجراء عملية نشر باستخدام أمر واحد مرة أخرى ، وهذا هو ، لدينا بالفعل جداول / أعمدة جديدة ووظائف إضافية.
5 الجبهة ، استجابة للتغيرات في الخلفية
هذا لم يكن كافيا على الإطلاق. وسيتبع ذلك استطراد. والحقيقة هي أن جميع CMS التي رأيتها في واجهة برمجة التطبيقات (API) التي رأيتها تقول "نحن رائعون في تقديم واجهة برمجة التطبيقات (API) ، وتثبّت الواجهة التي تريدها." هذا هو ما يعنيه "ما يشبهك" في الواقع "يزعجك كما تريد". تمامًا كما تقول أطر عمل واجهة المستخدم ، "انظر إلى الأزرار الرائعة التي نحن عليها ونفعل كل ذلك ، وتختلط مع الواجهة الخلفية لنفسك". التي قتلت دائما. أردت فقط العثور على CMS شامل مكتوب في javascript ، وذلك باستخدام GraphQL وتوفير كل من الأمام والخلف. لكنني لم أجد واحدة من هذا القبيل. أردت حقًا أن يتم إدراك تغييرات واجهة برمجة التطبيقات على الفور في المقدمة. ولهذا ، تم الانتهاء من العديد من النقاط الفرعية:
5.1 توليد شظايا API
في المقدمة ، يتم تسجيل الأجزاء من ملف المخطط في الطلبات. عند إعادة إنشاء واجهة برمجة التطبيقات (API) على الخادم ، يتم أيضًا إنشاء ملف JS جديد به أجزاء API. وفي الطلبات مكتوبة مثل هذا:
const { UserNoNestingFragment, EthAccountNoNestingFragment, NotificationTypeNoNestingFragment, BatchPayloadNoNestingFragment, } = queryFragments; const userFragment = ` fragment user on User { ...UserNoNesting EthAccounts{ ...EthAccountNoNesting } NotificationTypes{ ...NotificationTypeNoNesting } } ${UserNoNestingFragment} ${EthAccountNoNestingFragment} ${NotificationTypeNoNestingFragment} `; const usersConnection = ` query usersConnection ( $where: UserWhereInput $orderBy: UserOrderByInput $skip: Int $after: String $before: String $first: Int $last: Int ){ objectsConnection: usersConnection ( where: $where orderBy: $orderBy skip: $skip after: $after before: $before first: $first last: $last ){ aggregate{ count } edges{ node{ ...user } } } } ${userFragment} `;
5.2 سياق واحد لجميع المكونات
رد فعل 16.3 يقدم
API سياق جديد . لقد قمت بذلك حتى تتمكن من الوصول إلى سياق واحد في المكونات الفرعية على أي مستوى دون سرد الأنواع المرغوبة مسبقًا من السياق ، ولكن ببساطة تحديد سياق ثابتType = PrismaCmsContext والحصول على كل السحر من خلال هذا السياق> (بما في ذلك عميل API ، المخطط ، طلبات ، الخ).
5.3 المرشحات الديناميكية
أنا أيضا أردت حقا أن. يتيح لك GraphQL إنشاء استعلامات معقدة باستخدام بنية متداخلة. أردت أن تكون الفلاتر ديناميكية أيضًا ، تم تشكيلها من مخطط API ، وتسمح لنا بتهيئة ظروف متداخلة. إليك ما حدث:
5.4 بناء الموقع
وأخيراً ، ما افتقدته هو محرر موقع خارجي ، أي مصمم. أردت أن يكون لدى الخادم الحد الأدنى من الإجراءات فقط ، ويجب أن يتم التصميم النهائي في المقدمة (بما في ذلك إعداد التوجيه ، وإنشاء التحديدات ، وما إلى ذلك). هذا موضوع لمقال منفصل ، لأنه من بين أشياء أخرى ، كتبت أيضًا محرر wysiwyg المتعطش له على محتوى نقي قابل للتعديل ، وهناك الكثير من التفاصيل الدقيقة. إذا تم استعادتي لحقوقي ومن سيكون مهتماً ، سأكتب مقالة منفصلة.
حسنًا ، أخيرًا ، فيديو تجريبي قصير للمصمم أثناء العمل. لا يزال الخام جدا ، ولكن أنا أحب ذلك.
سأنتهي من ذلك. لم أكتب الكثير حتى الآن ، ما أود أن أكتب ، ولكن الكثير قد حدث. سأكون سعيدا للتعليق.
ملاحظة: جميع أكواد المصدر ، بما في ذلك أكواد مصدر الموقع نفسه ،
موجودة هنا .