متغيرات البيئة
ما يفعله كل إعداد في ملفات .env الخاصة بواجهة API والواجهتين الأماميتين، وأيها تحتاج إليه.
لحزمة الحزمة الكاملة
أين توجد الإعدادات
| الملف | يقرؤه | يحتوي على أسرار |
|---|---|---|
back-end/.env | واجهة API، مع yarn dev وداخل Docker Compose | نعم. لا تضفه إلى المستودع أبدًا. |
storefront/.env | موقع الطلبات، وقت البناء | لا. كل القيم عامة. |
admin-dashboard/.env | لوحة تحكم الفريق، وقت البناء | لا. كل القيم عامة. |
.env بجوار docker-compose.yml | Docker Compose، للحزمة الكاملة | لا |
أنشئ ملف كل تطبيق من .env.example الموجود بجواره، والذي يشرح كل متغير: cp .env.example .env. تعمل الأمثلة كما هي للتشغيل المحلي.
أين توجد الإعدادات
ملف واحد، .env في مجلد الموقع، يُقرأ عند بناء الموقع. كل قيمة فيه عامة، لذلك لا يحتوي أي سر أبدًا: مفاتيح الدفع والذكاء الاصطناعي توجد في ملف .env الخاص بواجهة API. أنشئه من .env.example، الذي يشير إلى واجهة API على http://localhost:8000: cp .env.example .env.
أين توجد الإعدادات
ملف واحد، .env في مجلد لوحة التحكم، يُقرأ عند بناء لوحة التحكم. كل قيمة فيه عامة، لذلك لا يحتوي أي سر أبدًا: مفاتيح الذكاء الاصطناعي توجد في ملف .env الخاص بواجهة API. أنشئه من .env.example، الذي يشير إلى واجهة API على http://localhost:8000: cp .env.example .env.
أين توجد الإعدادات
ملف واحد، .env في مجلد واجهة API، تقرؤه واجهة API مع yarn dev، وتقرؤه الحاوية عندما تمرّره بـ --env-file .env. يحتوي على أسرار: لا ترفعه إلى المستودع أبدًا. أنشئه من .env.example، الذي يشرح كل متغير ويعمل كما هو للتشغيل المحلي: cp .env.example .env.
تضبط صورة Docker قيمها الافتراضية الخاصة، لذلك يعمل docker run من دون ملف: SQLite على /data/database.sqlite، والملفات المرفوعة في /data/uploads، وCORS_ORIGIN للواجهتين الأماميتين المحليتين، وPUBLIC_MEDIA_URL=http://localhost:8000/media وSEED_DEMO_DATA=false. غيّر أيًا منها باستخدام -e.
أساسيات واجهة API
تتحقق واجهة API من JWT_SECRET، ومن CORS_ORIGIN في الإنتاج، قبل أن تبدأ. إذا كان أحدهما ناقصًا أو غير صالح، تتوقف وتطبع سطرًا واحدًا يوضح ما يجب إصلاحه.
| المتغير | وظيفته |
|---|---|
NODE_ENV | development محليًا، وهو ينشئ الجداول ويحدّثها عند بدء التشغيل. وproduction على خادم مباشر، وهو لا يلمس الجداول أبدًا. |
PORT | منفذ واجهة API، وهو 8000. تشير إليه الواجهتان الأماميتان. |
DB_TYPE | sqlite (كما في .env.example) أو mysql. |
SQLITE_DATABASE | مسار ملف SQLite، وهو ./database.sqlite افتراضيًا. |
JWT_SECRET | يوقّع كل تسجيل دخول. مطلوب. قيمة المثال مقبولة خارج الإنتاج فقط. |
JWT_EXPIRATION | مدة صلاحية تسجيل الدخول، وهي 7d افتراضيًا. |
CORS_ORIGIN | عنوانا الموقع ولوحة التحكم، مفصولين بفاصلة. يجب أن يكون عنوان العودة من الدفع المستضاف على أحدهما. إذا لم يُضبط، فلا يُسمح إلا بـ http://localhost:3030 وhttp://localhost:3031؛ وهو مطلوب في الإنتاج. |
FRONTEND_URL | عنوان لوحة التحكم، الذي تتصل منه إشعاراتها المباشرة. مطلوب في الإنتاج لهذه الإشعارات. |
STOREFRONT_URL | عنوان الموقع، الذي يُرسَل إليه العميل من رابط الدفع ورابط إعادة تعيين كلمة المرور. قيمته الافتراضية أول عنوان في CORS_ORIGIN. |
API_PUBLIC_URL | العنوان العام لواجهة API هذه، الذي يعيد إليه Stripe و PayPal المتصفح أولًا. قيمته الافتراضية http://localhost على PORT. |
TRUST_PROXY | اختياري. عدد الخوادم الوكيلة العكسية أمام واجهة API، حتى تحسب الحدود الخاصة بكل عنوان الزائرَ الحقيقي. |
RATE_LIMIT_LOGIN | اختياري. عدد محاولات تسجيل الدخول الفاشلة المسموح بها لعنوان واحد على نموذج تسجيل دخول خلال 15 دقيقة قبل 429، وهو 10 افتراضيًا. |
RATE_LIMIT_ORDERS, RATE_LIMIT_PAYMENT_SESSION, RATE_LIMIT_TRACKING, RATE_LIMIT_REGISTER, RATE_LIMIT_CONTACT, RATE_LIMIT_PASSWORD_RESET | اختياري. الحدود الخاصة بكل عنوان على النماذج العامة؛ يذكر .env.example القيمة الافتراضية لكل حد ونافذته الزمنية. |
ولّد JWT_SECRET خاصًا بك بالأمر:
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"كل ميزة اختيارية أدناه تبقى متوقفة ما دامت أسطرها في .env.example معلّقة كتعليقات.
استخدم MySQL بدلًا من SQLite
أنشئ قاعدة بيانات فارغة، ثم اضبط المشغّل والاتصال في ملف .env الخاص بواجهة API:
DB_TYPE=mysql
DB_HOST=your-mysql-host
DB_PORT=3306
DB_USERNAME=your-mysql-username
DB_PASSWORD=your-mysql-password
DB_DATABASE=your-database-nameثم شغّل yarn seed للمطعم التجريبي، أو yarn db:sync للجداول من دون بيانات. لا تنشئ واجهة API العاملة الجداول وتحدّثها بنفسها إلا مع NODE_ENV=development، لذلك مع NODE_ENV=production يُشغَّل أحد هذين الأمرين قبل التشغيل الأول (yarn seed:prod أو yarn db:sync:prod بعد yarn build).
موقع الطلبات ولوحة تحكم الفريق
كل قيمة NEXT_PUBLIC_* تُضمَّن في كود JavaScript الذي يحمّله المتصفح، ويستطيع أي شخص يفتح الصفحة قراءتها. لا تضع أي سر في هذه الملفات أبدًا، وأعد البناء بعد تغيير أي قيمة.
| المتغير | التطبيق | وظيفته |
|---|---|---|
NEXT_PUBLIC_API_BASE_URL | كلاهما | عنوان واجهة API مع /api، وهو http://localhost:8000/api افتراضيًا. |
NEXT_PUBLIC_MEDIA_HOSTNAME | كلاهما | مضيف https لمخزن صورك، مثل pub-1234.r2.dev، أو لواجهة API عندما تقدّم الصور على نطاق عام. يغيّر Next.js حجم الصور القادمة منه؛ وأي صورة أخرى تُعرض كما هي. اسم المضيف فقط. اتركه فارغًا ما دامت واجهة API تعمل على localhost. |
NEXT_PUBLIC_WEBSOCKET_BASE_URL | لوحة التحكم | عنوان واجهة API من دون /api، للطلبات والإشعارات المباشرة. |
NEXT_PUBLIC_DASHBOARD_URL | لوحة التحكم | عنوان لوحة التحكم نفسها، للروابط الكاملة والتطبيق القابل للتثبيت. |
NEXT_PUBLIC_STOREFRONT_URL | لوحة التحكم | المكان الذي يقود إليه رابط «عرض المتجر» في شريط التنقل. |
NEXT_PUBLIC_MAP_STYLE_LIGHT, NEXT_PUBLIC_MAP_STYLE_DARK | الموقع (المظهر الفاتح فقط)، ولوحة التحكم | أنماط اختيارية لمربعات الخريطة. القيمة الفارغة تستخدم أنماط OpenFreeMap العامة، التي لا تحتاج إلى مفتاح. |
API_INTERNAL_URL | الموقع | اختياري، للخادم فقط، يُقرأ عند بدء الحاوية. المكان الذي يصل منه خادم الموقع نفسه إلى واجهة API عندما لا يعمل عنوان المتصفح من داخله، كما في Docker Compose (http://api:8000/api). اتركه غير مضبوط في غير ذلك. |
BUILD_STANDALONE | كلاهما | القيمة true تجعل yarn build يُخرج خادمًا مستقلًا بذاته، وهي القيمة التي تضبطها ملفات Dockerfile. اتركه غير مضبوط في غير ذلك. |
وسوم التسويق في الموقع هي أيضًا قيم NEXT_PUBLIC_*.
خيارات Docker Compose
لا تحتاج إلى ضبط أي شيء للتشغيل المحلي. لتغيير شيء، ضعه في ملف .env بجوار docker-compose.yml وشغّل docker compose up --build مرة أخرى: تُضمِّن الواجهات الأمامية هذه القيم.
| المتغير | القيمة الافتراضية | وظيفته |
|---|---|---|
SITE_PORT | 3030 | منفذ الموقع على جهازك. |
ADMIN_PORT | 3031 | منفذ لوحة التحكم على جهازك. |
API_PORT | 8000 | منفذ واجهة API على جهازك. |
SITE_URL, ADMIN_URL, API_URL | العناوين المحلية على هذه المنافذ | العنوان الذي يصل منه المتصفح إلى كل تطبيق. اضبط الثلاثة عند تشغيل التطبيقات على نطاقاتك الخاصة. |
MEDIA_HOSTNAME | فارغ | المضيف العام لمخزنك، مع متغيرات R2_* في back-end/.env. |
SEED_DEMO_DATA | true | القيمة false تبدأ بجداول فارغة ومن دون حسابات بدلًا من المطعم التجريبي. لا تهم إلا مع وحدة تخزين جديدة. |
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 | USD | العملة المرسلة مع كل قيمة متتبَّعة. |
غيّر المنفذ عندما يستخدمه برنامج آخر بالفعل، مثل ADMIN_PORT=3041. تُبنى القيم CORS_ORIGIN وFRONTEND_URL وSTOREFRONT_URL وAPI_PUBLIC_URL وPUBLIC_MEDIA_URL في واجهة API، وعنوان واجهة API في الواجهات الأمامية، كلها من المنافذ والعناوين الثلاثة، لذلك تتبعها تلقائيًا.
تقرأ حاوية واجهة API الملف back-end/.env أيضًا إذا كان موجودًا، لذلك تُضبط مفاتيح المدفوعات والبريد والوسائط والذكاء الاصطناعي في مكان واحد لكل من yarn dev و Docker. ملف compose هو الذي يُعتمد للقيم التي تختلف داخل الحاوية: مسار قاعدة البيانات، ومجلد الملفات المرفوعة، والمنفذ، وNODE_ENV=production، والعناوين أعلاه. تعيش قاعدة البيانات والملفات المرفوعة في وحدة التخزين food-studio-data.
تخزين الوسائط
تقدّم واجهة API الصور التجريبية بنفسها، من public/media/food-studio، على /media/food-studio/…. الملفات المرفوعة من لوحة التحكم (صور الأطباق، وصور الملفات الشخصية، ونتائج استوديو الذكاء الاصطناعي) تُحفظ على قرص واجهة API تحت MEDIA_UPLOAD_DIR وتُقدَّم على /media/uploads/…، ما لم يُضبط مخزن.
PUBLIC_MEDIA_URL=http://localhost:8000/media
MEDIA_UPLOAD_DIR=./public/media/uploadsPUBLIC_MEDIA_URL هو العنوان الذي يُوصل منه إلى /media من المتصفح. تكتبه تعبئة البيانات داخل عنوان كل صورة، لذلك اضبطه قبل أول تعبئة على الخادم. على الخادم، وجّه MEDIA_UPLOAD_DIR إلى تخزين دائم؛ ومع Docker يكون داخل وحدة تخزين البيانات.
لإرسال الملفات المرفوعة إلى Cloudflare R2، أو أي مخزن متوافق مع S3، اضبط المتغيرات الخمسة كلها، وأعطِ الواجهتين الأماميتين المضيف العام للمخزن عبر NEXT_PUBLIC_MEDIA_HOSTNAME (ومع Docker Compose، MEDIA_HOSTNAME). اضبط الخمسة كلها أو لا شيء منها.
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المدفوعات
ترسل صفحة إتمام الطلب العميل إلى صفحة Stripe أو PayPal نفسها. اضبط STRIPE_SECRET_KEY وSTRIPE_WEBHOOK_SECRET، أو PAYPAL_CLIENT_ID وPAYPAL_CLIENT_SECRET وPAYPAL_WEBHOOK_ID (مع PAYPAL_ENV، وقيمته الافتراضية sandbox). من دون أي مزوّد، توفّر صفحة إتمام الطلب دفعًا تجريبيًا مدمجًا يجعل الطلب مدفوعًا من دون تحويل أي مال.
STRIPE_SECRET_KEY=sk_test_your-stripe-secret-key
STRIPE_WEBHOOK_SECRET=whsec_your-webhook-secretالبريد الإلكتروني
تُرسل روابط إعادة تعيين كلمة المرور عبر Resend. تحتاج إلى القيمتين معًا: مفتاح بصلاحية الإرسال، وعنوان مرسِل (From) على نطاق موثَّق في Resend. من دونهما يستجيب «نسيت كلمة المرور» كالمعتاد، ولا تُرسل أي رسالة، ويذكر السجل أن البريد غير مضبوط.
RESEND_API_KEY=re_your-sending-access-key
MAIL_FROM=Food Studio <noreply@your-domain.com>
MAIL_MAX_PER_ADDRESS_PER_DAY=5يفتح الرابط صفحة إعادة التعيين في الموقع على STOREFRONT_URL، بلغة العميل، ويعمل مرة واحدة خلال ساعة. يستقبل العنوان الواحد MAIL_MAX_PER_ADDRESS_PER_DAY رسالة في اليوم كحد أقصى، و5 افتراضيًا.
ميزات الذكاء الاصطناعي
مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.
تشغيل ميزات الذكاء الاصطناعي: مفاتيح المزوّدين، والنماذج التي تستخدمها كل ميزة، ونموذج إزالة الخلفية.
خادم MCP
مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.
السماح لوكلاء البرمجة وعملاء MCP الآخرين باستخدام أدوات المساعد: المفتاح ونقطة النهاية.
وضع العرض التجريبي
مُضمَّن مع مشترياتك. سجّل الدخول لقراءته، أو افتحه في ملف التنزيل.
تشغيل نسخة تجريبية عامة: مفاتيح الوضع التجريبي، والحسابات الخاصة بكل زائر، وما يمكن للزوار تغييره.
الإطلاق
قبل النشر على أي مكان عام:
- في ملف
.envالخاص بواجهة API، اضبطNODE_ENV=productionوJWT_SECRETطويلًا وعشوائيًا خاصًا بك. - اضبط
CORS_ORIGINعلى عنوانَي الموقع ولوحة التحكم، وFRONTEND_URLعلى عنوان لوحة التحكم، وSTOREFRONT_URLعلى عنوان الموقع، وAPI_PUBLIC_URLعلى عنوان واجهة API، وPUBLIC_MEDIA_URLعلى عنوان واجهة API متبوعًا بـ/media. - على قاعدة بيانات جديدة، شغّل
yarn build، ثمyarn seed:prodمرة واحدة (أوyarn db:sync:prodلجداول فارغة)، ثمyarn start:prod. لا توجد عمليات ترحيل (migrations): أداة تعبئة البيانات هي أداة إنشاء المخطط. - احفظ الملفات المرفوعة على تخزين دائم: مخزن، أو
MEDIA_UPLOAD_DIRعلى قرص يبقى بعد النشر. - وجّه فحص السلامة لدى الاستضافة إلى
/api/health، واضبطTRUST_PROXYعندما يقف خادم وكيل عكسي أمام واجهة API. - ابنِ كل واجهة أمامية مع
NEXT_PUBLIC_API_BASE_URLيشير إلى واجهة API المنشورة؛ ولوحة التحكم أيضًا معNEXT_PUBLIC_WEBSOCKET_BASE_URLوNEXT_PUBLIC_DASHBOARD_URLوNEXT_PUBLIC_STOREFRONT_URL. - في الموقع، اضبط
domain.urlفيsrc/config/brand.config.ts، وأعد كتابة سياسة الخصوصية والشروط فيmessages/legalلتناسب نشاطك. - في لوحة التحكم، اضبط مطابخك وساعات عملها ورموز التوصيل البريدية، ورسومك ورموز الخصم، وحوّل ساعة الخدمة إلى «الساعة الحقيقية»: تبدأها تعبئة البيانات على الساعة التجريبية، التي تُبقي كل المطابخ مفتوحة.
- غيّر كلمات المرور التجريبية، أو احذف الحسابات، وحوّل المدفوعات إلى المفاتيح الحقيقية (live).
لا يصلح لمطعم فيه طلبات حقيقية
يبني yarn railway:setup، ويجلب نموذج إزالة الخلفية، ويحذف كل الجداول ويعبّئ البيانات، في كل مرة يُشغَّل فيها، ويحذف yarn drop:prod كل الجداول. يناسبان بيئة جديدة، ولا يصلحان أبدًا كأمر بناء لمطعم يعمل فعليًا.