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

Hollinaمتغيرات البيئة

متغيرات البيئة

ما يفعله كل إعداد في ملفات .env الخاصة بواجهة API والواجهتين الأماميتين، وأيها تحتاج إليه.

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

أين توجد الإعدادات

الملفيقرؤهيحتوي على أسرار
back-end/.envواجهة API، مع yarn dev وداخل Docker Composeنعم. لا تضفه إلى المستودع أبدًا.
storefront/.envموقع الإقامات، وقت البناءلا. كل قيمة NEXT_PUBLIC_* عامة.
admin-dashboard/.envلوحة تحكم الحجوزات، وقت البناءلا. كل القيم عامة.
.env بجوار docker-compose.ymlDocker Compose، للحزمة الكاملةلا

أنشئ ملف كل تطبيق من .env.example الموجود بجانبه، وهو يشرح كل متغير: cp .env.example .env. تعمل الأمثلة كما هي للتشغيل المحلي، ولا يحتاج تشغيل Docker Compose إلى أي ملف.

أين توجد الإعدادات

ملف واحد هو .env في مجلد الموقع، يُقرأ عند بناء الموقع. كل قيمة NEXT_PUBLIC_* فيه عامة، فلا يحتوي سرًا أبدًا. أنشئه من .env.example الذي يشير إلى واجهة API على http://localhost:8000: cp .env.example .env. مع Docker مرّر القيم نفسها بـ --build-arg.

أين توجد الإعدادات

ملف واحد هو .env في مجلد لوحة التحكم، يُقرأ عند بناء لوحة التحكم. كل قيمة فيه عامة، فلا يحتوي سرًا أبدًا: مفاتيح الدفع والذكاء الاصطناعي في .env الخاص بواجهة API. أنشئه من .env.example الذي يشير إلى واجهة API على http://localhost:8000: cp .env.example .env. مع Docker مرّر القيم نفسها بـ --build-arg.

أين توجد الإعدادات

ملف واحد هو .env في مجلد واجهة API، تقرؤه واجهة API عند yarn dev، وتقرؤه الحاوية عندما تضيف --env-file .env -e NODE_ENV=production إلى docker run. يحوي أسرارًا: لا تضفه إلى المستودع أبدًا. أنشئه من .env.example الذي يشرح كل متغير ويعمل كما هو للتشغيل المحلي: cp .env.example .env.

صورة Docker تضبط قيمها الافتراضية بنفسها، فيعمل docker run بلا ملف: SQLite على /data/database.sqlite، والملفات المرفوعة في /data/uploads، وCORS_ORIGIN للواجهتين الأماميتين المحليتين، وFRONTEND_URL=http://localhost:3031 وSITE_URL=http://localhost:3030 وPUBLIC_MEDIA_URL=http://localhost:8000/media وSEED_DEMO_DATA=false. تجاوز أيًا منها بـ -e.

أساسيات واجهة API

تتحقق واجهة API من JWT_SECRET، ومن CORS_ORIGIN في الإنتاج، قبل أن تبدأ. إذا كان أحدهما ناقصًا أو غير صالح، تتوقف وتطبع سطرًا واحدًا يوضح ما يجب إصلاحه.

