بنيتُ لعائلتي تطبيق ويب لبرنامج رحلة — مع مساعد ذكاء اصطناعي بداخله

تاريخ النشر
11 يوليو 2026
بقلم
جاكوب لويد — كُتب بمساعدة الذكاء الاصطناعي بعد إنجاز المشروع
مدة القراءة
قراءة 1 دقيقة

بعبارة مبسطة: صنعت موقعًا صغيرًا فقط لرحلة عائلتي إلى اليابان — يعرض خطة كل يوم، والطقس، والخرائط، ويعمل على الهاتف حتى بلا تغطية. فيه أيضًا زر مساعد ذكاء اصطناعي صغير يمكنه الإجابة عن أسئلة الرحلة وتعديل الخطة قليلًا. هذا المقال قصة صادقة عن كيفية بنائه بمساعدة كبيرة من الذكاء الاصطناعي: ما نجح، وما تعطّل، وكيف حوّلت تصديرًا هشًا من أداة تصميم إلى شيء آمن للتعديل وآمن لوضعه على الويب. يمكنك تنزيل نموذج مُنظَّف وفتحه في أي متصفح.

سافرت عائلتي إلى اليابان، وأردت أن يحمل الجميع الخطة في جيوبهم — كل يوم موضّحًا،
والخرائط على بُعد نقرة، والطقس، والتفاصيل الصغيرة التي يسهل نسيانها وأنت منهك من
فارق التوقيت في محطة قطار. لذا بنيت تطبيق ويب صغيرًا لنا فقط: برنامج رحلة خاص
ومحمي برمز PIN
بجدول يومي، وطقس مباشر، ودعم للعمل دون اتصال، و— لأنني أنا —
مساعد ذكاء اصطناعي مدمج يمكنه الإجابة عن أسئلة حول الرحلة وحتى إجراء تعديلات
صغيرة.

هذه قصة البناء الصادقة: الأجزاء التي نجحت، والأجزاء التي تعطّلت بطرق لم أتوقعها،
وكيف تحوّل تصدير هش من أداة تصميم إلى شيء ارتحت لوضعه على الويب العام. في الأسفل
يوجد نموذج مُنظَّف يمكنك تنزيله وفتحه في أي متصفح.

خلاصة سريعة

  • ما هو: تطبيق ويب لبرنامج رحلة يراعي الهاتف أولًا — أيام، محطات، طقس مباشر، أدوات مساعدة للعملة والمنطقة الزمنية، دعم للعمل دون اتصال وقابل للتثبيت، مع تبويب لمساعد ذكاء اصطناعي.
  • الفكرة الجوهرية: تصدير جميل لكنه هش من أداة تصميم أصبح آمنًا للتعديل بمجرد أن أصبح الجدول كله مُدارًا بملف بيانات صغير واحد، وأعادت خطوة بناء توليد التطبيق.
  • البوابة: رمز PIN من جهة العميل مجرد مسرحية — الحقيقية هي جلسة من جهة الخادم مع إغلاق تصاعدي محدود المحاولات.
  • الذكاء الاصطناعي: نموذج محلي ذاتي الاستضافة، مربوط بحبل قصير (يجيب عن الأسئلة؛ يجري فقط تعديلات صغيرة ومحروسة).
  • الدرس الذي تكرر باستمرار: الطريقة الوحيدة لمعرفة أن التغيير نجح هي عرض التطبيق في متصفح حقيقي والنظر إليه — لا تثق أبدًا بأن الملف "يُفترض" أن يكون سليمًا.

البداية: صندوق أسود رائع الجمال

صمّمت الشكل في أداة تصميم بالذكاء الاصطناعي، ثم صدّرته. ما خرج كان ملف HTML واحد
قائمًا بذاته — تطبيق React كامل بخطوط وصور مضمّنة — بحجم 14 ميغابايت تقريبًا في
ملف واحد
. كان يبدو رائعًا ويعمل من أول نقرة مزدوجة.

