بناء مدونة مخصصة من الصفر في عام 2026 هو خيار متعمد. معظم الكتاب يختارون ببساطة منصة مستضافة ويمضون في طريقهم. قررت إعادة بناء مدونتي التقنية باستخدام Astro لأنني أردت امتلاك كل طبقة من طبقات التقنيات المستخدمة (stack) وتعلم الأنماط التي تجعل الموقع الساكن أسرع بالفعل، وليس مجرد مختلف. النتيجة هي موقع ثنائي اللغة يقدم محتوى باليابانية والإنجليزية، ولا يرسل أي JavaScript افتراضيًا، ويحتفظ بكل ذرة من التعقيد على جهازي بدلاً من متصفح الزائر.

إليك الأنماط الخمسة التي جعلت الأمر ينجح.

مجموعات المحتوى (Content Collections) باستخدام Zod

تقوم مجموعات المحتوى (Content Collections) في Astro بأكثر من مجرد تنظيم ملفات Markdown في مجلدات؛ فهي تفرض عقداً بين محتواك وكودك البرمجي. لقد قمت بربط مخطط Zod schema بكل مجموعة مقالات، مما يعني أن خطوة البناء (build step) تتحقق من الـ frontmatter قبل رندرة أي صفحة.

يتطلب المخطط حقل language يقبل قيمتين فقط: ja أو en. لا يوجد غموض بشأن اللغة التي سيحصل عليها القارئ. أضفت أيضاً حقل pair يربط الترجمات معاً. إذا نشرت مقالاً عن Astro باليابانية ثم ترجمته لاحقاً إلى الإنجليزية، فسيشارك كلا الملفين نفس معرف الزوج (pair ID). هذا يجعل بناء محول اللغة أمراً بسيطاً للغاية لأن العلاقة صريحة في البيانات، وليست مستنتجة من أسماء الملفات.

تصل التواريخ من الـ Markdown frontmatter كسلاسل نصية (strings)، لذا يقوم المخطط بتحويلها تلقائياً إلى كائنات Date حقيقية. هذا يلغي منطق معالجة النصوص داخل قوالب الصفحات الخاصة بي. ومع ذلك، فإن الفائدة الأهم هي نمط الفشل (failure mode)؛ فإذا كان الملف يفتقر إلى حقل مطلوب أو يستخدم رمز لغة غير صالح، سيتوقف البناء فوراً مع خطأ واضح. أقوم بإصلاحه في واجهة الأوامر (terminal) بدلاً من اكتشاف تخطيط معطل أو خطأ 404 صامت بعد النشر.

مسار تحويل المقالات (Article Conversion Pipeline)

لم أكتب كل منشور بهذا التنسيق الجديد منذ اليوم الأول. فقد عاشت سنوات من المحتوى على Zenn و Dev.to، ولكل منصة خصائصها الفريدة وصيغتها الخاصة. وبدلاً من النسخ واللصق والإصلاح يدوياً، كتبت سكربت TypeScript يقوم بتحويل دفعات كاملة من المقالات إلى Markdown قياسي.

يستخدم Zenn صيغة callout مخصصة للنصائح والتحذيرات. يقوم السكربت الخاص بي بتحويلها إلى وسوم HTML semantic من نوع aside لكي تظهر بشكل متسق عبر الموقع. أما Dev.to فيعتمد على وسوم Liquid للتضمينات والكتل الخاصة. يقوم المسار بترجمة هذه الوسوم إلى روابط Markdown بسيطة تعمل في أي مكان.

تحتوي بعض المنشورات على ملاحظات جانبية مخصصة للمنصة الأصلية فقط، مثل إخلاء مسؤولية حول جدران الدفع (paywalls) في Medium أو مسار صورة خاص بـ Zenn. أقوم بتغليف هذه الملاحظات في تعليقات HTML حتى يتمكن المحول من إزالتها أثناء عملية النقل. يعالج السكربت الملفات سطراً بسطر، لكنه يحترم حدود الكود. عندما يكتشف كتلة كود محاطة بأسوار (fenced code block)، فإنه يتخطى قواعد التحويل تماماً. إن إفساد عينة من الكود من شأنه أن يقوض الغرض الكامل من مدونة تقنية، لذا يعامل محلل السطر بسطر كتل الكود كمناطق لا يمكن المساس بها.

تشغيل أمر واحد الآن يعيد نشر سنوات من الكتابة دون كسر رابط واحد أو ملاحظة جانبية.

إنشاء صور OGP أثناء وقت البناء (Build-Time)

عادة ما تكون صور المشاركة الاجتماعية فكرة ثانوية. فإما أن تقوم بتصميمها يدوياً أو تثبت خدمة تشغيل ثقيلة تقوم بإنشاء البطاقات عند الطلب. لم أرغب في أي منهما. يتم إنتاج كل صورة Open Graph في هذا الموقع أثناء عملية البناء بحيث لا يتلقى الزوار أكثر من وسم img خفيف يشير إلى ملف PNG ثابت.

أستخدم Satori، الذي يأخذ وسم JSX ويقوم برندرتها إلى SVG. المخرجات دقيقة، ويمكن التنبؤ بها، وسهلة القوالب. جاء التحسين الحقيقي من التعامل مع الخطوط. يمكن لخط ويب ياباني كامل أن يتجاوز بسهولة خمسة ميجابايت. تحميل ذلك أثناء البناء، ناهيك عن مطالبة المتصفح بجلبها، سيكون أمراً غير منطقي.