المتغيروظيفته
NODE_ENVdevelopment محليًا، وهو ينشئ الجداول ويحدّثها عند بدء التشغيل. وproduction على خادم مباشر، وهو لا يلمس الجداول أبدًا.
PORTمنفذ واجهة API، وهو 8000. تشير إليه الواجهتان الأماميتان.
DB_TYPEsqlite (كما في .env.example) أو mysql. إذا لم يُضبط فالمقصود MySQL، لذلك أبقِ السطر.
SQLITE_DATABASEمسار ملف SQLite، وهو ./database.sqlite افتراضيًا.
JWT_SECRETيوقّع كل جلسة تسجيل دخول. مطلوب. قيمة المثال مقبولة خارج الإنتاج فقط.
JWT_EXPIRATIONمدة صلاحية تسجيل الدخول، 7d افتراضيًا. تعيدها استجابة تسجيل الدخول باسم expires_in.
CORS_ORIGINعنوانا الموقع ولوحة التحكم، مفصولان بفاصلة. إذا لم يُضبط فلا يُسمح إلا بـ http://localhost:3030 وhttp://localhost:3031، وليس بكل الأصول أبدًا؛ مطلوب في الإنتاج.
FRONTEND_URLعنوان لوحة التحكم، وتتصل منه إشعاراتها المباشرة، وهو http://localhost:3031 عند عدم الضبط.
SITE_URLعنوان الموقع. يعيد معالج الدفع الضيف إلى هنا، إلى صفحة حجزه، لذلك يجب أن يكون العنوان الذي يتصفح به الضيف.
TRUST_PROXYاختياري. عدد الوكلاء العكسيين أمام واجهة API، كي تحسب الحدود لكل عنوان (تسجيل الدخول والحجوزات والأسئلة والتقييمات) الزائر الحقيقي.
RATE_LIMIT_LOGINاختياري. عدد محاولات الدخول الفاشلة التي يمكن لعنوان واحد القيام بها خلال 15 دقيقة قبل 429، وهو 10 افتراضيًا.
SEED_DEMO_DATAتقرؤه صورة Docker فقط، على وحدة تخزين بلا قاعدة بيانات بعد: true ينشئها مع الشركة التجريبية، وfalse بالجداول فقط.

ولّد JWT_SECRET خاصًا بك بالأمر:

الطرفية
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"

كل ميزة اختيارية أدناه تبقى متوقفة ما دامت أسطرها في .env.example معلّقة كتعليقات.

المدفوعات

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

ملف .env الخاص بواجهة API
STRIPE_SECRET_KEY=your-stripe-secret-key
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-signing-secret
PAYPAL_CLIENT_ID=your-paypal-client-id
PAYPAL_CLIENT_SECRET=your-paypal-client-secret
PAYPAL_WEBHOOK_ID=your-paypal-webhook-id
PAYPAL_ENV=sandbox
المتغيروظيفته
STRIPE_SECRET_KEYيفعّل الدفع بالبطاقة عبر Checkout المستضاف من Stripe. مفتاح sk_test_ لا يحرّك مالًا حقيقيًا.
STRIPE_WEBHOOK_SECRETسر التوقيع لنقطة webhook في Stripe، أو الذي يطبعه stripe listen. بدونه يُرفض كل webhook من Stripe، فلا يُسوّى حجز بالبطاقة أبدًا.
PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRETيفعّل PayPal عبر Orders v2، الاثنان معًا.
PAYPAL_WEBHOOK_IDمعرّف اشتراك webhook في PayPal، الذي يتحقق من توقيع PayPal.
PAYPAL_ENVsandbox (الافتراضي) أو live.

الدفع عند الوصول لا يحتاج إلى مفتاح: هو مفتاح التبديل allow_pay_on_arrival في تبويب المدفوعات في لوحة التحكم، ومفعّل في البيانات الأولية.

استخدم MySQL بدلًا من SQLite

أنشئ قاعدة بيانات فارغة، ثم اضبط المشغّل والاتصال في ملف .env الخاص بواجهة API:

ملف .env الخاص بواجهة API
DB_TYPE=mysql
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=hollina

ثم شغّل yarn seed للشركة التجريبية، أو yarn db:sync للجداول بلا بيانات. لا تنشئ واجهة API العاملة الجداول وتحدّثها بنفسها إلا حين NODE_ENV=development، لذلك مع NODE_ENV=production يُشغَّل أحد هذين الأمرين قبل أول تشغيل (yarn seed:prod أو yarn db:sync:prod بعد yarn build).

الصور والملفات المرفوعة

تخدم واجهة API الصور الأولية بنفسها، من public/media/hollina، على /media/hollina/…. وتُخزَّن الملفات المرفوعة من لوحة التحكم (صور الإقامات، وأغلفة الوجهات، والصور الشخصية) على قرص واجهة API تحت MEDIA_UPLOAD_DIR وتُخدم على /media/uploads/…، ما لم تُضبط حاوية تخزين.

ملف .env الخاص بواجهة API
PUBLIC_MEDIA_URL=http://localhost:8000/media
MEDIA_UPLOAD_DIR=./public/media/uploads