لكنه كان أيضًا صندوقًا أسود. التطبيق بأكمله، مصغّرًا (minified)، كان يعيش في كتلة
واحدة ضخمة، والجدول مدفون بداخلها. تعديل الرحلة يدويًا يعني عملية جراحية في كود
مُولَّد آليًا. هذا مقبول مرة واحدة؛ لكنه كابوس في كل مرة تتغير فيها الخطط — وفي
رحلة عائلية، تتغير الخطط يوميًا.

لذا كان القرار الحقيقي الأول معماريًا: التوقف عن تعديل التصدير.

الفكرة الوحيدة التي جعلت كل شيء آخر ممكنًا

بدلًا من لمس الحزمة البالغة 14 ميغابايت، نقلت الجدول بأكمله إلى ملف بيانات
صغير وقابل للقراءة — ملف content.json واحد يحتوي الأيام والمحطات وملاحظات
الطقس وصور كل محطة وتكاليفها. ثم تقرأ خطوة بناء قصيرة ذلك الملف وتعيد توليد
التطبيق من التصدير النقي الأصلي.

هذا غيّر طابع المشروع بأكمله. الآن "إضافة محطة" أو "تصحيح وقت" هو تعديل من سطرين
في ملف بيانات يستطيع إنسان — أو مساعد ذكاء اصطناعي — القيام به بأمان، متبوعًا
بإعادة بناء. الجزء الهش (تطبيق الـ14 ميغابايت) لا يُلمس أبدًا يدويًا. كل عنصر
واجهة أضفته لاحقًا — بطاقة طقس مباشرة، وساعة مزدوجة توقيتك ↔ طوكيو، ومحوّل
عملة ثنائي الاتجاه، ومحطات قابلة للتوسيع بصور وملاحظات عن مواقف السيارات — كلها
مولَّدة من نفس عملية البناء المبنية على البيانات.

المطبّ الذي التهم كل عنصر واجهة: التطبيق يعيد بناء نفسه عند الإقلاع

إليكم الفخ الذي كلّفني أكبر قدر من الوقت، مكتوبًا هنا حتى لا يكلّفكم شيئًا.

التطبيق المصدَّر يعيد بناء الصفحة بأكملها عند إقلاعه. إذا حقنت الكود الخاص بك
في HTML الثابت — ساعة، شريط إعلان، أي شيء — فإنه يُمحى في اللحظة التي يُثبَّت
(mount) فيها التطبيق.
تختفي معرّفات عناصرك، وتُعيد getElementById القيمة
null إلى الأبد، ولا يظهر عنصر واجهتك أبدًا دون أي تنبيه. والأسوأ: إذا "تحققت"
بالبحث في ملف HTML المحفوظ، فإن كودك موجود هناك فعلًا، لذا يبدو الأمر سليمًا.
إنه فقط لا ينجو أبدًا إلى الشاشة.

قاعدتان أصلحتا الأمر نهائيًا:

  1. احقن في قالب التطبيق نفسه، لا في الصفحة. أضف عنصر واجهتك حيث يبني التطبيق
    واجهته، حتى يُعرَض كجزء من التطبيق وينجو من الإقلاع.
  2. اربط السلوك عبر تفويض الأحداث (event delegation) على document. يعيد
    التطبيق تثبيت أقسام كاملة عند تبديل التبويبات، فيدمّر عُقَدها ويعيد إنشاءها.
    المستمع (listener) المرفق بزر يموت عند إعادة العرض التالية؛ أما مستمع مفوَّض
    واحد على document (يتحقق مما نُقر عليه) فينجو من كل شيء.

