From 34c671f9f32f0b3fa6dbc71d2fdef41860056142 Mon Sep 17 00:00:00 2001 From: Hera Zhao Date: Mon, 6 Apr 2026 21:40:58 +0000 Subject: [PATCH] Fix SPA routing: fallback to index.html for Vue Router paths Direct navigation to /bugs, /oils, /manage etc. returned 404 because FastAPI's StaticFiles only served index.html for /. Now all non-API, non-asset routes return index.html so Vue Router handles client-side routing. Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/main.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/main.py b/backend/main.py index d9e0e0b..3ac3bd5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1494,4 +1494,18 @@ def startup(): seed_defaults(data["oils_meta"], data["recipes"]) if os.path.isdir(FRONTEND_DIR): - app.mount("/", StaticFiles(directory=FRONTEND_DIR, html=True), name="frontend") + # Serve static assets (js/css/images) directly + app.mount("/assets", StaticFiles(directory=os.path.join(FRONTEND_DIR, "assets")), name="assets") + app.mount("/public", StaticFiles(directory=FRONTEND_DIR), name="public") + + # SPA fallback: any non-API, non-asset route returns index.html + from fastapi.responses import FileResponse + + @app.get("/{path:path}") + async def spa_fallback(path: str): + # Serve actual files if they exist (favicon, icons, etc.) + file_path = os.path.join(FRONTEND_DIR, path) + if os.path.isfile(file_path): + return FileResponse(file_path) + # Otherwise return index.html for Vue Router + return FileResponse(os.path.join(FRONTEND_DIR, "index.html"))