How the FastAPI Application Is Mounted with an Optional Frontend in NekoImageGallery
The NekoImageGallery server uses the config.with_frontend boolean to conditionally prefix all API routes with /api and mount a React ASGI application at the root path, enabling seamless dual-mode deployment from a single codebase.
The hv0905/nekoimagegallery repository provides a unified deployment architecture where the same FastAPI backend can run standalone or serve a bundled React frontend. This behavior is controlled by the with_frontend configuration flag defined in app/config.py, which triggers dynamic route prefixing and conditional ASGI mounting logic in app/webapp.py.
Configuring the Frontend Toggle
The deployment mode is determined at runtime by the with_frontend setting in app/config.py. When set to True, the application prepares to serve both the API and the frontend; when False (the default), it operates as a pure API server without loading frontend assets.
Dynamic API Prefix Routing
In app/webapp.py at line 36, the application calculates a dynamic prefix based on the configuration value:
api_prefix = '/api' if config.with_frontend else ''
This api_prefix variable is injected into the FastAPI constructor at lines 36–45, ensuring that OpenAPI documentation and all endpoints shift accordingly:
app = FastAPI(
lifespan=lifespan,
title=app.__title__,
description=app.__description__,
version=app.__version__,
openapi_url=f"{api_prefix}/openapi.json",
docs_url=f"{api_prefix}/docs",
redoc_url=f"{api_prefix}/redoc",
)
When the frontend is enabled, API documentation moves to /api/docs and the interactive API explorer is accessible at /api/redoc; otherwise, these remain at the root /docs and /redoc paths.
Serving Static Files with Prefixed Routes
For local storage backends, static file serving respects the same api_prefix. Lines 64–68 of app/webapp.py mount the static directory under the calculated prefix:
if config.storage.method == "local":
app.mount(
api_prefix + "/static",
StaticFiles(directory=pathlib.Path(config.storage.local.path), check_dir=False),
name="static",
)
This ensures static assets remain accessible under /static or /api/static depending on the deployment mode, preventing broken image links when the frontend is active.
Mounting the Optional React Frontend
The optional frontend mounting occurs at lines 92–96 of app/webapp.py. When config.with_frontend is True, the server imports the compiled React ASGI application from neko_image_gallery_app and mounts it at the root path:
if config.with_frontend:
from neko_image_gallery_app import asgi_app as frontend_app
app.mount("/", frontend_app, name="frontend")
This makes the React interface available at http://host:port/ while the API operates under /api, preventing route collisions and allowing the frontend to handle client-side routing independently.
Application Entry Point
The command-line interface in main.py launches the server using Uvicorn at line 60:
uvicorn.run("app.webapp:app", host=host, port=port, root_path=root_path)
This entry point initializes the configured app object from app/webapp.py, applying all conditional mounts and prefixes defined above without requiring modifications to the startup command.
Deployment Modes
The same codebase operates in two distinct modes based on the configuration:
- API-Only Mode (
with_frontend=False): All routes mount at/, OpenAPI docs are at/docs, and no frontend assets are served. - Full-Stack Mode (
with_frontend=True): API routes are prefixed with/api, docs move to/api/docs, and the React app handles requests at/.
Summary
- The
config.with_frontendflag inapp/config.pycontrols dual-mode deployment behavior. - When enabled,
api_prefixbecomes/api, shifting all API routes and documentation under/apito avoid conflicts with the frontend. - The React frontend is conditionally mounted at
/viaapp.mount()only whenwith_frontendisTrue. - Static files for local storage backends automatically respect the dynamic
api_prefixto ensure consistent asset delivery. - The Uvicorn entry point in
main.pystarts the configured application without requiring code changes between deployment modes.
Frequently Asked Questions
How does the API prefix change when the frontend is enabled?
When config.with_frontend is set to True, the api_prefix variable is set to /api in app/webapp.py, causing all API endpoints, OpenAPI schemas, and automatic documentation to be served under /api. In standalone API mode, the prefix is an empty string, placing routes at the root /.
Where is the React frontend mounted when enabled?
The React frontend is mounted at the root path / using app.mount("/", frontend_app, name="frontend") in app/webapp.py at lines 92–96. This only occurs when config.with_frontend is True, allowing the frontend to serve the initial HTML while the API handles requests at /api.
Can I run the API without the frontend?
Yes, by default with_frontend is False, and the FastAPI application runs as a pure API backend with all routes mounted at the root. No frontend code from neko_image_gallery_app is imported or executed in this configuration.
How are the OpenAPI documentation URLs affected by the frontend setting?
The docs_url, redoc_url, and openapi_url parameters in the FastAPI constructor use formatted strings with api_prefix. When the frontend is enabled, documentation moves to /api/docs, /api/redoc, and /api/openapi.json respectively. In API-only mode, these remain at the standard /docs, /redoc, and /openapi.json paths.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →