انتقل إلى المقال

Hollinaانشر نشاط الحجز

انشر نشاط الحجز

ضع الموقع ولوحة التحكم وواجهة API على الإنترنت: Docker Compose على خادم واحد، أو تطبيق واحد لكل مضيف من Dockerfile الخاص به، أو Node.js مباشرة، ثم اربط معالج الدفع.

لحزمة الحزمة الكاملة

ثلاث طرق للنشر

الطريقةمناسبة لـما تحتاجه
Docker Compose على خادم واحدخادم VPS تتحكم فيه، والتطبيقات الثلاثة معًاالحزمة الكاملة، وDocker على الخادم، وخادم وكيل عكسي لـ HTTPS
تطبيق واحد لكل مضيف، من Dockerfile الخاص بهRailway وRender وFly.io ومضيفات أخرى تبني من Dockerfileمجلد كل تطبيق؛ ووحدة تخزين أو MySQL وحاوية تخزين لواجهة API
Node.js عاديأي مضيف NodeNode.js 22 أو أحدث وYarn 4 على المضيف

مهما كانت الطريقة التي تختارها، يدمج الموقع ولوحة التحكم عنوان واجهة API في JavaScript عند بنائهما، لذلك ابنهما بالعناوين العامة وليس المحلية أبدًا.

Docker Compose على خادم واحد

انسخ مجلد الحزمة إلى الخادم وضع ملف .env بجوار docker-compose.yml يحمل العناوين العامة الثلاثة. تُبنى منها كل العناوين الأخرى: الأصول المسموح بها في واجهة API، وعنوان لوحة التحكم، وعنوان الموقع الذي يعيد إليه معالج الدفع الضيف، وعناوين الصور، وعنوان واجهة API للواجهتين الأماميتين.

.env بجانب docker-compose.yml
SITE_URL=https://www.your-company.com
ADMIN_URL=https://admin.your-company.com
API_URL=https://api.your-company.com
MEDIA_HOSTNAME=api.your-company.com

MEDIA_HOSTNAME اختياري، مضيف واحد أو عدة مضيفين مفصولين بفاصلة (أضف مضيف حاويتك عندما تذهب الملفات المرفوعة إليها): تُغيَّر أحجام الصور على مضيفات https هذه بواسطة Next.js، وأي صورة أخرى تُحمَّل كما هي. ثم ابنِ وشغّل في الخلفية:

الطرفية
docker compose up --build -d
  • وجّه كل نطاق إلى الخادم عبر خادم وكيل عكسي يقدّم HTTPS (Caddy أو Nginx أو Traefik)، ويحوّل إلى المنافذ 3030 و3031 و8000.
  • خلف ذلك الوكيل اضبط TRUST_PROXY=1 في back-end/.env، فتحسب حدود تسجيل الدخول والحجز والأسئلة والتقييمات كل زائر لا الوكيل. تقرأ حاوية واجهة API الملف back-end/.env عندما يوجد، وهو أيضًا مكان مفاتيح الدفع والذكاء الاصطناعي وR2 وMCP.
  • بدون JWT_SECRET خاص بك تولّد واجهة API واحدًا عند أول تشغيل وتحفظه في وحدة التخزين hollina-data. وقاعدة البيانات والملفات المرفوعة في وحدة التخزين نفسها أيضًا، فاحتفظ بنسخة احتياطية منها.
  • يملأ أول تشغيل الشركة التجريبية ما لم يكن SEED_DEMO_DATA=false في .env. أبقِه في أول تشغيل: فالتعبئة هي التي تنشئ الحسابات.

واجهة API من Dockerfile

وجّه المضيف إلى مجلد واجهة API (back-end/ في الحزمة الكاملة). تستمع الصورة على PORT (8000 ما لم يحدد المضيف غيره)، وتردّ على GET /api/health بمجرد أن تستجيب قاعدة بياناتها، وتحفظ SQLite والملفات المرفوعة في /data.

  • اربط وحدة تخزين دائمة بالمسار /data. بدونها يبدأ كل نشر على قاعدة بيانات فارغة.
  • اضبط CORS_ORIGIN على عنواني الموقع ولوحة التحكم (مفصولين بفاصلة)، وFRONTEND_URL على عنوان لوحة التحكم، وSITE_URL على عنوان الموقع، وPUBLIC_MEDIA_URL على العنوان العام لواجهة API متبوعًا بـ /media.
  • اضبط SEED_DEMO_DATA=true في أول تشغيل على وحدة تخزين جديدة: القيمة الافتراضية للصورة هي false، وهي تنشئ الجداول بلا حسابات. ولا تُملأ قاعدة بيانات موجودة بالبيانات الأولية مرة أخرى أبدًا.
  • اضبط JWT_SECRET خاصًا بك، أو دع الحاوية تولّد واحدًا وتحفظه في /data/.jwt-secret.
  • اضبط TRUST_PROXY=1: فمنصة الاستضافة تضع وكيلًا أمام الحاوية.
  • على MySQL (DB_TYPE=mysql ومتغيرات DB_* الخمسة) لا تنشئ الحاوية الجداول. شغّل node dist/database/seeder.js (الشركة التجريبية) أو node dist/database/sync-schema.js (جداول فارغة) مرة واحدة بالبيئة نفسها.
  • تبقى الملفات المرفوعة على وحدة التخزين بعد إعادة النشر؛ ولإبعادها عن الخادم اضبط متغيرات R2_* الخمسة لحاوية تخزين.