النتيجة المترتبة هي قاعدة اختبار أعتبرها الآن قانونًا: لا تتحقق من واجهة ويب
بالبحث في الملف أو بفحص الرمز HTTP 200.
اعرضها في متصفح حقيقي (بلا واجهة
رسومية)، بعد إقلاعها، وانظر فعليًا إلى النتيجة. هذا هو الفحص الوحيد الذي يكشف
هذا النوع من الأخطاء — وقد كشفت عدة أخطاء بهذه الطريقة، منها محوّل عملة كان غير
مرئي حتى نقلته إلى القالب.

"مكتفٍ ذاتيًا" لم يكن كذلك

ادّعى التصدير أنه ملف واحد مكتفٍ ذاتيًا. لم يكن كذلك تمامًا. كان يجلب بصمت إطار
عمل الواجهة الخاص به من شبكة CDN عامة أثناء التشغيل، مُجمَّعًا من أجزاء عناوين
URL داخل الكود — لذا لم يجد بحث نصي عادي عن الـCDN أي شيء، وبدا الملف وكأنه
جاهز للعمل دون اتصال بينما لم يكن كذلك إطلاقًا. على استضافة ويب بسياسة أمان
صارمة، حُظر ذلك الجلب الخفي وفشل التطبيق بأكمله في البدء. على حاسوبي المحمول،
دون مثل هذه السياسة، عمل — لذا ظل الأمر غير مرئي حتى وصل إلى خادم حقيقي.

كان الحل هو استضافة إطار العمل ذاتيًا (تضمينه مع التطبيق حتى لا يوجد جلب
خارجي)، وبالنسبة للنموذج القابل للتنزيل، تضمينه مباشرة حتى يصبح الكل فعليًا
ملفًا واحدًا يُفتح من القرص دون أي اتصال بالإنترنت إطلاقًا. إذا أردت أن تأخذ شيئًا
عمليًا واحدًا من هذا القسم: "يعمل على جهازي" و"يعمل خلف رؤوس أمان خادم ويب
حقيقي" ادّعاءان مختلفان — اختبر الثاني.

البوابة: مسرحية مقابل قفل حقيقي

النسخة الأولى حمت الموقع برمز PIN داخل جافاسكريبت الصفحة. هذه مسرحية أمنية:
برنامج الرحلة بأكمله موجود في مصدر الصفحة، لذا يستطيع أي شخص يفتح أدوات المطوّر
قراءته دون كتابة الرمز إطلاقًا. مقبول لإخفاء حفلة مفاجئة عن نظرة عابرة؛ غير مقبول
لأي شيء تهتم به فعلًا.

النسخة الحقيقية نقلت البوابة إلى الخادم: تُرسل رمز PIN، يتحقق الخادم منه
ويبدأ جلسة، وعندها فقط يسلّم برنامج الرحلة. لديها أيضًا إغلاق تصاعدي لكل عنوان
IP
— بضع محاولات خاطئة وتُحظر تلك العناوين لفترات أطول تدريجيًا، حتى لا يستطيع
أحد إطلاق كل رمز من ستة أرقام رشقًا واحدًا.

سأكون صادقًا بشأن الحدود، لأن التظاهر بغير ذلك هو ما يوقع الناس في المشاكل: رمز
PIN من ستة أرقام محدود المحاولات فقط مناسب لبرنامج رحلة عائلية منخفض المخاطر،
لكنه ليس بمستوى أمان مصرفي. إذا كنت تحمي شيئًا حساسًا، استخدم عبارة مرور طويلة
وتسجيل دخول حقيقيًا. اجعل القفل مناسبًا لما وراء الباب.

المساعد الذكي، بحبل قصير

الجزء الممتع: مساعد صغير — سمّيته Yoshi — يعيش في تبويبه الخاص. في النسخة
العائلية الخاصة، يستطيع الإجابة عن أسئلة حول الرحلة ("ما خطة يوم الأكواريوم؟"،
"ماذا يجب أن نحزم؟") وإجراء تعديلات صغيرة ومحروسة على الجدول. الفكرة
الأساسية أنه يعدّل نفس ملف البيانات الآمن، وليس التطبيق الهش أبدًا — وهو
مسيّج: يستطيع الإضافة أو التعديل الطفيف، لكنه لا يستطيع حذف أيام، والرحلات
الجوية والحجوزات مقفلة بشكل صارم بحيث لا تستطيع أي رسالة دردشة لمسها.

