abualruz-homelab: الموقع والبنية التحتية التي تشغّله
موقع شخصي مبني على Astro 6 وSvelte 5، يعمل من homelab منزلي عبر Caddy وDocker، شُيِّد مرحلةً بمرحلة بكتيب عمل منشور لوكلاء الذكاء الاصطناعي.
هذا هو المشروع الميتا: الموقع الذي تقرأ عليه هذا الكلام، والبنية التحتية في الـhomelab التي تعكسه، وكتيب عمل الوكلاء الذي بنى الاثنين. وهو أيضاً - بالمعنى الحرفي - تجربة مستمرة في سؤال واحد: هل يمكنك إطلاق موقع شخصي بجودة إنتاجية باستخدام وكلاء ترميز الذكاء الاصطناعي كقوة عمل أساسية دون أن تنتهي بقاعدة كود تخجل منها؟
الإجابة حتى الآن: نعم - بس جنبها كام نجمة استثناء تقول: استنى بس.
لماذا يوجد هذا المشروع
سببان. الأول ممل: كنت أحتاج موقعاً شخصياً. كنت “أنوي” أن يكون لي واحد منذ سنوات، و”النية” هي المقبرة التي تذهب إليها المشاريع الجانبية ثم تطلع لك في الكوابيس. الثاني أكثر إثارة: أردت مشروعاً حقيقياً - لا لعبة، لا درساً تعليمياً، لا “hello world مع زر deploy” - لاختبار سير عمل التطوير بمساعدة الوكلاء الذي كنت أبنيه مع Fulcrum.
الموقع الشخصي مثالي لهذا. المتطلبات حقيقية. قرارات التصميم تهم. هناك محتوى فعلي يُكتب، وميزانيات أداء فعلية تُلتزم بها، وheaders CSP فعلية تُخطئ فيها بطرق محرجة ثم تُصلحها. لكن نطاق تأثير الأخطاء ملكي وحدي، مما يعني أنني أستطيع التحرك أسرع والفشل بشكل أكثر وضوحاً مما أستطيع في أي مشروع عميل.
كل مرحلة تُسلَّم مع سجل تقدم ووثيقة دروس. هذا ليس مسرحاً للتوثيق - تلك الوثائق هي مدخلات لتشغيل الوكيل التالي. يقرأ Chief-of-Staff وثيقة الدروس قبل توزيع العمل على المرحلة N+1. انضباط كتابتها هو انضباط جعل المرحلة التالية أسرع.
كيف يعمل
الموقع هو Astro 6 مع Svelte 5 للجزر التفاعلية. Astro يفعل ما يفترض فعله: JavaScript شبه معدوم للصفحات الثابتة، hydration انتقائي للأجزاء التي تحتاجه. نموذج runes في Svelte 5 جيد فعلاً - المكتبات التفاعلية الأولية أنظف من React hooks للنوع الصغير والمركّز من التفاعلية التي يحتاجها موقع شخصي.
المحتوى هو ملفات MDX في مخطط مجموعة منظّم مُتحقَّق منه بـZod وقت البناء. الموضوعات enum (مُعرَّفة مرة واحدة في src/data/topics.ts، مستخدمة من قِبَل المخطط وصفحات الـhub)، بحيث أن خطأً إملائياً في حقل frontmatter يفشل البناء بصوت عالٍ بدلاً من إنتاج 404 صامت. أصبحت أحب التحقق من المخطط وقت البناء في مواقع المحتوى. حلقة التغذية الراجعة سريعة والأخطاء محددة.
الـhomelab mirror يعمل على جهاز واحد في شبكتي المنزلية خلف reverse proxy من Caddy. Docker Compose يدير الخدمات؛ Caddy يتولى إنهاء TLS وتقديم الملفات الثابتة للموقع. سياسة أمان المحتوى (CSP) في ملف _headers مُقدَّم مع الأصول الثابتة - Caddy يمررها دون تغيير، وهو التقسيم الصحيح للمسؤوليات.
النشر هو workflow على GitHub Actions يبني موقع Astro، يدفع الناتج إلى السيرفر، ويعيد تشغيل خدمة Docker. مش فخم. ومش محتاج يبقى فخم. خط النشر الذي يجعلك تشعر بالذكاء هو عادةً الذي ينكسر الساعة 11 مساءً وأنت تحاول نشر إصلاح.
ما الذي يثير الاهتمام
نموذج التسليم المرحلي لم يكن جزءاً من الخطة الأصلية. ظهر من أول تشغيل للوكيل، الذي أنتج مرحلة 0 كانت أكثر تماسكاً مما كنت سأصمّمه مسبقاً - موقع قابل للحياة بحد أدنى مع مخطط محتوى وبناء يعمل وخط نشر - ووثيقة متابعة تضمنت قائمة بالأشياء التي يجب أن تحدث تالياً. تلك البنية كانت حاملة للحمل.
الخاصية المثيرة في “كل مرحلة لها وثيقة دروس” هي أنها تجبرك على صياغة ما تعلمته قبل أن تنسى السياق كلياً. يبدو هذا واضحاً، لكن في الواقع معظم مراجعات المشاريع تحدث بعد ثلاثة أسابيع من انتهاء العمل، حين تتلاشى التفاصيل وتنتج عموميات. كتابة وثيقة الدروس في نفس يوم تسليم المرحلة ينتج ملاحظات أكثر تحديداً بكثير. “يحتاج stopgap unsafe-inline في CSP إلى الحل قبل أن تنضج طريقة meta CSP من Astro” ملاحظة مفيدة. “CSP معقد” ليست كذلك.
مزيج Svelte 5 + Astro أجبرني أيضاً على التفكير بعناية في ما يحتاج أن يكون تفاعلياً وما لا يحتاج. الافتراض الافتراضي في تطوير الويب الحديث هو أن كل شيء تفاعلي؛ Astro يعكس ذلك، والعمل ضمن هذا القيد أنتج موقعاً أسرع مما كان سيكون لو وصلت إلى إطار SPA.
ما الذي كنت سأغيّره
الـhomelab mirror على جهاز واحد بلا failover. هذا اختيار متعمد - التعقيد الذي لا تحتاجه هو تعقيد سيعضّك - لكنه يعني أيضاً أن الموقع ينزل حين أجري صيانة على الأجهزة، وهو ما يحدث أكثر مما أحب الاعتراف به. جهاز ثانٍ في active-passive failover مع Caddy كباب أمامي على قائمة مرحلة مستقبلية.
قصة CSP لا تزال عملاً قيد التقدم. ملف _headers الحالي يستخدم unsafe-inline كحل مؤقت ريثما تنضج طريقة meta-tag CSP الأصلية من Astro. هذا بند دَيْن معروف ومتتبَّع، وسينفَّذ حين تكون الوضعية المصدرية مستقرة بما يكفي للاعتماد عليها.
الشيء الذي أكثر ما يثير اهتمامي للمراحل المستقبلية: استخدام الموقع نفسه كسطح ناتج لسير عمل الوكيل. الآن، سجلات التقدم ووثائق الدروس تعيش في ملفات markdown أقرأها. ما أريده هو طبقة ذاكرة وكيل منظّمة - Fulcrum، بالتأكيد - تستوعب تلك الوثائق كمصادر L0 وتسطّح الدروس المنسّقة تلقائياً حين يخطط COS للمرحلة التالية. البنية التحتية موجودة بالفعل. أحتاج فقط توصيلها بشكل صحيح.
هذا هو المشروع الميتا الحقيقي: بناء الأدوات، ثم استخدام الأدوات لبناء المشروع، ثم تغذية دروس المشروع مجدداً إلى الأدوات. الحلقة بدأت تنغلق.