This is a demo project that deploys a FastAPI application to AWS Lambda using AWS SAM.
The frontend of the application is a Vue 3 single-page application that is served from the root path of the FastAPI backend.
The backend also includes Powertools for AWS Lambda for enhanced logging and tracing in AWS.
Poetry is used for Python dependency management.
You can view the live version at:
https://3digtt1sjd.execute-api.eu-central-1.amazonaws.com/Prod/docs.
The SAM CLI builds and packages the app from the contents of the /src directory as specified in template.yaml in the project root.
The /src directory contains the FastAPI app in /src/app and a requirements.txt file that specifies the Python runtime dependencies.
Since the frontend is served from FastAPI, frontend build artifacts are generated in /src/frontend in order to be included in the SAM build.
The /frontend folder contains the Vue 3 frontend as a self-contained project created with npm create vue@latest.
/frontend # Vue 3 frontend
/src
/app
main.py # FastAPI app
/frontend # frontend build artifacts
requirements.txt # Python dependencies
/testsThe frontend is a Vite-powered Vue 3 single-page application.
The build npm script in /frontend/package.json is configured to output the build artifacts to /src/frontend so that they can be included in the SAM build.
You can run the frontend build manually with:
cd frontend
npm run buildThe frontend is served from the root path of the FastAPI app.
This runtime integration is implemented in /src/app/frontend.py:
def mount_frontend(app: FastAPI, build_dir: Path, assets_folder="assets") -> FastAPI:
"""Serves a frontend application at the root path `/`
Args:
app: FastAPI application instance
build_dir: Frontend build directory
(generated by `yarn build` or `npm run build`)
Returns:
FastAPI: instance with the frontend application mounted
"""
app.mount(
f"/{assets_folder}/",
StaticFiles(directory=(build_dir / assets_folder), html=True),
name="assets",
)
templates = Jinja2Templates(directory=build_dir)
@app.get("/{_full_path:path}", include_in_schema=False)
async def serve_frontend(request: Request, _full_path: str) -> HTMLResponse:
return templates.TemplateResponse("index.html", {"request": request})
return appTherein, the index.html file is served from the root path / as a Jinja2Templates.TemplateResponse
and the frontend build assets are statically mounted at /assets/ using FastAPI/Starlette's StaticFiles class.
The approach is taken from this answer on StackOverflow: https://stackoverflow.com/a/70065066/733291.
This project uses Poetry for dependency management.
Poetry organize dependencies in groups and this project distinguishes following groups:
main- dependencies for the FastAPI appdev- dependencies specifically for developmenttest- dependencies for running tests with pytestcode-qa- dependencies for code quality checks
The main group is the only one that is needed for the deployed app.
Therefore, the requirements.txt file in the /src directory is a direct dependency of the poetry.lock file.
As such, it is generated from the poetry.lock file with only dependencies from the main group using the poetry export command.
This happens automatically as part of pre-commit hooks (see /pre-commit-config.yaml).
You can update it manually with:
poetry export -f requirements.txt --only main --output src/requirements.txt --without-hashesDuring development, you can run the frontend build and the backend concurrently in separate processes.
Start the frontend build in watch mode:
cd frontend
npm install
# runs the frontend build with --watch flag
npm run watchStart the FastAPI app in dev mode using uvicorn:
poetry install
cd src
python -m app.mainYou can manually deploy the app to AWS using the AWS SAM CLI.
sam build --use-container
sam deploy --guidedYou can also deploy the app from a GitHub Actions workflow to AWS.
sam pipeline init --bootstrapThis command will initiate an interactive assistant that guides you through creating the necessary AWS infrastructure resources.