الأهم من ذلك، أن Yoshi يعمل على نموذج محلي ذاتي الاستضافة — ذكاء اصطناعي
صغير على عتادي الخاص، وليس واجهة برمجية سحابية مدفوعة — يُصَل إليه عبر تتابع
(relay) محروس. هذا موضوع قائم بذاته (وضع روبوت دردشة مستضاف محليًا بأمان على
الويب العام، ومدى بطئه على عتاد استهلاكي)، لذا كتبته بشكل منفصل:
وضع روبوت دردشة على الويب العام — على عتادي الخاص.

ملاحظة حول النموذج القابل للتنزيل أدناه: تبويب المساعد موجود لتراه أين يعيش،
لكن في النموذج هو مُعطَّل عمدًا — غير مربوط بأي ذكاء اصطناعي ولن يجيب.
لتشغيله في نسختك الخاصة، عليك توجيهه إلى نموذجك المحلي الخاص. هذا مقصود: لن
أشحن ملفًا عامًا يتصل بصمت بذكاء اصطناعي يعمل فعليًا.

يعمل دون اتصال، قابل للتثبيت، وجاهز للسفر

كانت المجموعة الأخيرة من اللمسات متعلقة بواقع استخدام هذا أثناء رحلة: واي فاي
فندق متقطع، لا بيانات على متن الطائرة، تجوال يأتي ويذهب. لذا أصبح التطبيق
PWA قابلًا للتثبيت — أضفه إلى الشاشة الرئيسية ويُفتح كتطبيق حقيقي — ويعمل
دون اتصال
، يقدّم برنامج الرحلة بأكمله من الجهاز بمجرد تحميله. القاعدة الوحيدة
التي حرصت عليها: لا يخزّن مؤقتًا برنامج الرحلة إلا بعد فتح ناجح للقفل، حتى لا
تتجاوز ذاكرة التخزين المؤقت دون اتصال البوابةَ أبدًا. عبر الإنترنت، يتحقق دائمًا
من البوابة مجددًا؛ دون اتصال، يثق بالنسخة الموجودة بالفعل على هاتفك. بالنسبة
لخطة سفر عائلية، هذه هي المقايضة الصحيحة.

(لعمّال الخدمة (service workers) حواف حادة — يمكن لنسخة قديمة مخزّنة مؤقتًا أن
تستمر في تقديم صفحة قديمة لفترة طويلة بعد إصلاح خطأ ما. تعلّمت دائمًا شحن عامل
مُحدَّث، لا مجرد حذف القديم، حتى تلتقط المتصفحات التغيير فعليًا.)

اختباره وكأنه حقيقي، لأنه كذلك بالفعل

لأن العائلة كانت تستخدم هذا فعليًا أثناء السفر، تعاملت مع كل تغيير كأنه نشر:
ابنِ، اعرض الصفحة الحقيقية في متصفح بلا واجهة رسومية بعد الإقلاع، شغّل التبويبات
والأزرار الفعلية، وعندها فقط انشر. في منتصف الرحلة، دفعت إصلاحات صغيرة مباشرة
بهذه الطريقة — شارة "TODAY" تُبرز اليوم الحالي (مرتبطة بتوقيت طوكيو، لا بهاتف
المشاهد)، تحديث الطقس، وبعض تفاصيل التخطيط الصغيرة — كل واحدة تحقّقتُ منها أولًا
في متصفح حقيقي. إنه نفس الدرس الذي تعلمته من مطبّ إعادة البناء عند الإقلاع،
مُكتَسَبًا مجددًا: وجود الملف ليس هو عمل الميزة.

