FastAPI Example
Generated Equipment projects include web.py, a small FastAPI entry point that reads host and port from config/web.yaml and uses the generated application container.
The example is intentionally minimal. It shows how to combine FastAPI with the generated app() container, not how to structure every production API.
Dependencies
The generated pyproject.toml includes:
dependencies = [
"equipment>=1.0.0",
"fastapi[standard]>=0.100.0,<1",
"uvicorn[standard]>=0.30,<1",
]
Install the generated project before running the web example:
python -m pip install .
Configuration
config/web.yaml:
web:
host: ${WEB_HOST:0.0.0.0}
port: ${PORT:8000}
Set WEB_HOST or PORT in .env or the process environment to change runtime behavior.
Generated web.py
from app import app
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from uvicorn import Server, Config
app = app()
name = app.config.app.name()
web = FastAPI(title=name)
@web.get("/", response_class=HTMLResponse)
async def landing() -> str:
return f'''
<h1>{name}</h1>
<hr />
<p>{app.inspiring().quote()}</p>
'''
if __name__ == '__main__':
server = Server(Config(
app='web:web',
host=str(app.config.web.host()),
port=int(app.config.web.port()),
))
server.run()
The generated file creates the application container once at module import time. For many small apps, that is enough. For larger apps, keep the container creation in one module and import routers that depend on services.
Run
python web.py
Then open the configured host and port, usually http://127.0.0.1:8000 for local development.
If WEB_HOST=0.0.0.0, the server listens on all interfaces. Browsers on the same machine should still use 127.0.0.1 or localhost.
Extend
Add routers or services in app/, then inject framework services through the generated App container. Keep route functions thin and move business logic into testable services.
Add A Router
Create a router module:
# app/routes/health.py
from fastapi import APIRouter
from app import app
router = APIRouter()
application = app()
@router.get("/health")
def health() -> dict[str, str]:
return {
"status": "ok",
"app": application.config.app.name(),
}
Include it in web.py:
from app.routes.health import router as health_router
web.include_router(health_router)
Use Services In Routes
Keep route handlers thin:
@web.post("/reports/{report_id}/rebuild")
def rebuild_report(report_id: int) -> dict[str, str]:
app.queue().push(rebuild_report_job, report_id)
return {"status": "queued"}
Put business behavior in services registered in app/__init__.py, then call those services from routes or queued jobs.
Configuration Per Environment
Local .env example:
APP_ENV=local
WEB_HOST=127.0.0.1
PORT=8000
LOG_CHANNEL=stack
QUEUE_CONNECTION=sync
Container or PaaS example:
APP_ENV=production
WEB_HOST=0.0.0.0
PORT=8000
LOG_CHANNEL=console
QUEUE_CONNECTION=redis
Testing FastAPI Routes
Use FastAPI's test client for HTTP behavior and Equipment's TestCase for service behavior:
from fastapi.testclient import TestClient
from web import web
class WebTest(TestCase):
def test_health(self):
client = TestClient(web)
response = client.get("/health")
self.assertEqual(200, response.status_code)
self.assertEqual("ok", response.json()["status"])
For service-level tests, call the service directly without HTTP. This keeps most tests fast and focused.
Deployment Notes
- The generated
web.pyruns Uvicorn directly for convenience. - Production deployments may use a process manager, container command, or platform-specific start command.
- Keep secrets in environment variables, not in route modules.
- Use
LOG_CHANNEL=consolein platforms that collect stdout. - Use
QUEUE_CONNECTION=redisand a separate worker process for slow work.
Troubleshooting
Server starts but route cannot import app:
Run from the generated project root or install the project with python -m pip install ..
Port is already in use:
Change PORT in .env or stop the process using the port.
Queued route blocks instead of returning quickly:
QUEUE_CONNECTION is probably sync. Use Redis for true background processing.
Guidance
- Keep web configuration in
config/web.yamlor environment variables. - Do not hardcode secrets or deployment hostnames in
web.py. - Use FastAPI's normal testing tools for HTTP behavior and Equipment's
TestCasefor service-level behavior. - Keep route handlers small and move business logic into services.
- Use queues for slow work triggered by HTTP requests.