The Problem
API documentation drift is a persistent maintenance burden. Teams build endpoints but keep documentation in sync through manual effort, leading to outdated specs, mismatched expectations, and onboarding friction. FastAPI Voyager addresses this by auto-generating an interactive visual graph from your running code, eliminating the gap between implementation and documentation.
What This Does
FastAPI Voyager introspects a running FastAPI, Django Ninja, or Litestar application and renders an interactive graph of endpoints, models, and relationships. The Python core lives in src/fastapi_voyager/ (57 files), with adapters for each framework: fastapi_adapter.py, django_ninja_adapter.py, and litestar_adapter.py. The Vue front-end at web/vue-main (Ca 0, Ce 6) consumes the generated DOT output. A call graph analysis runs through cli.py → generate_visualization → load_app_from_module, then delegates to the appropriate adapter. Each adapter calls into introspectors/ (FastAPI, Django Ninja, Litestar) to extract route metadata, which flows through type_helper.py (19 functions) to normalize types into a shared schema. The result is rendered via render.py (19 functions) into DOT format, consumed by the JavaScript front-end for display.
How It Is Wired
Execution starts at src/fastapi_voyager/cli.py:151 (main), which reaches 81 functions and is called from 1 place. The graph analysis path is: main → load_app_from_module → _get_adapter → adapter-specific introspection → analysis_schemas → full_class_name (called 12 times from analysis_schemas) → add_to_node_set / add_to_link_set → render_template (called 11 places) → render_dot. The most connected module is src/fastapi_voyager/web/vue-main with 6 outgoing edges and no incoming imports from this repo, making it a leaf consumer. The call graph has 269 resolved edges between internal functions; get_core_types is the most widely called function (14 call sites). Execution does not leave the process except through filesystem reads in adapter setup scripts; no outbound network calls are traced from source.
How To Use It
Setup: Install the package:
uv add fastapi-voyager
Or via pip:
pip install fastapi-voyager
Configuration: Create a FastAPI app and mount the voyager instance. Required config includes module_prefix and module_color dict; ga_id for analytics. Example from the codebase:
from fastapi import FastAPI
from fastapi_voyager import create_voyager
app = FastAPI()
@app.get("/hello")
def hello():
return {"message": "Hello World"}
app.mount("/voyager", create_voyager(
app,
module_color={"src.services": "tomato"},
module_prefix="src.services",
swagger_url="/docs",
ga_id="G-XXXXXXXXVL",
initial_page_policy="first",
enable_pydantic_resolve_meta=True))
Running it: Start your app with uvicorn, then visit http://localhost:8000/voyager. For CLI-driven generation:
voyager -m path.to.your.app.module --server
Framework-specific wiring is in src/fastapi_voyager/adapters/. Django Ninja and Litestar follow the same create_voyager entry point but pass their own API instances.
Real-World Use
In a micro-service architecture with composition-oriented development, Voyager can be mounted alongside your API surface. For example, an orchestration layer can import create_voyager from each sub-application and mount them under a single /voyager path, providing a unified view across services. The tests/service/schema/ directory demonstrates schema introspection for entity resolution, and the tests/fastapi/demo.py defines sample routes (get_sprints, post_fullname) that Voyager would render as nodes and edges.
Code Health & Issues
- HIGH - Pin third-party GitHub Actions to commit SHA:
.github/workflowsusesastral-sh/setup-uv@v4andsoftprops/action-gh-release@v2without commit pins; a tag move could execute unvetted code with repo secrets. - HIGH - Make CI invoke the test suite it has: 31 test files exist but no test command appears in any workflow; a green check that never runs assertions is worse than no check.
- MEDIUM - Enable Dependabot or Renovate: one manifest present, no update bot configured; published advisories go unpatched without automated bumps.
- MEDIUM - Gate pull requests on dependency vulnerability scan: no dependency scan in CI; a known-vulnerable package could reach production without detection.
- LOW - Set timeout-minutes on workflow jobs:
publish.ymldeclares no job timeout; a wedged step runs to the six-hour platform default.
The Bottom Line
The code offers a functional, well-structured introspection engine that successfully visualizes FastAPI, Django Ninja, and Litestar endpoints with minimal configuration. The internal call graph is resolvable and the entry points are clear. However, the duplication of setup scripts (134 repeated 6-line blocks across 19 files) and the unguarded GitHub Actions pins represent real maintenance risk. Teams comfortable with auto-generated docs who can action the dependency hygiene fixes will find immediate value; others may find the operational overhead of keeping introspections in sync with a evolving codebase non-trivial.