feat: serve the built Vue SPA from Quart with history-mode fallback

The frontend blueprint is registered after the api blueprint so /api/*
routes are matched first; everything else falls through to the SPA.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 07:36:16 -04:00
parent bcd9a23501
commit 8e61dc4df4
2 changed files with 20 additions and 0 deletions
+3
View File
@@ -6,6 +6,7 @@ from quart import Quart
from .api import api_bp
from .config import get_config
from .frontend import frontend_bp
def create_app() -> Quart:
@@ -15,5 +16,7 @@ def create_app() -> Quart:
app = Quart(__name__)
app.secret_key = cfg.secret_key
app.register_blueprint(api_bp)
# Registered last so /api/* routes win over the SPA catch-all.
app.register_blueprint(frontend_bp)
return app
+17
View File
@@ -0,0 +1,17 @@
"""Serves the built Vue SPA from frontend/dist/ with history-mode fallback."""
from pathlib import Path
from quart import Blueprint, send_from_directory
FRONTEND_DIST = Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"
frontend_bp = Blueprint("frontend", __name__)
@frontend_bp.route("/")
@frontend_bp.route("/<path:subpath>")
async def serve_spa(subpath: str = ""):
if subpath and (FRONTEND_DIST / subpath).is_file():
return await send_from_directory(FRONTEND_DIST, subpath)
return await send_from_directory(FRONTEND_DIST, "index.html")