Alinabil1 commited on
Commit
d5f16a7
·
1 Parent(s): d6d15aa

feat: switch to Docker SDK with complete backend integration

Browse files
Files changed (5) hide show
  1. .spacesconfig +0 -3
  2. Dockerfile +41 -0
  3. README.md +2 -3
  4. app.py +100 -132
  5. entrypoint.sh +11 -162
.spacesconfig DELETED
@@ -1,3 +0,0 @@
1
- sdk: gradio
2
- sdk_version: 5.9.1
3
- python_version: 3.12
 
 
 
 
Dockerfile ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Set environment variables
6
+ ENV PYTHONUNBUFFERED=1 \
7
+ PYTHONDONTWRITEBYTECODE=1 \
8
+ PIP_NO_CACHE_DIR=1 \
9
+ PORT=7860 \
10
+ OUTPUT_DIR=/app/output
11
+
12
+ # Install system dependencies
13
+ RUN apt-get update && apt-get install -y --no-install-recommends \
14
+ curl \
15
+ gcc \
16
+ g++ \
17
+ && rm -rf /var/lib/apt/lists/*
18
+
19
+ # Copy requirements and install Python dependencies
20
+ COPY requirements.txt .
21
+ RUN pip install --upgrade pip && \
22
+ pip install -r requirements.txt
23
+
24
+ # Download spacy model
25
+ RUN python -m spacy download en_core_web_sm || true
26
+
27
+ # Copy application code
28
+ COPY . .
29
+
30
+ # Create output directory
31
+ RUN mkdir -p output
32
+
33
+ # Expose port
34
+ EXPOSE 7860
35
+
36
+ # Health check
37
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
38
+ CMD curl -f http://localhost:7860/health || exit 1
39
+
40
+ # Run the application
41
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -3,9 +3,8 @@ title: Moharek GEO Platform
3
  emoji: 🚀
4
  colorFrom: blue
5
  colorTo: green
6
- sdk: gradio
7
- sdk_version: 5.9.1
8
- app_file: app.py
9
  pinned: false
10
  license: mit
11
  ---
 
3
  emoji: 🚀
4
  colorFrom: blue
5
  colorTo: green
6
+ sdk: docker
7
+ app_port: 7860
 
8
  pinned: false
9
  license: mit
10
  ---
app.py CHANGED
@@ -1,55 +1,71 @@
1
  """
2
  Moharek GEO Platform - Hugging Face Space
3
- AI-Powered Generative Engine Optimization Platform
4
  """
5
 
6
  import os
7
  import sys
8
  from pathlib import Path
9
 
10
- # Add server to path
11
  sys.path.insert(0, str(Path(__file__).parent))
12
 
13
  import gradio as gr
14
  import uvicorn
15
- from fastapi import FastAPI
16
  from fastapi.staticfiles import StaticFiles
17
- from fastapi.responses import FileResponse, RedirectResponse
18
 
19
- # Import the main API
20
  from server.api import app as fastapi_app
21
 
22
  # Configuration
23
- PORT = 7860
24
  HOST = "0.0.0.0"
25
 
26
- # Mount frontend static files with /app prefix
 
 
 
 
27
  frontend_path = Path(__file__).parent / "frontend"
28
  if frontend_path.exists():
29
- fastapi_app.mount("/frontend", StaticFiles(directory=str(frontend_path)), name="frontend")
 
 
 
30
 
31
- # Serve HTML pages with /app prefix
32
  @fastapi_app.get("/app/")
33
- async def serve_index():
34
  return FileResponse(str(frontend_path / "index.html"))
35
 
36
- @fastapi_app.get("/app/{page}.html")
37
- async def serve_page(page: str):
38
- file_path = frontend_path / f"{page}.html"
 
 
 
 
39
  if file_path.exists():
40
  return FileResponse(str(file_path))
41
- return {"error": "Page not found"}
42
-
43
- # Create Gradio interface for HF Space
44
- def create_gradio_interface():
45
- """Create Gradio interface for Hugging Face Space"""
46
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  with gr.Blocks(
48
  title="Moharek GEO Platform",
49
- theme=gr.themes.Soft(
50
- primary_hue="teal",
51
- secondary_hue="green",
52
- ),
53
  css="""
54
  .gradio-container {
55
  background: linear-gradient(135deg, #071f21 0%, #0F4246 100%);
@@ -59,115 +75,83 @@ def create_gradio_interface():
59
  background: linear-gradient(135deg, #c8f04e, #a8d630) !important;
60
  color: #071f21 !important;
61
  font-weight: 900 !important;
62
- border: none !important;
63
- }
64
- .gr-button-primary:hover {
65
- transform: translateY(-2px);
66
- box-shadow: 0 8px 25px rgba(200, 240, 78, 0.3);
67
  }
68
  """
69
  ) as demo:
 
 
70
 
71
- gr.Markdown(
72
- """
73
- # 🚀 محرك — Moharek GEO Platform
74
-
75
- ## منصة تحسين محركات البحث بالذكاء الاصطناعي
76
-
77
- **Search Growth System** — 5 محركات متكاملة تغطي كل رحلة العميل
78
-
79
- ---
80
-
81
- ### 🎯 الميزات الرئيسية:
82
-
83
- - 📈 **SEO Engine** — تحسين محركات البحث التقليدية
84
- - 🤖 **AI Visibility Engine** — الظهور في ChatGPT و Gemini
85
- - 🎯 **Ads Engine** — إدارة الإعلانات الذكية
86
- - 📝 **Content Engine** — إنشاء محتوى متعدد القنوات
87
- - ⭐ **Trust Engine** — بناء الثقة والسمعة الرقمية
88
-
89
- ---
90
- """
91
- )
92
 
93
  with gr.Row():
94
  with gr.Column(scale=2):
95
- gr.Markdown("### 🔍 ابدأ تحليل موقعك الآن")
96
 
97
- website_url = gr.Textbox(
98
  label="رابط الموقع",
99
- placeholder="https://example.com",
100
- info="أدخل رابط موقعك للحصول على تحليل شامل"
101
  )
102
 
103
- org_name = gr.Textbox(
104
- label="اسم الشركة/المؤسسة",
105
  placeholder="اسم شركتك"
106
  )
107
 
108
- max_pages = gr.Slider(
109
  minimum=10,
110
  maximum=100,
111
  value=50,
112
  step=10,
113
- label="عدد الصفحات للتحليل",
114
- info="كلما زاد العدد، كان التحليل أكثر شمولاً"
115
  )
116
 
117
- analyze_btn = gr.Button("🚀 ابدأ التحليل", variant="primary", size="lg")
118
 
119
  with gr.Column(scale=1):
120
- gr.Markdown(
121
- """
122
- ### 📊 ماذا ستحصل؟
123
-
124
- ✅ تحليل SEO شامل
125
- ✅ تقييم GEO Score
126
- استخراج الكلمات المفتاحية
127
- ✅ تحليل المحتوى
128
- ✅ توصيات قابلة للتنفيذ
129
- ✅ JSON-LD Schema
130
-
131
- ---
132
-
133
- ### 🌐 الوصول الكامل
134
-
135
- للوصول إلى لوحة التحكم الكاملة:
136
-
137
- 👉 [افتح لوحة التحكم](/app/portal.html)
138
-
139
- 👉 [الصفحة الرئيسية](/app/index.html)
140
-
141
- 👉 [API Docs](/api/docs)
142
-
143
- 👉 [Login Debug](/app/login-debug.html)
144
- """
145
- )
146
-
147
- with gr.Row():
148
- output_status = gr.Textbox(
149
- label="حالة التحليل",
150
- interactive=False,
151
- lines=3
152
- )
153
 
154
- with gr.Row():
155
- output_json = gr.JSON(label="نتائج التحليل")
156
 
157
- def analyze_website(url, name, pages):
158
- """Analyze website and return results"""
159
  if not url or not url.startswith('http'):
160
- return "❌ الرجاء إدخال رابط صحيح يبدأ بـ http:// أو https://", None
161
 
162
  try:
163
  import requests
164
-
165
- # Call the API
166
  response = requests.post(
167
- f"http://{HOST}:{PORT}/api/jobs",
168
  json={
169
  "url": url,
170
- "org_name": name or "Unknown",
171
  "org_url": url,
172
  "max_pages": int(pages),
173
  "runs": 1
@@ -179,51 +163,35 @@ def create_gradio_interface():
179
  data = response.json()
180
  if data.get("ok"):
181
  job_id = data.get("job_id")
182
- return f"✅ تم إنشاء التحليل بنجاح!\n\nJob ID: {job_id}\n\nيمكنك متابعة التقدم من لوحة التحكم", data
183
- else:
184
- return f"❌ خطأ: {data.get('error', 'Unknown error')}", None
185
- else:
186
- return f"❌ خطأ في الاتصال: {response.status_code}", None
187
-
188
  except Exception as e:
189
- return f"❌ حدث خطأ: {str(e)}", None
190
 
191
  analyze_btn.click(
192
- fn=analyze_website,
193
- inputs=[website_url, org_name, max_pages],
194
- outputs=[output_status, output_json]
195
  )
196
 
197
- gr.Markdown(
198
- """
199
- ---
200
-
201
- ### 📚 الوثائق والموارد
202
-
203
- - [دليل الاستخدام](https://github.com/moharek/geo-platform)
204
- - [API Documentation](/api/docs)
205
- - [تواصل معنا](mailto:hello@moharek.com)
206
-
207
- ---
208
-
209
- © 2025 محرك — Moharek GEO Platform | Search Growth System
210
- """
211
- )
212
 
213
  return demo
214
 
215
  # Main execution
216
  if __name__ == "__main__":
217
- print("🚀 Starting Moharek GEO Platform on Hugging Face Space...")
218
- print(f"🌐 Server will be available at http://{HOST}:{PORT}")
219
-
220
- # Create Gradio interface
221
- demo = create_gradio_interface()
222
 
223
- # Mount Gradio at root
224
  app = gr.mount_gradio_app(fastapi_app, demo, path="/")
225
 
226
- # Run the combined app
227
  uvicorn.run(
228
  app,
229
  host=HOST,
 
1
  """
2
  Moharek GEO Platform - Hugging Face Space
3
+ Complete integration of FastAPI backend + Gradio frontend
4
  """
5
 
6
  import os
7
  import sys
8
  from pathlib import Path
9
 
10
+ # Add paths
11
  sys.path.insert(0, str(Path(__file__).parent))
12
 
13
  import gradio as gr
14
  import uvicorn
 
15
  from fastapi.staticfiles import StaticFiles
16
+ from fastapi.responses import FileResponse
17
 
18
+ # Import the main FastAPI app
19
  from server.api import app as fastapi_app
20
 
21
  # Configuration
22
+ PORT = int(os.environ.get("PORT", 7860))
23
  HOST = "0.0.0.0"
24
 
25
+ print("🚀 Moharek GEO Platform Starting...")
26
+ print(f"📍 Working directory: {Path.cwd()}")
27
+ print(f"🌐 Server: http://{HOST}:{PORT}")
28
+
29
+ # Mount frontend files at /app prefix
30
  frontend_path = Path(__file__).parent / "frontend"
31
  if frontend_path.exists():
32
+ print(f"📁 Frontend path: {frontend_path}")
33
+
34
+ # Mount static files
35
+ fastapi_app.mount("/frontend", StaticFiles(directory=str(frontend_path)), name="frontend_static")
36
 
37
+ # Serve frontend pages at /app/*
38
  @fastapi_app.get("/app/")
39
+ async def serve_app_index():
40
  return FileResponse(str(frontend_path / "index.html"))
41
 
42
+ @fastapi_app.get("/app/{page}")
43
+ async def serve_app_page(page: str):
44
+ # Handle both .html and without extension
45
+ if not page.endswith('.html'):
46
+ page = page + '.html'
47
+
48
+ file_path = frontend_path / page
49
  if file_path.exists():
50
  return FileResponse(str(file_path))
51
+
52
+ return {"error": "Page not found"}, 404
 
 
 
53
 
54
+ # Serve assets
55
+ @fastapi_app.get("/{filename}")
56
+ async def serve_assets(filename: str):
57
+ # Serve CSS, JS, SVG, etc from frontend root
58
+ if any(filename.endswith(ext) for ext in ['.css', '.js', '.svg', '.png', '.jpg', '.webp']):
59
+ file_path = frontend_path / filename
60
+ if file_path.exists():
61
+ return FileResponse(str(file_path))
62
+ return {"error": "Not found"}, 404
63
+
64
+ # Create Gradio interface
65
+ def create_gradio_ui():
66
  with gr.Blocks(
67
  title="Moharek GEO Platform",
68
+ theme=gr.themes.Soft(primary_hue="teal", secondary_hue="green"),
 
 
 
69
  css="""
70
  .gradio-container {
71
  background: linear-gradient(135deg, #071f21 0%, #0F4246 100%);
 
75
  background: linear-gradient(135deg, #c8f04e, #a8d630) !important;
76
  color: #071f21 !important;
77
  font-weight: 900 !important;
 
 
 
 
 
78
  }
79
  """
80
  ) as demo:
81
+ gr.Markdown("""
82
+ # 🚀 محرك — Moharek GEO Platform
83
 
84
+ ## منصة تحسين محركات البحث بالذكاء الاصطناعي
85
+
86
+ **Search Growth System** — 5 محركات متكاملة
87
+
88
+ ---
89
+
90
+ ### 🎯 الميزات الرئيسية:
91
+
92
+ - 📈 **SEO Engine** — تحسين محركات البحث
93
+ - 🤖 **AI Visibility Engine** — الظهور في ChatGPT
94
+ - 🎯 **Ads Engine** — إدارة الإعلانات
95
+ - 📝 **Content Engine** — إنشاء المحتوى
96
+ - **Trust Engine** — بناء الثقة
97
+ """)
 
 
 
 
 
 
 
98
 
99
  with gr.Row():
100
  with gr.Column(scale=2):
101
+ gr.Markdown("### 🔍 ابدأ التحليل")
102
 
103
+ url_input = gr.Textbox(
104
  label="رابط الموقع",
105
+ placeholder="https://example.com"
 
106
  )
107
 
108
+ org_input = gr.Textbox(
109
+ label="اسم الشركة",
110
  placeholder="اسم شركتك"
111
  )
112
 
113
+ pages_slider = gr.Slider(
114
  minimum=10,
115
  maximum=100,
116
  value=50,
117
  step=10,
118
+ label="عدد الصفحات"
 
119
  )
120
 
121
+ analyze_btn = gr.Button("🚀 ابدأ التحليل", variant="primary")
122
 
123
  with gr.Column(scale=1):
124
+ gr.Markdown("""
125
+ ### 📊 ماذا ستحصل؟
126
+
127
+ ✅ تحليل SEO شامل
128
+ ✅ تقييم GEO Score
129
+ استخراج الكلمات المفتاحية
130
+ ✅ توصيات قابلة للتنفيذ
131
+
132
+ ---
133
+
134
+ ### 🌐 الوصول الكامل
135
+
136
+ 👉 [لوحة التحكم](/app/portal.html)
137
+ 👉 [تسجيل الدخول](/app/login.html)
138
+ 👉 [API Docs](/api/docs)
139
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
+ status_output = gr.Textbox(label="الحالة", interactive=False, lines=3)
142
+ json_output = gr.JSON(label="النتائج")
143
 
144
+ def analyze(url, org, pages):
 
145
  if not url or not url.startswith('http'):
146
+ return "❌ الرجاء إدخال رابط صحيح", None
147
 
148
  try:
149
  import requests
 
 
150
  response = requests.post(
151
+ f"http://localhost:{PORT}/api/jobs",
152
  json={
153
  "url": url,
154
+ "org_name": org or "Unknown",
155
  "org_url": url,
156
  "max_pages": int(pages),
157
  "runs": 1
 
163
  data = response.json()
164
  if data.get("ok"):
165
  job_id = data.get("job_id")
166
+ return f"✅ تم إنشاء التحليل!\n\nJob ID: {job_id}", data
167
+ return f"❌ خطأ: {data.get('error')}", None
168
+ return f"❌ خطأ: {response.status_code}", None
 
 
 
169
  except Exception as e:
170
+ return f"❌ خطأ: {str(e)}", None
171
 
172
  analyze_btn.click(
173
+ fn=analyze,
174
+ inputs=[url_input, org_input, pages_slider],
175
+ outputs=[status_output, json_output]
176
  )
177
 
178
+ gr.Markdown("""
179
+ ---
180
+
181
+ © 2025 محرك — Moharek GEO Platform
182
+ """)
 
 
 
 
 
 
 
 
 
 
183
 
184
  return demo
185
 
186
  # Main execution
187
  if __name__ == "__main__":
188
+ print(" Creating Gradio interface...")
189
+ demo = create_gradio_ui()
 
 
 
190
 
191
+ print("✅ Mounting Gradio to FastAPI...")
192
  app = gr.mount_gradio_app(fastapi_app, demo, path="/")
193
 
194
+ print("✅ Starting server...")
195
  uvicorn.run(
196
  app,
197
  host=HOST,
entrypoint.sh CHANGED
@@ -1,168 +1,17 @@
1
  #!/bin/bash
2
-
3
- # Startup initialization script for Hugging Face
4
  set -e
5
 
6
- echo "🚀 Initializing Moharek GEO Platform..."
7
-
8
- # Create directories
9
- mkdir -p output
10
- mkdir -p frontend
11
- mkdir -p server
12
- mkdir -p src
13
-
14
- # Initialize databases
15
- python3 << 'PYEOF'
16
- import sqlite3
17
- from pathlib import Path
18
- import sys
19
-
20
- try:
21
- output_dir = Path('output')
22
- output_dir.mkdir(exist_ok=True)
23
-
24
- # Jobs database
25
- conn = sqlite3.connect(str(output_dir / 'jobs.db'))
26
- conn.execute("""CREATE TABLE IF NOT EXISTS jobs (
27
- id INTEGER PRIMARY KEY AUTOINCREMENT,
28
- url TEXT NOT NULL,
29
- org_name TEXT,
30
- org_url TEXT,
31
- max_pages INTEGER DEFAULT 3,
32
- runs INTEGER DEFAULT 1,
33
- status TEXT DEFAULT 'pending',
34
- progress TEXT DEFAULT '{}',
35
- result_path TEXT,
36
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
37
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
38
- )""")
39
- conn.commit()
40
- conn.close()
41
-
42
- # Users database
43
- conn = sqlite3.connect(str(output_dir / 'users.db'))
44
- conn.execute("""CREATE TABLE IF NOT EXISTS users (
45
- id INTEGER PRIMARY KEY AUTOINCREMENT,
46
- email TEXT UNIQUE NOT NULL,
47
- password_hash TEXT NOT NULL,
48
- role TEXT DEFAULT 'user',
49
- company_id INTEGER,
50
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
51
- )""")
52
- conn.commit()
53
- conn.close()
54
-
55
- # Projects database
56
- conn = sqlite3.connect(str(output_dir / 'projects.db'))
57
- conn.execute("""CREATE TABLE IF NOT EXISTS projects (
58
- id INTEGER PRIMARY KEY AUTOINCREMENT,
59
- user_id INTEGER,
60
- name TEXT NOT NULL,
61
- url TEXT NOT NULL,
62
- industry TEXT,
63
- color TEXT DEFAULT '#3b82f6',
64
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
65
- )""")
66
- conn.execute("""CREATE TABLE IF NOT EXISTS project_snapshots (
67
- id INTEGER PRIMARY KEY AUTOINCREMENT,
68
- project_id INTEGER,
69
- job_id INTEGER,
70
- geo_score INTEGER,
71
- seo_score INTEGER,
72
- ai_visibility INTEGER,
73
- pages_crawled INTEGER,
74
- keywords_count INTEGER,
75
- snapshot_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
76
- )""")
77
- conn.commit()
78
- conn.close()
79
-
80
- # Clients database
81
- conn = sqlite3.connect(str(output_dir / 'clients.db'))
82
- conn.execute("""CREATE TABLE IF NOT EXISTS client_tokens (
83
- id INTEGER PRIMARY KEY AUTOINCREMENT,
84
- token TEXT UNIQUE NOT NULL,
85
- job_id INTEGER NOT NULL,
86
- client_email TEXT,
87
- owner_user_id INTEGER,
88
- expires_at TIMESTAMP,
89
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
90
- )""")
91
- conn.commit()
92
- conn.close()
93
-
94
- # Payments database
95
- conn = sqlite3.connect(str(output_dir / 'payments.db'))
96
- conn.execute("""CREATE TABLE IF NOT EXISTS subscriptions (
97
- id INTEGER PRIMARY KEY AUTOINCREMENT,
98
- user_id INTEGER NOT NULL UNIQUE,
99
- plan TEXT NOT NULL DEFAULT 'free',
100
- stripe_customer_id TEXT,
101
- stripe_subscription_id TEXT,
102
- status TEXT DEFAULT 'active',
103
- current_period_start TIMESTAMP,
104
- current_period_end TIMESTAMP,
105
- cancel_at_period_end BOOLEAN DEFAULT 0,
106
- trial_end TIMESTAMP,
107
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
108
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
109
- )""")
110
- conn.execute("""CREATE TABLE IF NOT EXISTS usage (
111
- id INTEGER PRIMARY KEY AUTOINCREMENT,
112
- user_id INTEGER NOT NULL,
113
- resource TEXT NOT NULL,
114
- count INTEGER DEFAULT 1,
115
- period_start TIMESTAMP NOT NULL,
116
- period_end TIMESTAMP NOT NULL,
117
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
118
- )""")
119
- conn.execute("""CREATE TABLE IF NOT EXISTS payments (
120
- id INTEGER PRIMARY KEY AUTOINCREMENT,
121
- user_id INTEGER NOT NULL,
122
- stripe_payment_id TEXT,
123
- amount INTEGER NOT NULL,
124
- currency TEXT DEFAULT 'usd',
125
- status TEXT DEFAULT 'pending',
126
- description TEXT,
127
- invoice_url TEXT,
128
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
129
- )""")
130
- conn.execute("""CREATE TABLE IF NOT EXISTS invoices (
131
- id INTEGER PRIMARY KEY AUTOINCREMENT,
132
- user_id INTEGER NOT NULL,
133
- stripe_invoice_id TEXT,
134
- amount_due INTEGER,
135
- amount_paid INTEGER,
136
- currency TEXT DEFAULT 'usd',
137
- status TEXT,
138
- invoice_pdf TEXT,
139
- period_start TIMESTAMP,
140
- period_end TIMESTAMP,
141
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
142
- )""")
143
- conn.commit()
144
- conn.close()
145
-
146
- # Create JSON files
147
- for fname in ['audit.json', 'analysis.json', 'recommendations.json']:
148
- fpath = output_dir / fname
149
- if not fpath.exists():
150
- fpath.write_text('{}')
151
-
152
- history_path = output_dir / 'history.json'
153
- if not history_path.exists():
154
- history_path.write_text('[]')
155
 
156
- print("✅ Databases and files initialized")
157
- except Exception as e:
158
- print(f"❌ Database init error: {e}")
159
- import traceback
160
- traceback.print_exc()
161
- sys.exit(1)
162
- PYEOF
163
 
164
- echo "✅ Initialization complete"
165
- echo "🚀 Starting FastAPI server on port 7860..."
 
166
 
167
- # Start the server with error handling
168
- exec python3 -m uvicorn server.api:app --host 0.0.0.0 --port 7860 --log-level info
 
 
1
  #!/bin/bash
 
 
2
  set -e
3
 
4
+ echo "===== Moharek GEO Platform Startup ====="
5
+ echo "Working directory: $(pwd)"
6
+ echo "Python version: $(python --version)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
+ # Create output directory
9
+ mkdir -p /app/output
 
 
 
 
 
10
 
11
+ # Initialize database
12
+ echo "Initializing database..."
13
+ python -c "from server.users import init_db; init_db()" || true
14
 
15
+ # Start the application
16
+ echo "Starting application..."
17
+ exec python app.py