Multi-tenant Claude Code monitoring dashboard. FastAPI + PostgreSQL + Docker + SSE real-time updates. Montserrat font, black/#FFC407 color scheme. Apache reverse proxy config at /cc-dashboard/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
from src.config import settings
|
|
from src.routers import admin, auth, dashboard, events, ingest, keys, projects
|
|
|
|
BASE = settings.BASE_PATH # "/cc-dashboard"
|
|
|
|
app = FastAPI(
|
|
title=settings.APP_TITLE,
|
|
docs_url=f"{BASE}/docs" if settings.DEBUG else None,
|
|
redoc_url=None,
|
|
root_path=BASE,
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# API routers
|
|
for router in [auth.router, keys.router, admin.router, ingest.router,
|
|
dashboard.router, events.router, projects.router]:
|
|
app.include_router(router)
|
|
|
|
# Static files — served at /cc-dashboard/static/
|
|
app.mount(f"{BASE}/static", StaticFiles(directory="src/static"), name="static")
|
|
|
|
# SPA fallback — serve index.html for all non-API routes
|
|
from fastapi.responses import FileResponse
|
|
from fastapi import Request
|
|
|
|
@app.get(f"{BASE}/", include_in_schema=False)
|
|
@app.get(f"{BASE}", include_in_schema=False)
|
|
async def spa_root():
|
|
return FileResponse("src/static/index.html")
|
|
|
|
|
|
@app.get(f"{BASE}/{{path:path}}", include_in_schema=False)
|
|
async def spa_fallback(path: str, request: Request):
|
|
# Don't catch API routes
|
|
if path.startswith("api/") or path.startswith("static/"):
|
|
from fastapi import HTTPException
|
|
raise HTTPException(status_code=404)
|
|
return FileResponse("src/static/index.html")
|