Implementation:OpenHands OpenHands SPAStaticFiles Mount
| Knowledge Sources | |
|---|---|
| Domains | Server_Architecture, SaaS_Infrastructure |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Concrete tool for mounting a single-page application static file server with HTML5 history mode fallback at the root path, provided by the OpenHands enterprise server layer.
Description
The SPAStaticFiles mount is the final route registration in the SaaS server assembly. It uses the custom SPAStaticFiles class from the OpenHands server module, which extends Starlette's StaticFiles to add fallback behavior: when a requested path does not match any static file in the configured directory, the server returns index.html instead of a 404 response. The mount is registered at the root path (/) with html=True to enable automatic HTML content-type detection. Because this is a catch-all mount, it must be registered after all API routers to ensure that API endpoints take precedence. The directory parameter points to the built frontend assets directory containing the compiled SPA bundle.
Usage
Use this mount as the final step in SaaS server assembly after all API routers and middleware have been registered. The SPAStaticFiles class handles both serving static assets (JavaScript, CSS, images, fonts) and providing the HTML5 history mode fallback necessary for client-side routing to function correctly when users navigate directly to deep URLs.
Code Reference
Source Location
- Repository: OpenHands
- File: enterprise/saas_server.py:L130-140
Signature
app.mount(
"/",
SPAStaticFiles(directory=frontend_directory, html=True),
name="spa"
)
Import
from openhands.server.static import SPAStaticFiles
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| directory | str or Path | Yes | Filesystem path to the directory containing the built SPA frontend assets |
| html | bool | Yes | Set to True to enable HTML content-type detection and index.html fallback |
Outputs
| Name | Type | Description |
|---|---|---|
| response | Response | Static file content for known paths, or index.html for unrecognized paths (HTML5 history mode fallback) |
Usage Examples
Basic Usage
from fastapi import FastAPI
from openhands.server.static import SPAStaticFiles
app = FastAPI()
# Register all API routers first...
# app.include_router(api_router)
# Mount SPA static files last to serve the frontend
# This must be the final mount to avoid intercepting API routes
app.mount(
"/",
SPAStaticFiles(directory="/app/frontend/dist", html=True),
name="spa"
)