الموقع ولوحة التحكم من Dockerfile الخاص بكل منهما

وجّه المضيف إلى مجلد التطبيق وأعطه قيم NEXT_PUBLIC_* على أنها معاملات بناء، وليس متغيرات تشغيل: فهي تُدمج عند البناء. تقدّم كل صورة خادم Next.js المستقل على PORT (3030 للموقع و3031 للوحة التحكم، ما لم يحدد المضيف غيرهما).

معامل البناءالتطبيقالقيمة
NEXT_PUBLIC_API_BASE_URLكلاهماالعنوان العام لواجهة API متبوعًا بـ /api
NEXT_PUBLIC_SITE_URLكلاهماالعنوان العام للموقع: العناوين الأساسية وخريطة الموقع في الموقع، و«العودة إلى الموقع» و«عرض الإقامة» في لوحة التحكم
NEXT_PUBLIC_MEDIA_HOSTNAMEكلاهمااختياري. مضيفات https التي تخدم الصور (نطاق واجهة API أو نطاق حاويتك أو الاثنان)، مفصولة بفاصلة
NEXT_PUBLIC_WEBSOCKET_BASE_URLلوحة التحكمالعنوان العام لواجهة API دون /api، للإشعارات المباشرة

يجلب خادم الموقع أيضًا من واجهة API أثناء تكوين عناوين الصفحات، والعرض الأول للصفحة الرئيسية وصفحات الإقامات، وخريطة الموقع. مع عنوان عام لواجهة API يعمل من الخادم أيضًا لا يلزم شيء آخر؛ ويتغلب API_INTERNAL_URL وقت التشغيل عليه عندما يجب أن يستخدم الخادم عنوانًا آخر.

Node.js عادي

ابنِ كل تطبيق مرة واحدة على المضيف، ثم شغّله. اضبط .env الخاص بالواجهتين الأماميتين على العناوين العامة قبل yarn build.

التطبيقالبناءالتشغيل
APIyarn build، ثم مرة واحدة yarn seed:prod (الشركة التجريبية) أو yarn db:sync:prod (جداول فارغة)yarn start:prod
موقع الإقاماتyarn buildyarn start (المنفذ 3030)
لوحة تحكم الحجوزاتyarn buildyarn start (المنفذ 3031)

تربط واجهة API العنوان 0.0.0.0 وتقرأ PORT. أبقِ ملف SQLite وMEDIA_UPLOAD_DIR على تخزين يبقى بعد النشر، أو استخدم MySQL وحاوية تخزين.

استقبل مدفوعات حقيقية

التثبيت الجديد يسوّي حجوزات البطاقة وPayPal بالمحاكي المرفق، الذي لا يأخذ أي مال، إلى أن يُضبط معالج. اضبط المعالجات التي سيدفع بها ضيوفك: مع Stripe وحده يعرض الموقع البطاقة، ومع PayPal وحده PayPal، ومع الاثنين الاثنين، ويعرض معهما الدفع عند الوصول ما دام مفعّلًا. في بيئة واجهة API:

  • Stripe: STRIPE_SECRET_KEY، ونقطة webhook على https://<your API>/api/webhooks/payments/stripe للأحداث checkout.session.completed وpayment_intent.payment_failed وcharge.refunded وcharge.dispute.created، ويوضع سر توقيعها في STRIPE_WEBHOOK_SECRET. قبل ضبطه يُرفض كل webhook من Stripe ولا يُسوّى حجز بالبطاقة أبدًا.
  • PayPal: PAYPAL_CLIENT_ID وPAYPAL_CLIENT_SECRET وPAYPAL_ENV=live، وwebhook على https://<your API>/api/webhooks/payments/paypal للأحداث PAYMENT.CAPTURE.COMPLETED وPAYMENT.CAPTURE.DENIED وPAYMENT.CAPTURE.REFUNDED وPAYMENT.CAPTURE.REVERSED، ويوضع معرّفه في PAYPAL_WEBHOOK_ID.
  • SITE_URL على العنوان العام للموقع: يعيد معالج الدفع الضيف إلى صفحة حجزه هناك.
  • الدفع عند الوصول مفتاح تبديل في تبويب المدفوعات في لوحة التحكم، وهو مفعّل افتراضيًا.

