mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-05-22 07:34:47 +02:00
fix(dashboard): SPA catch-all route for client-side routing
- Add catch-all route that serves index.html for any non-API path - Mount /assets separately for static JS/CSS files - Enables browser refresh on React Router paths (/mesh, /config, etc.) - API routes (/api/*) continue to work normally Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d52abb2572
commit
30dc0b75df
1 changed files with 25 additions and 3 deletions
|
|
@ -7,8 +7,9 @@ from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
from .ws import DashboardBroadcaster, router as ws_router
|
from .ws import DashboardBroadcaster, router as ws_router
|
||||||
|
|
@ -61,10 +62,31 @@ def create_app() -> FastAPI:
|
||||||
# WebSocket router (no prefix, path is /ws/live)
|
# WebSocket router (no prefix, path is /ws/live)
|
||||||
app.include_router(ws_router)
|
app.include_router(ws_router)
|
||||||
|
|
||||||
# Static files - mount LAST so /api routes take priority
|
# Static files setup for SPA
|
||||||
static_dir = Path(__file__).parent / "static"
|
static_dir = Path(__file__).parent / "static"
|
||||||
|
index_html = static_dir / "index.html"
|
||||||
|
|
||||||
if static_dir.exists():
|
if static_dir.exists():
|
||||||
app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static")
|
# Mount /assets for JS, CSS, images
|
||||||
|
assets_dir = static_dir / "assets"
|
||||||
|
if assets_dir.exists():
|
||||||
|
app.mount("/assets", StaticFiles(directory=str(assets_dir)), name="assets")
|
||||||
|
|
||||||
|
# SPA catch-all: serve index.html for any non-API, non-static path
|
||||||
|
# This enables React Router client-side routing
|
||||||
|
@app.get("/{path:path}")
|
||||||
|
async def spa_catch_all(request: Request, path: str):
|
||||||
|
# Let static files be served directly if they exist
|
||||||
|
file_path = static_dir / path
|
||||||
|
if file_path.is_file():
|
||||||
|
return FileResponse(file_path)
|
||||||
|
# Otherwise serve index.html for client-side routing
|
||||||
|
return FileResponse(index_html)
|
||||||
|
|
||||||
|
# Explicit root route
|
||||||
|
@app.get("/")
|
||||||
|
async def root():
|
||||||
|
return FileResponse(index_html)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue