From 896d8e4ce201490504d6026e6ee37d1deba545d8 Mon Sep 17 00:00:00 2001 From: Junwei Zhao Date: Mon, 23 Feb 2026 21:18:12 +1100 Subject: [PATCH] Udate config for stats --- backend/app/main.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/backend/app/main.py b/backend/app/main.py index 6451fd9..5e63ba6 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -124,4 +124,24 @@ app.include_router(router, prefix="/api") # Serve frontend static files if they exist (production / Docker) static_dir = Path(__file__).resolve().parent.parent / "static" if static_dir.is_dir(): + # Catch-all SPA fallback: serve index.html for any non-API, non-asset path. + # This must be registered BEFORE the static mount so /backgrounds, /bookmarks, + # /stats etc. return 200 + index.html instead of 404. + from fastapi.responses import FileResponse as _FileResponse + import re as _re + + _ASSET_RE = _re.compile(r"\.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|map|json|webmanifest)$", _re.I) + + @app.get("/{full_path:path}", include_in_schema=False) + async def spa_fallback(full_path: str): + # Let actual static asset requests fall through to the mount below + if _ASSET_RE.search(full_path): + from starlette.responses import Response + return Response(status_code=404) + index = static_dir / "index.html" + if index.is_file(): + return _FileResponse(str(index)) + from starlette.responses import Response + return Response(status_code=404) + app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static")