PUBLIC_MEDIA_URL هو العنوان الذي يُوصَل به إلى /media من المتصفح. تُبنى منه كل عناوين الصور، وتنقل واجهة API العناوين المخزنة إليه عند بدئها، فنقل واجهة API يُبقي كل صورة. على الخادم وجّه MEDIA_UPLOAD_DIR إلى تخزين دائم؛ ومع Docker هو في وحدة تخزين البيانات.

لإرسال الملفات المرفوعة إلى Cloudflare R2، أو أي حاوية متوافقة مع S3، اضبط المتغيرات الخمسة كلها. أعطِ الواجهتين الأماميتين المضيف العام للحاوية عبر NEXT_PUBLIC_MEDIA_HOSTNAME (مع Docker Compose، MEDIA_HOSTNAME) كي يغيّر Next.js أحجام تلك الصور.

ملف .env الخاص بواجهة API
R2_ACCESS_KEY_ID=your-r2-access-key-id
R2_SECRET_ACCESS_KEY=your-r2-secret-access-key
R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your-bucket-name
R2_PUBLIC_URL=https://your-public-url.r2.dev

تُعاد ترميز الصور عند الرفع بصيغة JPEG، بعرض أقصاه 1920 بكسل، مع نسخة أصغر لبطاقات الإقامات. تُقبل الفيديوهات بصيغة MP4 أو WebM أو MOV أو M4V، حتى 150 ميغابايت.

موقع الإقامات ولوحة تحكم الحجوزات

كل قيمة NEXT_PUBLIC_* تُضمَّن في كود JavaScript الذي يحمّله المتصفح، ويستطيع أي شخص يفتح الصفحة قراءتها. لا تضع أي سر في هذه الملفات أبدًا، وأعد البناء بعد تغيير أي قيمة.

