The web UI defines GET /docs (src/opal/web/routes.py, renders src/opal/web/templates/docs.html), but FastAPI's built-in Swagger UI registers /docs first in create_app() (src/opal/api/app.py — no docs_url override), so the app route never matches. The web docs template has been unreachable dead code the whole time; requests to /docs get the ~1KB Swagger stub.
Surfaced by the max-width survey during the parts UI work (the template was edited for centering before discovering nothing can render it).
Fix is a decision plus a few lines, either:
- Move the API docs aside —
FastAPI(docs_url="/api/docs", redoc_url=None) in create_app() — so the web docs page owns /docs, or
- Declare Swagger the intended occupant and delete the dead web route + template.
Either way: check nav/templates for links to /docs, and add a render test pinning whichever page owns the URL so it can't silently flip again.
🤖 Generated with Claude Code
The web UI defines
GET /docs(src/opal/web/routes.py, renders src/opal/web/templates/docs.html), but FastAPI's built-in Swagger UI registers/docsfirst increate_app()(src/opal/api/app.py — nodocs_urloverride), so the app route never matches. The web docs template has been unreachable dead code the whole time; requests to/docsget the ~1KB Swagger stub.Surfaced by the max-width survey during the parts UI work (the template was edited for centering before discovering nothing can render it).
Fix is a decision plus a few lines, either:
FastAPI(docs_url="/api/docs", redoc_url=None)increate_app()— so the web docs page owns/docs, orEither way: check nav/templates for links to
/docs, and add a render test pinning whichever page owns the URL so it can't silently flip again.🤖 Generated with Claude Code