SignalWatch / app.py
nehal's picture
Fix HF port conflict: let platform Gradio runtime serve merged app (no manual uvicorn)
271b903
Raw History Blame Contribute Delete
2.01 kB
"""Hugging Face Gradio Space entrypoint for SignalWatch.
HF free tier only supports the Gradio SDK. We merge our FastAPI backend (live
simulator, anomaly scoring, alerts) and the built React dashboard into a single
app, then let the platform's Gradio runtime serve it — no manual uvicorn, so
there is no port conflict.
"""
import os
import sys
from pathlib import Path
SPACE_ROOT = Path(__file__).parent
BACKEND_DIR = SPACE_ROOT / "backend"
STATIC_DIR = SPACE_ROOT / "static"
sys.path.insert(0, str(BACKEND_DIR))
os.chdir(BACKEND_DIR)
import gradio as gr # noqa: E402
from starlette.responses import FileResponse, JSONResponse # noqa: E402
from starlette.staticfiles import StaticFiles # noqa: E402
from starlette.exceptions import HTTPException as StarletteHTTPException # noqa: E402
from main import app # noqa: E402 FastAPI app with all /api routes + lifespan
# ---- Serve the built React dashboard ------------------------------
app.mount("/assets", StaticFiles(directory=str(STATIC_DIR / "assets")), name="assets")
@app.get("/", include_in_schema=False)
async def index():
return FileResponse(STATIC_DIR / "index.html")
@app.exception_handler(StarletteHTTPException)
async def spa_fallback(request, exc):
p = request.url.path
if exc.status_code == 404 and not p.startswith("/api") and not p.startswith("/gradio"):
if (STATIC_DIR / "index.html").exists():
return FileResponse(STATIC_DIR / "index.html")
return JSONResponse({"detail": "Not Found"}, status_code=404)
# ---- Gradio Blocks -------------------------------------------------
# Exists to satisfy the SDK; the real UI is the React SPA served at /.
with gr.Blocks(title="SignalWatch") as demo:
gr.Markdown("# 📡 SignalWatch")
gr.HTML(
'<p style="font-family:Inter,sans-serif;color:#94a3b8">'
"Loading SignalWatch dashboard…</p>"
)
# Merge: Gradio serves everything (its own /gradio + our / and /api).
app = gr.mount_gradio_app(app, demo, path="/gradio")