بدلاً من ذلك، أستخدم تقنية Google Fonts subsetting. يفحص السكربت نص العنوان لمنشور معين ويطلب فقط مجموعة الرموز (glyphs) الدقيقة المطلوبة لرندرة ذلك النص. إذا كان العنوان يستخدم أربعين حرفاً يابانياً فريداً، فسيتم نقل تلك الحروف الأربعين فقط عبر الشبكة. يظل البناء سريعاً، ولا تظهر الصورة المنشودة أبداً مربعات "tofu" (رموز مكسورة) لأن المجموعة الفرعية دقيقة. لا نترك شيئاً للصدفة أثناء وقت التشغيل.

الوضع الداكن عبر رموز Tailwind (Tailwind Tokens)

رفضت تزيين كل عنصر بفئات dark: المساعدة (utility classes). هذا النهج لا يتوسع بشكل جيد ويملأ الكود الخاص بك بالضجيج. لقد أعدت تعريف رموز الألوان نفسها بحيث يشير نفس اسم الفئة إلى قيم مختلفة اعتماداً على السمة (theme) النشطة.

أستخدم خصائص CSS المخصصة (CSS custom properties) لكل لون سطح ونص. في الوضع الفاتح، تشير --color-white إلى #ffffff. وفي الوضع الداكن، يشير نفس اسم المتغير إلى قيمة قريبة من الأسود. يظل ملف HTML الخاص بي مستقلاً تماماً عن الوضع (agnostic)؛ حيث يمكن للبطاقة استخدام bg-ui-surface و text-ui-primary دون الاهتمام بالوقت من اليوم. يقوم تبديل المظهر (theme switch) بتغيير تعريفات المتغيرات عند الجذر (root)، وتستجيب الواجهة بأكملها فوراً.

الخطر الوحيد في هذا النهج هو وميض المحتوى الفاتح قبل تحميل ملفات التنسيق (stylesheets). لقد حللت هذه المشكلة باستخدام نص برمجي صغير مضمن (inline script) في رأس المستند head. يعمل هذا النص قبل أول عملية رسم (first paint)، حيث يتحقق من localStorage وتفضيلات النظام، ويضبط سمة البيانات (data attribute) الصحيحة على الفور. ولأن النص البرمجي يعطل عملية الرندرة (render) لبضع أجزاء من الثانية فقط، فإن الزائر لا يرى أبداً وميضاً أبيض مزعجاً قبل تفعيل الوضع الداكن.

بنية الجزر (Island Architecture) وصفر JavaScript

المبدأ الأساسي لـ Astro هو أن الصفحة يجب أن تبدأ كـ HTML ثابت. ولا يدخل JavaScript إلا عندما تتطلب التفاعلات ذلك حقاً. وقد أخذت هذا الأمر على محمل الجد.

تجنبت استخدام React للقائمة العامة ومبدل المظهر؛ حيث يتم التعامل مع كليهما باستخدام كمية صغيرة من vanilla JavaScript التي تعيش في وحدة (module) واحدة. لا يوجد عبء إضافي لعملية الـ hydration، ولا مقارنة للـ virtual DOM (diffing)، ولا وقت تشغيل للإطار (framework runtime) يجب تحميله.

المكتبة الثقيلة الوحيدة التي أستخدمها هي Mermaid.js لرسم المخططات من النصوص. وبدلاً من استيرادها بشكل عام، قمت بتغليفها داخل Intersection Observer. يراقب الـ observer حاويات المخططات، وعندما يقوم المستخدم بالتمرير لمسافة بضع مئات من البكسلات من أحدها، يقوم النص البرمجي بحقن وحدة Mermaid ديناميكياً ورسم المخطط. إذا كان المنشور لا يحتوي على مخططات، فإن هذه المكتبة لا تستهلك أي بيانات من الشبكة أبداً. يظل تحميل الصفحة الأولي خفيفاً، ولا يدفع المتصفح ثمن سوى ما يراه القارئ بالفعل.

عقلية "البناء أولاً" (Build-First Mindset)

الخيط الرابط بين كل الأنماط بسيط: إذا كان بإمكانك القيام بالعمل أثناء عملية البناء (build)، فافعل ذلك هناك. تحقق من صحة بياناتك باستخدام Zod قبل نشر الموقع. قم بتحويل صيغة المنصة الخاصة مسبقاً بدلاً من القيام بذلك وقت الطلب. قم برسم صور التواصل الاجتماعي في ملفات ثابتة بدلاً من تشغيل خادم. قم بحل ألوان المظهر عبر الرموز (tokens) بدلاً من إرسال المنطق البرمجي إلى كل عميل. وأجل تحميل JavaScript الثقيل حتى يحتاجه المستخدم بالفعل.

إن دفع التعقيد نحو اليسار (pushing complexity leftward) إلى خطوة البناء يحافظ على قابلية التنبؤ بوقت التشغيل، ويجعل حجم البيانات المرسلة (payload) صغيراً، وعبء الصيانة قابلاً للإدارة. يظل الموقع سريعاً ليس بسبب خدعة واحدة، بل ببساطة لأن هناك عمليات أقل تحدث داخل متصفح الزائر. هذا هو العائد الحقيقي لاختيار بنية ثابتة (static architecture) في عام 2026.