Open source
FastAPI Rocket Boilerplate
A Python API starter for the boring, expensive parts of a backend: auth, an admin, a database, background work, and a generated TypeScript client. The user service is the pattern. A new domain copies it.
The problem
The first month of an API is rarely the domain. It is passwords, tokens, migrations, an admin someone can actually use, and a queue that does not fall over when the request should return. This project puts that month in the repository, with tests that refuse to pass under 95% coverage.
What you get
- FastAPI on Python 3.11, async where the stack allows it, with OpenAPI docs at
/docs. - OAuth2 password flow: register, login, refresh, and logout. Access tokens and refresh tokens are separate JWTs. Refresh tokens can be revoked and are checked against a blacklist.
- SQLModel models with create and update timestamps, soft delete, and a
Recordrow for every create, update, soft delete and hard delete. The record stores whether the change came from the API or the admin, and who did it. - Alembic migrations, applied when the stack comes up. Tests can run them too.
- An admin on SQLAdmin, with its own login, a session, and the same JWT check used by the API.
- Celery workers, RabbitMQ as the broker, Redis as the result backend.
- A
/check_healthroute that reports the database, Celery, RabbitMQ and Redis. - Optional Sentry, and a generated TypeScript SDK from the OpenAPI schema. Operation ids are prefixed with the tag so the client reads cleanly.
Architecture
A login, then a protected call
Decisions
Access and refresh are different tokens, with different scopes. Logout does not depend on the access token expiring. A RevokedToken row blocks a refresh token that has been retired. Tests swap Postgres for SQLite in memory, so the suite does not need the Docker network. Migrations still have their own tests, and they are written to run where the database hostname is the Compose service.
The ORM is small on purpose. ModelCore gives every table an id, timestamps, a deleted flag, and save, delete, get_one and get_all. Soft delete is the default. Hard delete is explicit. Each of those writes a record, so the admin and the API leave the same kind of trail.
Coverage is a gate, not a badge you add later. make test runs pytest with --cov-fail-under=95. GitHub Actions builds the Compose stack and runs that suite on every pull request. Trunk runs on pull requests as well, for the lint and format checks.
Stack
Python 3.11, FastAPI, Pydantic, SQLModel, Alembic, PostgreSQL, Celery, RabbitMQ, Redis, SQLAdmin, python-jose, bcrypt, Sentry SDK, Poetry, Docker Compose, pytest, and a Node step that generates the TypeScript client.
What is left open
The user model already has is_verified. Email confirmation is the natural next use of that flag. The revoked-token table is ready for a real relation back to the user. Neither gap blocks the starter. A new service copies user and imports its models into the Alembic list.