حساباتك الأولى

لا توجد صفحة تسجيل: حسابا لوحة التحكم يأتيان من التعبئة. ابدأ أول مرة بالشركة التجريبية، وسجّل الدخول، ثم اجعلها لك:

  1. غيّر بيانات تسجيل الدخول للحسابين في الإعدادات ثم الأمان، أو أنشئ مديرًا عامًا (Super Admin) خاصًا بك في إدارة المسؤولين واحذف الحسابين الأوليين.
  2. أعد الإقامات التجريبية إلى المسودة كي لا يعرضها الموقع بعد الآن. ليس في لوحة التحكم حذف للإقامة، ولا تحذف واجهة API إقامة إلا حين لا يحجز أي من حجوزاتها ليالي، وهذا شأن الحجز المكتمل دائمًا.
  3. اضبط اسم الشركة وشعارها النصي ووصفها وبريد التواصل والهاتف وسطر العنوان في الإعدادات ثم الشركة؛ وإقامة الواجهة والإقامات المختارة في الإعدادات ثم الصفحة الرئيسية؛ والدفع عند الوصول وسياسة الإلغاء في الإعدادات ثم المدفوعات.
  4. أعد تسمية الوجهات التجريبية أو استبدلها في الإعدادات ثم الوجهات. لا يمكن حذف وجهة ما زالت لها إقامات.

الإطلاق

قبل أن يصبح نشاط الحجز متاحًا من الإنترنت:

  1. في بيئة واجهة API، NODE_ENV=production وJWT_SECRET طويل وعشوائي خاص بك (يولّد Docker واحدًا عند عدم ضبطه). في الإنتاج ترفض واجهة API البدء بدون CORS_ORIGIN، وتذكر القيمة الناقصة.
  2. CORS_ORIGIN على الموقع ولوحة التحكم، وFRONTEND_URL على لوحة التحكم، وSITE_URL على الموقع، وPUBLIC_MEDIA_URL على واجهة API متبوعًا بـ /media.
  3. ضبط Stripe أو PayPal أو الاثنين مع webhook لكل منهما. إلى أن يحدث ذلك يؤكد المحاكي كل حجز بالبطاقة أو PayPal دون أخذ أي مال، ويقول سجل بدء واجهة API Payment simulator active.
  4. قاعدة البيانات والملفات المرفوعة على تخزين دائم، مع نسخة احتياطية.
  5. فحص الصحة الخاص بالمضيف على /api/health، وTRUST_PROXY=1 خلف وكيل.
  6. بناء الواجهتين الأماميتين بقيم NEXT_PUBLIC_* العامة.
  7. في الموقع: علامتك في src/config/brand.config.ts، وسياسة الخصوصية في messages/privacy معاد كتابتها لشركتك وبلدك.
  8. تغيير بيانات تسجيل الدخول للحسابين الأوليين، أو حذفهما.
  9. DEMO_MODE=false على واجهة API وNEXT_PUBLIC_DEMO_MODE=false في الواجهتين الأماميتين، كما تُشحن.

ليست لشركة لها بيانات حقيقية

yarn setup:fresh يبني ويحذف كل الجداول ويملأها بالبيانات في كل مرة يعمل فيها، وyarn db:reset يحذف كل الجداول. وتشغيل yarn seed مرة أخرى يعيد الإقامات والحجوزات وإعدادات الشركة المرفقة إلى قيمها المرفقة، مع أنه يبقي الصفوف التي أنشأتها. هي تناسب بيئة جديدة تمامًا، وليست أمر تشغيل أو بناء أبدًا.

توقفت عند خطوة؟

ابحث عن الحل قبل أن تبدأ من جديد.

حل المشكلات

تفضيلات ملفات تعريف الارتباط

نستخدم ملفات تعريف الارتباط لتعزيز تجربة التصفح الخاصة بك وتحليل حركة المرور على الموقع وتخصيص المحتوى. بالنقر على "قبول الكل"، فإنك توافق على استخدامنا لملفات تعريف الارتباط للتحليلات والإعلانات المخصصة.