المتغيرالتطبيقوظيفته
NEXT_PUBLIC_API_BASE_URLكلاهماعنوان واجهة API مع /api، وهو http://localhost:8000/api افتراضيًا.
NEXT_PUBLIC_SITE_URLكلاهماالعنوان العام للموقع، http://localhost:3030 افتراضيًا. في الموقع تُبنى منه العناوين الأساسية وبدائل اللغات وبطاقات المشاركة وrobots.txt وخريطة الموقع؛ وفي لوحة التحكم يُبنى منه الشعار النصي في صفحة تسجيل الدخول و«العودة إلى الموقع» ورابط الخصوصية، و«عرض الإقامة» في محرر الإقامة.
NEXT_PUBLIC_MEDIA_HOSTNAMEكلاهمااختياري. مضيفات https التي تخدم الصور، مفصولة بفاصلة: المضيف العام لحاويتك، مثل pub-1234.r2.dev، أو نطاق واجهة API، أو الاثنان. تُغيَّر أحجام الصور عليها بواسطة Next.js؛ وأي صورة أخرى تُحمَّل كما هي. مضيفات فقط، بدون https://. يقرأ التطبيقان القائمة نفسها، فقيمة واحدة تخدمهما. اتركه فارغًا ما دامت واجهة API تعمل على localhost.
NEXT_PUBLIC_WEBSOCKET_BASE_URLلوحة التحكمعنوان واجهة API من دون /api، للإشعارات المباشرة.
NEXT_PUBLIC_MAP_STYLE_LIGHT, NEXT_PUBLIC_MAP_STYLE_DARKالموقعأنماط MapLibre اختيارية لخريطة صفحة الإقامة. إن لم تُضبط ترسم السمتان نمط Positron من OpenFreeMap، وهو لا يحتاج إلى مفتاح.
API_INTERNAL_URLالموقعاختياري، للخادم فقط، ويُقرأ وقت التشغيل وليس وقت البناء. هو المكان الذي يصل منه خادم الموقع نفسه إلى واجهة API عندما لا يعمل عنوان المتصفح من داخله، كما في Docker (http://api:8000/api في Docker Compose). اتركه بلا ضبط في غير ذلك.
BUILD_STANDALONEكلاهماالقيمة true تجعل yarn build يُخرج خادمًا مستقلًا بذاته، وهي القيمة التي تضبطها ملفات Dockerfile. اتركه غير مضبوط في غير ذلك.

أوسمة التسويق في الموقع هي أيضًا قيم NEXT_PUBLIC_*: Google Tag Manager وGA4 وMeta وTikTok وSnapchat وPinterest، ويُفعَّل كل منها بمعرّف واحد.

خيارات Docker Compose

لا تحتاج إلى ضبط أي شيء للتشغيل المحلي. لتغيير شيء، ضعه في ملف .env بجوار docker-compose.yml وشغّل docker compose up --build مرة أخرى: تُضمِّن الواجهات الأمامية هذه القيم.

المتغيرالقيمة الافتراضيةوظيفته
SITE_PORT3030منفذ الموقع على جهازك.
ADMIN_PORT3031منفذ لوحة التحكم على جهازك.
API_PORT8000منفذ واجهة API على جهازك.
SITE_URL, ADMIN_URL, API_URLالعناوين المحلية على هذه المنافذالعنوان الذي يصل منه المتصفح إلى كل تطبيق. اضبط الثلاثة عند تشغيل التطبيقات على نطاقاتك الخاصة.
MEDIA_HOSTNAMEفارغمضيفات https التي تخدم الصور، مفصولة بفاصلة: المضيف العام لحاويتك (مع متغيرات R2_* في back-end/.env)، أو نطاق واجهة API نفسها، أو الاثنان.
SEED_DEMO_DATAtruefalse يبدأ بجداول فارغة وبلا حسابات بدلًا من الشركة التجريبية. ولا يهم إلا على وحدة تخزين جديدة.
NEXT_PUBLIC_GTM_ID, NEXT_PUBLIC_GA4_MEASUREMENT_ID, NEXT_PUBLIC_META_PIXEL_ID, NEXT_PUBLIC_TIKTOK_PIXEL_ID, NEXT_PUBLIC_SNAPCHAT_PIXEL_ID, NEXT_PUBLIC_PINTEREST_TAG_IDفارغوسوم التسويق في الموقع، وكلها اختيارية.
NEXT_PUBLIC_ANALYTICS_CURRENCY, NEXT_PUBLIC_ANALYTICS_DEBUGUSD, falseالعملة المرسلة مع كل سعر يُتتبَّع، وتسجيل كل حدث في وحدة تحكم المتصفح.
NEXT_PUBLIC_MAP_STYLE_LIGHT, NEXT_PUBLIC_MAP_STYLE_DARKفارغأنماط خريطة صفحة الإقامة؛ وإذا تُرك فارغًا استُخدم Positron من OpenFreeMap.

غيّر المنفذ حين يستخدمه برنامج آخر، مثل ADMIN_PORT=3041. أما CORS_ORIGIN وFRONTEND_URL وSITE_URL وPUBLIC_MEDIA_URL في واجهة API، وعنوانا واجهة API والموقع في الواجهتين الأماميتين، فكلها تُبنى من المنافذ والعناوين الثلاثة، فتتبعها من تلقاء نفسها.

تقرأ حاوية واجهة API الملف back-end/.env أيضًا عندما يوجد، فتُضبط مفاتيح الدفع والذكاء الاصطناعي وR2 وMCP في مكان واحد لكل من yarn dev وDocker. ويتغلب ملف compose في القيم التي تختلف داخل الحاوية: مسار قاعدة البيانات، ومجلد الملفات المرفوعة، والمنفذ، وNODE_ENV=production، والعناوين أعلاه. وقاعدة البيانات والملفات المرفوعة في وحدة التخزين hollina-data.

المساعد الذكي

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

تفعيل المساعد الذكي: مفتاح Google Gemini وما يُحاسَب عليه.

خادم MCP

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

السماح لوكلاء البرمجة وعملاء MCP الآخرين باستخدام أدوات المساعد: المفتاح ونقطة النهاية.

وضع العرض التجريبي

مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.

مفتاح التبديل للعرض التجريبي العام، ولماذا يبقى متوقفًا لشركة حقيقية.

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

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

حل المشكلات

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

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