Nagesh Muralidhar commited on
Commit
8f0bc94
·
1 Parent(s): 1bcce96

adding app.py

Browse files
Files changed (3) hide show
  1. Dockerfile +5 -1
  2. app.py +85 -39
  3. build_frontend.sh +224 -12
Dockerfile CHANGED
@@ -25,7 +25,7 @@ RUN npm install && \
25
  npm run build || \
26
  (echo "Frontend build failed, creating dummy build directory" && \
27
  mkdir -p build && \
28
- echo "<html><body><h1>PodCraft</h1><p>Frontend not built correctly. Please check logs.</p></body></html>" > build/index.html)
29
 
30
  # Return to app directory and install backend dependencies
31
  WORKDIR /app
@@ -35,6 +35,10 @@ RUN pip install --no-cache-dir -r requirements.txt
35
  RUN mkdir -p ./static && \
36
  cp -r frontend/podcraft/build/* ./static/ || echo "No frontend build files to copy"
37
 
 
 
 
 
38
  # Create directories for temp files
39
  RUN mkdir -p temp_audio temp
40
 
 
25
  npm run build || \
26
  (echo "Frontend build failed, creating dummy build directory" && \
27
  mkdir -p build && \
28
+ echo "<html><head><title>PodCraft</title></head><body><h1>PodCraft</h1><p>Frontend not built correctly. Please check logs.</p></body></html>" > build/index.html)
29
 
30
  # Return to app directory and install backend dependencies
31
  WORKDIR /app
 
35
  RUN mkdir -p ./static && \
36
  cp -r frontend/podcraft/build/* ./static/ || echo "No frontend build files to copy"
37
 
38
+ # Verify the static files were copied
39
+ RUN ls -la ./static && \
40
+ if [ -f "./static/index.html" ]; then echo "Frontend build found"; else echo "Frontend build not found"; fi
41
+
42
  # Create directories for temp files
43
  RUN mkdir -p temp_audio temp
44
 
app.py CHANGED
@@ -19,11 +19,25 @@ os.makedirs("./temp", exist_ok=True)
19
  os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout
20
  os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  try:
23
- # Set up CORS headers to allow frontend to access backend
24
  from backend.app.main import app
25
- from fastapi.middleware.cors import CORSMiddleware
26
-
27
  app.add_middleware(
28
  CORSMiddleware,
29
  allow_origins=["*"],
@@ -31,31 +45,59 @@ try:
31
  allow_methods=["*"],
32
  allow_headers=["*"],
33
  )
34
-
35
- # Serve static files from the frontend build directory
36
- from fastapi.staticfiles import StaticFiles
37
-
38
- # Check if static directory exists with index.html
39
- static_path = Path("./static")
40
- if static_path.exists() and (static_path / "index.html").exists():
41
- app.mount("/", StaticFiles(directory="./static", html=True), name="static")
42
-
43
- # For Hugging Face Spaces - expose the app
44
- if __name__ == "__main__":
45
- import uvicorn
46
-
47
- port = int(os.environ.get("PORT", 7860))
48
- host = os.environ.get("HOST", "0.0.0.0")
49
-
50
- logger.info(f"Starting server on {host}:{port}")
51
- uvicorn.run(app, host=host, port=port)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  except Exception as e:
54
- # If there's an error, create a minimal FastAPI app to show the error
55
- from fastapi import FastAPI
56
- from fastapi.responses import HTMLResponse
57
- from fastapi.staticfiles import StaticFiles
58
-
59
  error_app = FastAPI()
60
 
61
  @error_app.get("/", response_class=HTMLResponse)
@@ -79,23 +121,27 @@ except Exception as e:
79
  <p>Please check your environment variables and configuration.</p>
80
  <p>MongoDB URL format should be: <code>mongodb+srv://username:[email protected]/...</code></p>
81
  <p>API keys should be properly formatted and valid.</p>
 
 
 
82
  </div>
83
  </body>
84
  </html>
85
  """
86
 
87
- # Check if static directory exists with index.html
88
- static_path = Path("./static")
89
- if static_path.exists() and (static_path / "index.html").exists():
90
  error_app.mount("/static", StaticFiles(directory="./static"), name="static")
91
 
92
- if __name__ == "__main__":
93
- import uvicorn
94
-
95
- port = int(os.environ.get("PORT", 7860))
96
- host = os.environ.get("HOST", "0.0.0.0")
97
-
98
- logger.error(f"Application failed to start normally. Starting error app on {host}:{port}")
99
- logger.error(f"Error: {str(e)}")
100
-
101
- uvicorn.run(error_app, host=host, port=port)
 
 
 
19
  os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout
20
  os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout
21
 
22
+ # Create a FastAPI app - either the main one or an error one
23
+ from fastapi import FastAPI, Request
24
+ from fastapi.responses import HTMLResponse, JSONResponse
25
+ from fastapi.staticfiles import StaticFiles
26
+ from fastapi.middleware.cors import CORSMiddleware
27
+
28
+ # Check if static directory exists with index.html
29
+ static_path = Path("./static")
30
+ static_index_exists = static_path.exists() and (static_path / "index.html").exists()
31
+ logger.info(f"Static path exists: {static_path.exists()}")
32
+ if static_path.exists():
33
+ logger.info(f"Static directory contents: {os.listdir(static_path)}")
34
+ logger.info(f"Static index exists: {(static_path / 'index.html').exists()}")
35
+
36
  try:
37
+ # Try to import the main app
38
  from backend.app.main import app
39
+
40
+ # Add CORS middleware
41
  app.add_middleware(
42
  CORSMiddleware,
43
  allow_origins=["*"],
 
45
  allow_methods=["*"],
46
  allow_headers=["*"],
47
  )
48
+
49
+ # Add an index route to check if the API is accessible
50
+ @app.get("/api/status")
51
+ async def status():
52
+ return {"status": "ok", "message": "PodCraft API is running"}
53
+
54
+ # Override the root route to serve the frontend
55
+ @app.get("/", response_class=HTMLResponse)
56
+ async def read_root():
57
+ # If static files exist, return the index.html file
58
+ if static_index_exists:
59
+ with open(static_path / "index.html") as f:
60
+ return f.read()
61
+ else:
62
+ return """
63
+ <html>
64
+ <head>
65
+ <title>PodCraft API</title>
66
+ <style>
67
+ body { font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f8f9fa; }
68
+ .container { max-width: 800px; padding: 2rem; background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
69
+ h1 { color: #6366F1; }
70
+ pre { background-color: #f5f5f5; padding: 1rem; border-radius: 0.25rem; overflow: auto; }
71
+ </style>
72
+ </head>
73
+ <body>
74
+ <div class="container">
75
+ <h1>PodCraft API</h1>
76
+ <p>The PodCraft API is running, but the frontend static files were not found.</p>
77
+ <p>Static directory: <code>./static</code></p>
78
+ <p>Static directory exists: <code>{static_path.exists()}</code></p>
79
+ <p>If you need to access the API directly, you can use the following endpoints:</p>
80
+ <ul>
81
+ <li><code>/api/status</code> - Check API status</li>
82
+ <li><code>/docs</code> - API documentation</li>
83
+ </ul>
84
+ </div>
85
+ </body>
86
+ </html>
87
+ """
88
+
89
+ # Mount static files
90
+ if static_index_exists:
91
+ # Use the mount approach for static assets like CSS/JS, but not for the root path
92
+ logger.info("Mounting static files at /static")
93
+ app.mount("/static", StaticFiles(directory="./static"), name="static")
94
+
95
+ app_to_run = app
96
+ logger.info("Using main application")
97
 
98
  except Exception as e:
99
+ # If there's an error, create a minimal FastAPI app
100
+ logger.error(f"Error initializing main app: {str(e)}")
 
 
 
101
  error_app = FastAPI()
102
 
103
  @error_app.get("/", response_class=HTMLResponse)
 
121
  <p>Please check your environment variables and configuration.</p>
122
  <p>MongoDB URL format should be: <code>mongodb+srv://username:[email protected]/...</code></p>
123
  <p>API keys should be properly formatted and valid.</p>
124
+ <p>Static directory exists: <code>{static_path.exists()}</code></p>
125
+ {f"<p>Static directory contents: <code>{os.listdir(static_path)}</code></p>" if static_path.exists() else ""}
126
+ <p>Static index exists: <code>{static_index_exists}</code></p>
127
  </div>
128
  </body>
129
  </html>
130
  """
131
 
132
+ # Mount static files if they exist
133
+ if static_index_exists:
 
134
  error_app.mount("/static", StaticFiles(directory="./static"), name="static")
135
 
136
+ app_to_run = error_app
137
+ logger.info("Using error application")
138
+
139
+ # For Hugging Face Spaces - expose the app
140
+ if __name__ == "__main__":
141
+ import uvicorn
142
+
143
+ port = int(os.environ.get("PORT", 7860))
144
+ host = os.environ.get("HOST", "0.0.0.0")
145
+
146
+ logger.info(f"Starting server on {host}:{port}")
147
+ uvicorn.run(app_to_run, host=host, port=port)
build_frontend.sh CHANGED
@@ -8,7 +8,7 @@ set -e # Exit on error
8
  if [ -d "frontend/podcraft" ]; then
9
  echo "Frontend code already exists"
10
  else
11
- echo "Frontend code not found, creating dummy placeholder"
12
  mkdir -p frontend/podcraft/public
13
  mkdir -p frontend/podcraft/src
14
 
@@ -51,7 +51,8 @@ EOF
51
  <head>
52
  <meta charset="UTF-8" />
53
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
54
- <title>PodCraft</title>
 
55
  </head>
56
  <body>
57
  <div id="root"></div>
@@ -94,18 +95,78 @@ ReactDOM.createRoot(document.getElementById('root')).render(
94
  )
95
  EOF
96
 
97
- # Create a minimal App.jsx
98
  cat > frontend/podcraft/src/App.jsx << EOF
99
- import React from 'react'
100
  import './App.css'
101
 
102
  function App() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  return (
104
  <div className="App">
105
  <header className="App-header">
106
- <h1>PodCraft</h1>
107
- <p>Welcome to PodCraft API. This is the backend server for the PodCraft application.</p>
108
- <p>Please use the API endpoints to interact with the application.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  </header>
110
  </div>
111
  )
@@ -114,7 +175,7 @@ function App() {
114
  export default App
115
  EOF
116
 
117
- # Create minimal CSS files
118
  cat > frontend/podcraft/src/index.css << EOF
119
  body {
120
  margin: 0;
@@ -123,6 +184,12 @@ body {
123
  sans-serif;
124
  -webkit-font-smoothing: antialiased;
125
  -moz-osx-font-smoothing: grayscale;
 
 
 
 
 
 
126
  }
127
  EOF
128
 
@@ -132,18 +199,163 @@ EOF
132
  }
133
 
134
  .App-header {
135
- background-color: #282c34;
136
  min-height: 100vh;
137
  display: flex;
138
  flex-direction: column;
139
  align-items: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  justify-content: center;
141
- font-size: calc(10px + 2vmin);
142
- color: white;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
144
  EOF
145
 
146
- echo "Created dummy frontend code"
147
  fi
148
 
149
  # Make the script executable
 
8
  if [ -d "frontend/podcraft" ]; then
9
  echo "Frontend code already exists"
10
  else
11
+ echo "Frontend code not found, creating a fallback UI"
12
  mkdir -p frontend/podcraft/public
13
  mkdir -p frontend/podcraft/src
14
 
 
51
  <head>
52
  <meta charset="UTF-8" />
53
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
54
+ <title>PodCraft - AI Podcast Generator</title>
55
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
56
  </head>
57
  <body>
58
  <div id="root"></div>
 
95
  )
96
  EOF
97
 
98
+ # Create a minimal App.jsx with a more functional UI
99
  cat > frontend/podcraft/src/App.jsx << EOF
100
+ import React, { useState, useEffect } from 'react'
101
  import './App.css'
102
 
103
  function App() {
104
+ const [apiStatus, setApiStatus] = useState('checking')
105
+ const [mongoStatus, setMongoStatus] = useState('unknown')
106
+ const [apiMessage, setApiMessage] = useState('')
107
+
108
+ useEffect(() => {
109
+ // Check the API status
110
+ fetch('/api/status')
111
+ .then(response => response.json())
112
+ .then(data => {
113
+ setApiStatus('online')
114
+ setApiMessage(data.message || 'API is running')
115
+ })
116
+ .catch(error => {
117
+ setApiStatus('offline')
118
+ console.error('API Error:', error)
119
+ })
120
+ }, [])
121
+
122
  return (
123
  <div className="App">
124
  <header className="App-header">
125
+ <div className="logo">
126
+ <i className="fas fa-microphone-alt"></i>
127
+ <h1>PodCraft</h1>
128
+ </div>
129
+ <p className="tagline">AI-Powered Podcast Generator</p>
130
+
131
+ <div className="status-container">
132
+ <div className="status-card">
133
+ <div className="status-header">
134
+ <i className="fas fa-server"></i>
135
+ <h3>API Status</h3>
136
+ </div>
137
+ <div className="status-content">
138
+ <div className={`status-indicator \${apiStatus}`}>
139
+ {apiStatus === 'checking' ? 'Checking...' :
140
+ apiStatus === 'online' ? 'Online' : 'Offline'}
141
+ </div>
142
+ {apiMessage && <p className="status-message">{apiMessage}</p>}
143
+ </div>
144
+ </div>
145
+ </div>
146
+
147
+ <div className="features">
148
+ <div className="feature">
149
+ <i className="fas fa-robot"></i>
150
+ <h3>AI Debate</h3>
151
+ <p>Create engaging debates between AI personalities</p>
152
+ </div>
153
+ <div className="feature">
154
+ <i className="fas fa-podcast"></i>
155
+ <h3>Podcast Generation</h3>
156
+ <p>Convert debates into audio podcasts</p>
157
+ </div>
158
+ <div className="feature">
159
+ <i className="fas fa-cogs"></i>
160
+ <h3>Workflow Editor</h3>
161
+ <p>Customize the podcast creation process</p>
162
+ </div>
163
+ </div>
164
+
165
+ <div className="note">
166
+ <p>Note: This is a simplified UI for the application.</p>
167
+ <p>The full application UI is unavailable in this build.</p>
168
+ <p>API endpoints can still be accessed directly for testing.</p>
169
+ </div>
170
  </header>
171
  </div>
172
  )
 
175
  export default App
176
  EOF
177
 
178
+ # Create enhanced CSS files
179
  cat > frontend/podcraft/src/index.css << EOF
180
  body {
181
  margin: 0;
 
184
  sans-serif;
185
  -webkit-font-smoothing: antialiased;
186
  -moz-osx-font-smoothing: grayscale;
187
+ background-color: #1a1a2e;
188
+ color: #ffffff;
189
+ }
190
+
191
+ * {
192
+ box-sizing: border-box;
193
  }
194
  EOF
195
 
 
199
  }
200
 
201
  .App-header {
202
+ background-color: #0f0f1a;
203
  min-height: 100vh;
204
  display: flex;
205
  flex-direction: column;
206
  align-items: center;
207
+ justify-content: flex-start;
208
+ padding: 2rem;
209
+ }
210
+
211
+ .logo {
212
+ display: flex;
213
+ align-items: center;
214
+ margin-bottom: 1rem;
215
+ }
216
+
217
+ .logo i {
218
+ font-size: 3rem;
219
+ color: #6366F1;
220
+ margin-right: 1rem;
221
+ }
222
+
223
+ .logo h1 {
224
+ font-size: 3rem;
225
+ margin: 0;
226
+ background: linear-gradient(90deg, #6366F1, #8B5CF6);
227
+ -webkit-background-clip: text;
228
+ -webkit-text-fill-color: transparent;
229
+ }
230
+
231
+ .tagline {
232
+ font-size: 1.5rem;
233
+ margin-bottom: 3rem;
234
+ color: #94a3b8;
235
+ }
236
+
237
+ .status-container {
238
+ width: 100%;
239
+ max-width: 800px;
240
+ margin-bottom: 3rem;
241
+ }
242
+
243
+ .status-card {
244
+ background-color: #1e1e2d;
245
+ border-radius: 0.5rem;
246
+ padding: 1.5rem;
247
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
248
+ }
249
+
250
+ .status-header {
251
+ display: flex;
252
+ align-items: center;
253
+ margin-bottom: 1rem;
254
+ }
255
+
256
+ .status-header i {
257
+ font-size: 1.5rem;
258
+ color: #6366F1;
259
+ margin-right: 0.5rem;
260
+ }
261
+
262
+ .status-header h3 {
263
+ margin: 0;
264
+ font-size: 1.2rem;
265
+ }
266
+
267
+ .status-content {
268
+ display: flex;
269
+ flex-direction: column;
270
+ align-items: center;
271
+ }
272
+
273
+ .status-indicator {
274
+ padding: 0.5rem 1.5rem;
275
+ border-radius: 2rem;
276
+ font-weight: bold;
277
+ margin-bottom: 1rem;
278
+ }
279
+
280
+ .status-indicator.checking {
281
+ background-color: #374151;
282
+ color: #d1d5db;
283
+ }
284
+
285
+ .status-indicator.online {
286
+ background-color: #065f46;
287
+ color: #a7f3d0;
288
+ }
289
+
290
+ .status-indicator.offline {
291
+ background-color: #991b1b;
292
+ color: #fecaca;
293
+ }
294
+
295
+ .status-message {
296
+ font-style: italic;
297
+ color: #94a3b8;
298
+ }
299
+
300
+ .features {
301
+ display: flex;
302
+ flex-wrap: wrap;
303
  justify-content: center;
304
+ gap: 2rem;
305
+ margin-bottom: 3rem;
306
+ width: 100%;
307
+ max-width: 1000px;
308
+ }
309
+
310
+ .feature {
311
+ background-color: #1e1e2d;
312
+ border-radius: 0.5rem;
313
+ padding: 1.5rem;
314
+ width: 100%;
315
+ max-width: 300px;
316
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
317
+ transition: transform 0.3s ease;
318
+ }
319
+
320
+ .feature:hover {
321
+ transform: translateY(-5px);
322
+ }
323
+
324
+ .feature i {
325
+ font-size: 2.5rem;
326
+ color: #8B5CF6;
327
+ margin-bottom: 1rem;
328
+ }
329
+
330
+ .feature h3 {
331
+ margin: 0;
332
+ margin-bottom: 0.5rem;
333
+ font-size: 1.2rem;
334
+ }
335
+
336
+ .feature p {
337
+ margin: 0;
338
+ color: #94a3b8;
339
+ font-size: 0.9rem;
340
+ }
341
+
342
+ .note {
343
+ margin-top: 2rem;
344
+ padding: 1rem;
345
+ background-color: #1e1e2d;
346
+ border-radius: 0.5rem;
347
+ width: 100%;
348
+ max-width: 800px;
349
+ }
350
+
351
+ .note p {
352
+ margin: 0.5rem 0;
353
+ color: #94a3b8;
354
+ font-size: 0.9rem;
355
  }
356
  EOF
357
 
358
+ echo "Created fallback frontend code"
359
  fi
360
 
361
  # Make the script executable