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
|
||||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from .ws import DashboardBroadcaster, router as ws_router
|
||||
|
|
@ -61,10 +62,31 @@ def create_app() -> FastAPI:
|
|||
# WebSocket router (no prefix, path is /ws/live)
|
||||
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"
|
||||
index_html = static_dir / "index.html"
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue