منظومة Oikosmou — دليل النشر الكامل
كل ما تحتاجه لتنزيل النظام من GitHub وتشغيله محلياً، ثم استضافته على الإنترنت — بما في ذلك قاعدة البيانات، تهيئة الواجهة (Webhost)، والمفاتيح السرّية، مع أفضل ٣ حلول استضافة مجانية وخطوات النقل التفصيلية لكلٍّ منها.
١. نظرة عامة على النظام
تتكوّن منظومة Oikosmou من أربعة مكوّنات تتواصل عبر REST API واحد:
| المكوّن | التقنية | المجلد | الدور |
|---|---|---|---|
| الخادم الخلفي (Backend) | Python · FastAPI · SQLAlchemy | oikosmou_backend/ | الـ API وقاعدة البيانات والمصادقة والإشعارات والبريد |
| تطبيق المستخدم | Flutter (Android/iOS/Web) | oikosmou_app/ | تجربة الألوان، الحاسبة، المتاجر، الطلبات، المكافآت |
| لوحة الإدارة | Flutter Web | oikosmou_admin/ | إدارة المحتوى والمستخدمين والطلبات والتقارير |
| الحزمة المشتركة | Dart Package | oikosmou_shared/ | نماذج DTO و enums و validators مشتركة |
| صفحة الهبوط | HTML/JS · PWA | landing/ | صفحة تعريفية + Web Push + تنزيل APK |
| قاعدة البيانات | PostgreSQL 16 | database/ | نسخة SQL كاملة جاهزة للاستعادة (٢١ جدول) |
# تدفّق البيانات
User App ─┐
├──► FastAPI Backend ──► PostgreSQL 16
Admin Web ─┘ │
Landing PWA ───────────►┘ (REST/HTTPS + JWT)
٢. المتطلبات الأساسية
| الأداة | الإصدار | لازمة لـ |
|---|---|---|
| Git | ≥ 2.30 | تنزيل المشروع |
| Docker + Docker Compose | Docker ≥ 24 / Compose ≥ 2.20 | قاعدة البيانات (الأسهل) |
| Python | 3.11 أو 3.12 | تشغيل الـ Backend |
| PostgreSQL | 16 | قاعدة البيانات (بديل Docker) |
| Flutter SDK | ≥ 3.19 (Dart ≥ 3.3) | بناء التطبيق ولوحة الإدارة |
downloads/ ولا يلزمك Android Studio إلا لإعادة بنائه.٣. التنزيل من GitHub
# استنساخ المستودع
git clone git@github.com:bodoorzahera/oikosmou.git
# أو عبر HTTPS
git clone https://github.com/bodoorzahera/oikosmou.git
cd oikosmou
بنية المجلدات بعد الاستنساخ:
oikosmou/
├── oikosmou_backend/ # FastAPI + Alembic + Docker
├── oikosmou_app/ # تطبيق المستخدم Flutter
├── oikosmou_admin/ # لوحة الإدارة Flutter Web
├── oikosmou_shared/ # الحزمة المشتركة Dart
├── landing/ # صفحة الهبوط PWA
├── database/ # ← نسخة SQL كاملة (schema + بيانات)
├── downloads/ # APK جاهز للتثبيت
├── deploy.html # ← هذا الملف
└── Features.html # صفحة الميزات الدعائية
٤. قاعدة البيانات
النظام يأتي مع نسخة قاعدة بيانات كاملة في مجلد database/ (٢٠٦ لون، ٢٠ منتج، ٥ متاجر، عروض، تصاميم، وحسابات تجريبية). لديك طريقتان:
الطريقة أ — Docker (الأسرع، موصى بها)
cd oikosmou_backend
docker compose up -d # PostgreSQL 16 على المنفذ 5433
# انتظر حتى تصبح الحاوية healthy، ثم استعِد البيانات:
cat ../database/oikosmou_full.sql | docker compose exec -T db psql -U oikosmou -d oikosmou
الطريقة ب — توليد البيانات من الصفر عبر Alembic + Seed
cd oikosmou_backend
source venv/bin/activate
alembic upgrade head # إنشاء كل الجداول (٢١ جدول)
python -m app.scripts.seed_data # تعبئة البيانات التجريبية
| المعطى | القيمة الافتراضية |
|---|---|
| Host / Port | localhost : 5433 (Docker) — تأكد أن .env يطابقه |
| Database | oikosmou |
| User / Password | oikosmou / oikosmou_dev_2024 |
| Admin login | admin@oikosmou.gr / admin123456 |
٥. الخادم الخلفي (Backend)
cd oikosmou_backend
# 1) بيئة افتراضية وتثبيت المكتبات
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# 2) إعداد متغيّرات البيئة (موجود مسبقاً في .env)
# عدّل DATABASE_URL والمفاتيح حسب الحاجة — انظر القسم ٧
# 3) تشغيل الخادم (تطوير)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# 4) أو للإنتاج (متعدّد العمّال)
gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
http://localhost:8000/docs لرؤية توثيق Swagger التفاعلي لكل الـ endpoints.٦. الواجهات (Frontend)
لوحة الإدارة (Flutter Web)
cd oikosmou_admin
flutter pub get
# التشغيل للتطوير:
flutter run -d chrome
# أو بناء نسخة ويب للنشر:
flutter build web --release # الناتج في build/web/
تطبيق المستخدم (Flutter)
cd oikosmou_app
flutter pub get
flutter run # على جهاز/محاكي
flutter build apk --release # بناء APK
# APK جاهز أيضاً في: downloads/oikosmou-latest.apk
صفحة الهبوط (Landing)
# مجلد ثابت static — يُرفع كما هو على أي استضافة ويب
cd landing
python3 -m http.server 8080 # معاينة محلية
baseUrl ليشير لعنوان خادمك:
oikosmou_app/lib/core/constants/api_constants.dartoikosmou_admin/lib/core/constants/api_constants.dart
٧. متغيّرات البيئة والمفاتيح
كل إعدادات الـ Backend في oikosmou_backend/.env. أهمّ المفاتيح:
| المتغيّر | الوصف | إلزامي؟ |
|---|---|---|
DATABASE_URL | رابط PostgreSQL (asyncpg) | نعم |
SECRET_KEY | مفتاح توقيع JWT — غيّره في الإنتاج | نعم |
ACCESS_TOKEN_EXPIRE_MINUTES | عمر توكن الدخول | افتراضي 30 |
CORS_ORIGINS | قائمة النطاقات المسموح لها بالاتصال | نعم |
SMTP_* | إرسال البريد/النشرة البريدية (Gmail App Password) | للبريد |
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY | إشعارات Web Push للمتصفح | للإشعارات |
FCM_SERVER_KEY + firebase-service-account.json | إشعارات الموبايل عبر Firebase | للموبايل |
GOOGLE_CLIENT_ID / SECRET / REDIRECT_URI | تسجيل الدخول عبر Google | لـ OAuth |
توليد مفاتيح VAPID لإشعارات الويب
cd oikosmou_backend && source venv/bin/activate
python -c "from py_vapid import Vapid01; v=Vapid01(); v.generate_keys(); print(v)"
# أو استخدم vapid_keys.json الموجود ثم انسخ المفاتيح إلى .env
مفتاح SECRET_KEY عشوائي للإنتاج
python -c "import secrets; print(secrets.token_urlsafe(48))"
.env وfirebase-service-account.json يحتويان أسراراً حقيقية. هذا المستودع خاص (private). إن جعلته عاماً يوماً ما، أزِل هذه الملفات من التتبّع أولاً (git rm --cached) وبدّل كل المفاتيح المسرّبة.٨. أفضل ٣ حلول استضافة مجانية
النظام يحتاج ٣ أشياء على الإنترنت: (أ) خادم Python للـ API، (ب) قاعدة PostgreSQL، (ج) استضافة ملفات ثابتة للوحة الإدارة وصفحة الهبوط. الحلول الثلاثة التالية توفّر ذلك مجاناً بالكامل:
الحل ١ · Render + Neon
الأسهل للمبتدئين. Backend على Render Free، قاعدة بيانات على Neon (Postgres مجاني سخي)، الواجهة على Netlify.
الحل ٢ · Railway المتكامل
كل شيء في منصّة واحدة (Backend + Postgres) برصيد مجاني شهري، والواجهة على Cloudflare Pages.
الحل ٣ · Fly.io + Supabase
الأقوى أداءً. حاويات Docker على Fly.io، Postgres على Supabase، الواجهة على GitHub Pages.
الحل ١ — Render + Neon + Netlify
| المكوّن | المنصّة | الباقة المجانية |
|---|---|---|
| Backend API | Render Web Service | ٧٥٠ ساعة/شهر (ينام بعد ١٥ دقيقة خمول) |
| قاعدة البيانات | Neon | ٠.٥ GB تخزين + فرع واحد دائم |
| لوحة الإدارة + Landing | Netlify | ١٠٠ GB نقل/شهر |
الخطوات
١) إنشاء قاعدة البيانات على Neon
# 1. أنشئ حساباً على neon.tech ومشروعاً جديداً (اختر منطقة قريبة)
# 2. انسخ Connection String، ثم استعِد البيانات:
psql "postgresql://USER:PASS@ep-xxx.neon.tech/oikosmou?sslmode=require" \
-f database/oikosmou_full.sql٢) نشر الـ Backend على Render
أنشئ Web Service جديداً واربطه بمستودع GitHub، أو استخدم ملف render.yaml. الإعدادات:
Root Directory : oikosmou_backend
Build Command : pip install -r requirements.txt
Start Command : gunicorn app.main:app -w 2 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:$PORT
أضف متغيّرات البيئة في لوحة Render → Environment:
DATABASE_URL = postgresql+asyncpg://USER:PASS@ep-xxx.neon.tech/oikosmou?ssl=require
SECRET_KEY = <مفتاح عشوائي 48 حرف>
CORS_ORIGINS = ["https://YOUR-ADMIN.netlify.app","https://YOUR-LANDING.netlify.app"]
SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=... SMTP_PASSWORD=...
asyncpg: استبدل postgresql:// بـ postgresql+asyncpg:// واستخدم ?ssl=require.٣) نشر لوحة الإدارة + Landing على Netlify
# عدّل baseUrl في api_constants.dart ليشير لرابط Render، ثم:
cd oikosmou_admin && flutter build web --release
# اسحب مجلد build/web إلى Netlify Drop (app.netlify.com/drop)
# أو عبر CLI:
npx netlify-cli deploy --dir=build/web --prod
# كرّر نفس الشيء لمجلد landing/https://oikosmou.onrender.com + لوحة إدارة على https://oikosmou-admin.netlify.app — مجاناً بالكامل.الحل ٢ — Railway (متكامل) + Cloudflare Pages
| المكوّن | المنصّة | الباقة المجانية |
|---|---|---|
| Backend + Database | Railway | $5 رصيد/شهر (يكفي مشروعاً صغيراً) — Postgres مُدار بنقرة |
| لوحة الإدارة + Landing | Cloudflare Pages | غير محدود تقريباً + CDN عالمي |
١) المشروع وقاعدة البيانات
# على railway.app أنشئ مشروعاً جديداً ثم:
# New → Database → Add PostgreSQL (يُنشئ DATABASE_URL تلقائياً)
# استعِد البيانات عبر رابط الاتصال العام:
psql "$RAILWAY_DATABASE_PUBLIC_URL" -f database/oikosmou_full.sql٢) نشر الـ Backend
Railway يكتشف Dockerfile الموجود في oikosmou_backend/ تلقائياً.
Root Directory : oikosmou_backend
# Railway يبني من Dockerfile مباشرة. أضف المتغيّرات:
DATABASE_URL = ${{Postgres.DATABASE_URL}} # مرجع داخلي + حوّله لصيغة asyncpg
SECRET_KEY = <مفتاح عشوائي>
PORT = 8000
gunicorn بدل uvicorn --reload، أو اضبط Start Command في Railway.٣) نشر الواجهة على Cloudflare Pages
cd oikosmou_admin && flutter build web --release
npx wrangler pages deploy build/web --project-name=oikosmou-admin
# و landing/ بنفس الطريقةالحل ٣ — Fly.io + Supabase + GitHub Pages
| المكوّن | المنصّة | الباقة المجانية |
|---|---|---|
| Backend (Docker) | Fly.io | حتى ٣ آلات صغيرة مشتركة + لا ينام |
| قاعدة البيانات | Supabase | ٥٠٠ MB Postgres + لوحة تحكّم غنية |
| لوحة الإدارة + Landing | GitHub Pages | مجاني للمستودعات |
١) قاعدة البيانات على Supabase
# أنشئ مشروعاً على supabase.com، ثم من Settings → Database انسخ الرابط:
psql "postgresql://postgres:PASS@db.xxx.supabase.co:5432/postgres" \
-f database/oikosmou_full.sql٢) نشر الـ Backend على Fly.io
مهمّ: شغّل أوامر Fly من داخل مجلد oikosmou_backend/ حيث يوجد الـ Dockerfile وfly.toml — وإلا سيظهر الخطأ Could not find a Dockerfile.
curl -L https://fly.io/install.sh | sh # تثبيت flyctl
cd oikosmou_backend # ← لازم: هنا يوجد Dockerfile و fly.toml
fly launch --no-deploy --copy-config # يستخدم fly.toml الجاهز بدل إعادة الكشف
fly secrets set DATABASE_URL="postgresql+asyncpg://postgres:PASS@db.xxx.supabase.co:5432/postgres" \
SECRET_KEY="<عشوائي>"
fly deploy
Dockerfile داخل مجلد فرعي. المستودع يحوي oikosmou_backend/fly.toml جاهزاً (المنفذ الداخلي 8080، HTTPS إجباري). الـ Dockerfile يعمل في الإنتاج عبر gunicorn ويحترم $PORT تلقائياً.٣) نشر الواجهة على GitHub Pages
cd oikosmou_admin
flutter build web --release --base-href /oikosmou-admin/
# ادفع محتوى build/web إلى فرع gh-pages في مستودع منفصل:
cd build/web && git init && git add -A && git commit -m "deploy"
git branch -M gh-pages
git remote add origin git@github.com:bodoorzahera/oikosmou-admin.git
git push -f origin gh-pages
# فعّل Pages من Settings → Pages → Branch: gh-pages٩. تهيئة استضافة الواجهة (Webhost) — تفاصيل مهمّة
لوحة الإدارة وتطبيق الويب من نوع SPA (تطبيق صفحة واحدة) تستخدم توجيهاً داخلياً عبر GoRouter. أي استضافة ثابتة تحتاج إعداداً ليعمل التحديث (refresh) على المسارات الفرعية:
Netlify — ملف _redirects داخل build/web/
/* /index.html 200
Vercel — ملف vercel.json
{ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] }
Apache — ملف .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
Nginx
server {
listen 80;
root /var/www/oikosmou_admin; # محتوى build/web
index index.html;
location / { try_files $uri $uri/ /index.html; }
location /api/ { proxy_pass http://127.0.0.1:8000; } # وكيل للـ API (اختياري)
}
- baseUrl: عدّل
api_constants.dartليشير لرابط الـ API الإنتاجي (https) قبلflutter build web. - CORS: أضف نطاق الواجهة إلى
CORS_ORIGINSفي.envعلى الخادم، وإلا ستُرفض الطلبات. - base-href: إن نُشرت في مجلد فرعي (مثل GitHub Pages) استخدم
--base-href /اسم-المجلد/.
إشعارات الويب (Service Worker) لصفحة الهبوط
صفحة landing/ تتضمّن sw.js وmanifest.json لإشعارات Web Push. يجب أن تُخدَّم عبر HTTPS (كل المنصّات أعلاه توفّره مجاناً) ليعمل الـ Service Worker.
١٠. قائمة تحقّق الإنتاج
| ✔ | البند |
|---|---|
| ☐ | تغيير SECRET_KEY إلى قيمة عشوائية طويلة |
| ☐ | تعيين DATABASE_URL لقاعدة الإنتاج (مع +asyncpg و SSL) |
| ☐ | استعادة database/oikosmou_full.sql على قاعدة الإنتاج |
| ☐ | ضبط CORS_ORIGINS على نطاقات الواجهة الحقيقية (أزل *) |
| ☐ | تحديث baseUrl في تطبيق المستخدم ولوحة الإدارة |
| ☐ | استبدال gunicorn بـ uvicorn --reload في الإنتاج |
| ☐ | تحديث GOOGLE_REDIRECT_URI ونطاقات OAuth المعتمدة في Google Console |
| ☐ | تفعيل النسخ الاحتياطي التلقائي لقاعدة البيانات |
| ☐ | التأكد من HTTPS لكل النطاقات (لازم لإشعارات Web Push) |
١١. حلّ المشاكل الشائعة
| المشكلة | الحل |
|---|---|
| الواجهة لا تتصل بالـ API (CORS error) | أضف نطاق الواجهة إلى CORS_ORIGINS وأعد تشغيل الخادم |
| refresh على مسار فرعي يعطي 404 | أضف قاعدة إعادة التوجيه (القسم ٩) حسب منصّتك |
asyncpg يرفض الاتصال SSL | أضف ?ssl=require لرابط Neon/Supabase |
| الخادم المجاني ينام (Render) | طبيعي بعد ١٥د خمول — أول طلب يستغرق ~٣٠ث للإيقاظ، أو استخدم Fly.io |
DuplicateObject: type already exists عند الترحيل | القاعدة مُهيّأة مسبقاً — استخدم الاستعادة من SQL بدل alembic upgrade |
| إشعارات الويب لا تعمل | تأكد من HTTPS وصحّة مفاتيح VAPID في .env |
| تطبيق Flutter web يظهر أبيض | تأكد من --base-href الصحيح عند النشر في مجلد فرعي |