diff --git a/packages/server/src/notify_bridge_server/main.py b/packages/server/src/notify_bridge_server/main.py index d22b06a..3aebdaa 100644 --- a/packages/server/src/notify_bridge_server/main.py +++ b/packages/server/src/notify_bridge_server/main.py @@ -158,7 +158,27 @@ async def health(): from pathlib import Path if _cfg.static_dir and Path(_cfg.static_dir).is_dir(): from fastapi.staticfiles import StaticFiles - app.mount("/", StaticFiles(directory=_cfg.static_dir, html=True), name="frontend") + from starlette.responses import FileResponse + from starlette.exceptions import HTTPException as StarletteHTTPException + + _static_dir = Path(_cfg.static_dir) + + class SPAStaticFiles(StaticFiles): + """StaticFiles that falls back to index.html for SvelteKit client-side routes. + + Unknown paths return index.html so that deep links like /settings + hydrate the SPA, while /api/* and real asset 404s behave normally. + """ + + async def get_response(self, path: str, scope): + try: + return await super().get_response(path, scope) + except StarletteHTTPException as exc: + if exc.status_code == 404 and not path.startswith("api/"): + return FileResponse(_static_dir / "index.html") + raise + + app.mount("/", SPAStaticFiles(directory=_cfg.static_dir, html=True), name="frontend") def run():