جرّبه بنفسك — نزّل النموذج

التنزيل أدناه هو نموذج عام مُنظَّف من التطبيق. كل اسم وتاريخ وعنوان وتفصيل
هو محتوى تجريبي خيالي؛ إنها خطة طوكيو خيالية لسبعة أيام. افتح index.html في
أي متصفح — بلا تثبيت، بلا خادم، بلا حساب. يعمل دون اتصال؛ فقط بطاقة الطقس
المباشر وروابط الخرائط تصل إلى الإنترنت.

تحفظان صادقان. أولًا، إنه ملف واحد بحجم ~14 ميغابايت لأن التطبيق والخطوط
والصور بأكملها مضمّنة حتى يعمل بلا أي اعتماديات — وهذا يجعله بطيئًا عند أول
فتح
؛ نسخة إنتاج حقيقية كانت ستقسّم وتضغط كل ذلك. ثانيًا، كما ذُكر، المساعد
الذكي معطَّل
في النموذج — يفتح التبويب ويخبرك بذلك.

ابنِ واحدًا بنفسك

صندوق "نفّذ هذا بنفسك" في الأعلى ليس شعارًا — كُتب هذا المقال ليُسلَّم مباشرة
إلى مساعد ذكاء اصطناعي. الوصفة، مُختصرة:

  1. ضع الخطة في ملف بيانات. الأيام، المحطات، الملاحظات، الطقس — ملف واحد
    قابل للقراءة يكون مصدر الحقيقة الوحيد.
  2. ولّد التطبيق منه. خطوة بناء حتمية تحوّل البيانات إلى واجهة، بحيث تكون
    التعديلات دائمًا على البيانات، لا على الكود المولَّد أبدًا.
  3. إذا بدأت من تصدير أداة تصميم، احترم إقلاعه. احقن في قالب التطبيق،
    استخدم أحداثًا مفوَّضة، واستضف ذاتيًا كل ما يجلبه.
  4. احمِ على الخادم، لا في الصفحة. جلسة مع إغلاق محدود المحاولات تتفوق دائمًا
    على رمز PIN بجافاسكريبت.
  5. اجعله يعمل دون اتصال أولًا إذا كان سيسافر — خزّن مؤقتًا فقط بعد فتح حقيقي
    للقفل.
  6. تحقق في متصفح، بعد الإقلاع. ليس "الملف موجود". الشاشة.

المطبّات، مجمَّعة

  • التصدير يعيد بناء DOM عند الإقلاع — أي شيء تحقنه في الصفحة يُمحى؛ احقن
    بدلًا من ذلك في قالب التطبيق، وفوّض الأحداث على document.
  • "مكتفٍ ذاتيًا" قد لا يكون كذلك — يمكن للتصدير جلب إطار عمله أثناء
    التشغيل؛ استضفه ذاتيًا، واختبر خلف رؤوس أمان خادمك الحقيقي، لا محليًا فقط.
  • رمز PIN من جهة العميل مجرد مسرحية — المحتوى موجود في الصفحة؛ احمِ على
    الخادم.
  • رمز PIN من ستة أرقام محدود المحاولات فقط، وليس غير قابل للكسر — مناسب
    للمخاطر المنخفضة، خاطئ لأي شيء حساس.
  • عمّال الخدمة يخزّنون مؤقتًا بقوة — اشحن عاملًا مُحدَّثًا لنشر إصلاح؛ حذف
    الملف القديم لا يلغي تسجيله.
  • "الملف موجود" ≠ "الميزة تعمل" — اعرضه وانظر إليه، في كل مرة.

التنزيلات

مجاني للاستخدام الشخصي. إذا وفّر لك عصرًا كاملًا من الوقت، فزر القهوة قريب منك.


← المزيد من الذكاء الاصطناعي والنماذج المحلية