Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
29 changes: 15 additions & 14 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
- uses: actions/checkout@v4

- name: Install uv
run: pip install uv
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Create venv
run: uv venv
- name: Install uv
run: pip install uv

- name: Install package with dev dependencies
run: uv pip install -e ".[dev]"
- name: Sync workspace
# --all-packages is required to include extras from workspace members
# (backend's dev extra holds ruff itself).
run: uv sync --all-packages --all-extras

- name: Run Ruff
run: uv run ruff check src
- name: Ruff check (backend + cli + tests)
# --no-sync prevents uv run's implicit re-sync from dropping member
# extras (it defaults to no extras and would remove ruff).
run: uv run --no-sync ruff check backend/src cli/src backend/tests
43 changes: 21 additions & 22 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@ on: [push, pull_request]
jobs:
tests:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11

- name: Install uv
run: pip install uv

- name: Create venv
run: uv venv

- name: Install package with dev dependencies
run: uv pip install -e ".[dev]"

- name: Run tests
run: uv run pytest
env:
ENVIRONMENT: local
SECRET_KEY: test-secret-key-for-testing-only
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install uv
run: pip install uv

- name: Sync workspace
run: uv sync --all-packages --all-extras

# Tests live in backend/ today; cli/ has no tests yet.
- name: Pytest (backend)
# --no-sync prevents uv run's implicit re-sync from dropping member
# extras (it defaults to no extras and would remove pytest).
run: cd backend && uv run --no-sync pytest
env:
ENVIRONMENT: local
SECRET_KEY: test-secret-key-for-testing-only
46 changes: 24 additions & 22 deletions .github/workflows/type-checking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@ on: [push, pull_request]
jobs:
type-check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11

- name: Install uv
run: pip install uv

- name: Create venv
run: uv venv

- name: Install package with dev dependencies
run: uv pip install -e ".[dev]"

- name: Run mypy
run: uv run mypy src --config-file pyproject.toml
env:
ENVIRONMENT: local
SECRET_KEY: test-secret-key-for-testing-only
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install uv
run: pip install uv

- name: Sync workspace
run: uv sync --all-packages --all-extras

- name: Mypy (backend)
run: cd backend && uv run --no-sync mypy src --config-file pyproject.toml
env:
ENVIRONMENT: local
SECRET_KEY: test-secret-key-for-testing-only

- name: Mypy (cli)
run: cd cli && uv run --no-sync mypy -p cli
env:
ENVIRONMENT: local
SECRET_KEY: test-secret-key-for-testing-only
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
/lib/
/lib64/
parts/
sdist/
var/
Expand Down Expand Up @@ -110,7 +110,7 @@ venv.bak/
# Rope project settings
.ropeproject

# mkdocs documentation
# zensical documentation
/site

# mypy
Expand Down
180 changes: 65 additions & 115 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center"> Benav Labs FastAPI boilerplate</h1>
<p align="center" markdown=1>
<i><b>Batteries-included FastAPI starter</b> with production-ready defaults, optional modules, and clear docs.</i>
<i><b>Batteries-included FastAPI starter</b> — vertical-slice modules, swappable infrastructure, plugin-ready CLI.</i>
</p>

<p align="center">
Expand Down Expand Up @@ -32,168 +32,118 @@

* ⚡️ Fully async FastAPI + SQLAlchemy 2.0
* 🧱 Pydantic v2 models & validation
* 🔐 JWT auth (access + refresh), cookies for refresh
* 👮 Rate limiter + tiers (free/pro/etc.)
* 🔐 Server-side sessions + CSRF; OAuth (Google wired, GitHub scaffolded); API keys
* 👮 Rate limiter with per-tier, per-path rules
* 🧰 FastCRUD for efficient CRUD & pagination
* 🧑‍💼 **CRUDAdmin**: minimal admin panel (optional)
* 🚦 ARQ background jobs (Redis)
* 🧊 Redis caching (server + client-side headers)
* 🌐 Configurable CORS middleware for frontend integration
* 🐳 One-command Docker Compose
* 🚀 NGINX & Gunicorn recipes for prod
* 🧑‍💼 **SQLAdmin**-based admin panel (optional, env-toggled)
* 🚦 [Taskiq](https://taskiq-python.github.io/) workers (Redis or RabbitMQ broker)
* 🧊 Redis or Memcached caching (`@cache` decorator + provider API)
* 🛠 **Plugin-ready `bp` CLI** — generate compose files, audit env, mount third-party command/feature plugins
* 🐳 Docker Compose for local / prod / nginx-fronted (generated by the CLI)

## Why and When to use it

**Perfect if you want:**

* A pragmatic starter with auth, CRUD, jobs, caching and rate-limits
* **Sensible defaults** with the freedom to opt-out of modules
* **Docs over boilerplate** in README - depth lives in the site
* **A foundation that grows** — vertical-slice modules + a plugin-aware CLI for code generators
* **Docs over boilerplate** in this README — depth lives on the [docs site](https://benavlabs.github.io/FastAPI-boilerplate/)

> **Not a fit** if you need a monorepo microservices scaffold - [see the docs](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/project-structure/) for pointers.
> **Not a fit** if you need a monorepo microservices scaffold [see the docs](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/project-structure/) for pointers.

**What you get:**

* **App**: FastAPI app factory, [env-aware docs](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/development/) exposure
* **Auth**: [JWT access/refresh](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/authentication/), logout via token blacklist
* **DB**: Postgres + SQLAlchemy 2.0, [Alembic migrations](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/database/)
* **CRUD**: [FastCRUD generics](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/database/crud/) (get, get_multi, create, update, delete, joins)
* **Caching**: [decorator-based endpoints cache](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/caching/); client cache headers
* **Queues**: [ARQ worker](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/background-tasks/) (async jobs), Redis connection helpers
* **App**: FastAPI [app factory](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/project-structure/), env-aware docs exposure
* **Auth**: [server-side sessions](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/authentication/sessions/), CSRF, [OAuth](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/authentication/), [API keys](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/authentication/permissions/)
* **DB**: Postgres + SQLAlchemy 2.0, [Alembic migrations](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/database/migrations/) with prod-confirm gate
* **CRUD**: [FastCRUD generics](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/database/crud/)
* **Caching**: [decorator + provider API](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/caching/) (Redis or Memcached)
* **Queues**: [Taskiq workers](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/background-tasks/) (Redis or RabbitMQ)
* **Rate limits**: [per-tier + per-path rules](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/rate-limiting/)
* **Admin**: [CRUDAdmin views](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/admin-panel/) for common models (optional)
* **Admin**: [SQLAdmin views](https://benavlabs.github.io/FastAPI-boilerplate/user-guide/admin-panel/) (optional, env-toggled)
* **CLI**: [`bp` tool](https://benavlabs.github.io/FastAPI-boilerplate/cli/) for compose scaffolding, env audits, and plugin extensions

This is what we've been using in production apps. Several applications running in production started from this boilerplate as their foundation - from SaaS platforms to internal tools. It's proven, stable technology that works together reliably. Use this as the foundation for whatever you want to build on top.
> **Building an AI SaaS?** Skip even more setup with [**FastroAI**](https://fastro.ai) — our production-ready template with AI integration, payments, and frontend included.

> **Building an AI SaaS?** Skip even more setup with [**FastroAI**](https://fastro.ai) - our production-ready template with AI integration, payments, and frontend included.
## Repo Layout

## TL;DR - Quickstart
This is a [uv workspace](https://docs.astral.sh/uv/concepts/projects/workspaces/) with two members. One venv at the root covers both.

Use the template on GitHub, create your repo, then:
```text
fastapi-boilerplate/
├── pyproject.toml # workspace root (uv workspace metadata)
├── backend/ # the deployable application
│ ├── src/ # interfaces/, infrastructure/, modules/
│ ├── pyproject.toml
│ └── Dockerfile # multi-stage: dev / migrate / prod
└── cli/ # `bp` — developer/operator tool (never ships in prod)
└── src/cli/
```

## Quickstart

```bash
git clone https://github.com/<you>/FastAPI-boilerplate
cd FastAPI-boilerplate
uv sync --all-packages --all-extras # one venv at the root, both members installed
```

**Quick setup:** Run the interactive setup script to choose your deployment configuration:
Generate a compose file for the deployment shape you want:

```bash
./setup.py
uv run bp deploy generate local # hot-reload dev stack
# or: uv run bp deploy generate prod # production single-host
# or: uv run bp deploy generate nginx # production behind nginx
```

Or directly specify the deployment type: `./setup.py local`, `./setup.py staging`, or `./setup.py production`.

The script copies the right files for your deployment scenario. Here's what each option sets up:

### Option 1: Local development with Uvicorn

Best for: **Development and testing**

**Copies:**

- `scripts/local_with_uvicorn/Dockerfile` → `Dockerfile`
- `scripts/local_with_uvicorn/docker-compose.yml` → `docker-compose.yml`
- `scripts/local_with_uvicorn/.env.example` → `src/.env`

Sets up Uvicorn with auto-reload enabled. The example environment values work fine for development.

**Manual setup:** `./setup.py local` or copy the files above manually.

### Option 2: Staging with Gunicorn managing Uvicorn workers

Best for: **Staging environments and load testing**

**Copies:**

- `scripts/gunicorn_managing_uvicorn_workers/Dockerfile` → `Dockerfile`
- `scripts/gunicorn_managing_uvicorn_workers/docker-compose.yml` → `docker-compose.yml`
- `scripts/gunicorn_managing_uvicorn_workers/.env.example` → `src/.env`

Sets up Gunicorn managing multiple Uvicorn workers for production-like performance testing.

> [!WARNING]
> Change `SECRET_KEY` and passwords in the `.env` file for staging environments.

**Manual setup:** `./setup.py staging` or copy the files above manually.

### Option 3: Production with NGINX

Best for: **Production deployments**

**Copies:**

- `scripts/production_with_nginx/Dockerfile` → `Dockerfile`
- `scripts/production_with_nginx/docker-compose.yml` → `docker-compose.yml`
- `scripts/production_with_nginx/.env.example` → `src/.env`

Sets up NGINX as reverse proxy with Gunicorn + Uvicorn workers for production.

> [!CAUTION]
> You MUST change `SECRET_KEY`, all passwords, and sensitive values in the `.env` file before deploying!

**Manual setup:** `./setup.py production` or copy the files above manually.

---

**Start your application:**
Configure your env (the CLI helps with secrets and validation):

```bash
docker compose up
cp backend/.env.example backend/.env
uv run bp env gen-secret # print a fresh SECRET_KEY
uv run bp env validate # audit .env against the production validator
```

**Access your app:**
- **Local**: http://127.0.0.1:8000 (auto-reload enabled) → [API docs](http://127.0.0.1:8000/docs)
- **Staging**: http://127.0.0.1:8000 (production-like performance)
- **Production**: http://localhost (NGINX reverse proxy)

### Next steps

**Create your first admin user:**
```bash
docker compose run --rm create_superuser
```
Bring it up:

**Run database migrations** (if you add models):
```bash
cd src && uv run alembic revision --autogenerate && uv run alembic upgrade head
docker compose up --build
# → http://127.0.0.1:8000 (Swagger at /docs)
```

**Test background jobs:**
```bash
curl -X POST 'http://127.0.0.1:8000/api/v1/tasks/task?message=hello'
```
**Without Docker** (Postgres + Redis required locally):

**Or run locally without Docker:**
```bash
uv sync && uv run uvicorn src.app.main:app --reload
cd backend
uv run alembic upgrade head
uv run python -m scripts.setup_initial_data # creates the first admin user + default tier
uv run fastapi dev src/interfaces/main.py # API
uv run taskiq worker infrastructure.taskiq.worker:default_broker # in a second terminal
```

> Full setup (from-scratch, .env examples, PostgreSQL & Redis, gunicorn, nginx) lives in the [docs](https://benavlabs.github.io/FastAPI-boilerplate/getting-started/installation/).

## Configuration (minimal)

Create `src/.env` and set **app**, **database**, **JWT**, and **environment** settings. See the [docs](https://benavlabs.github.io/FastAPI-boilerplate/getting-started/configuration/) for a copy-pasteable example and production guidance.

[https://benavlabs.github.io/FastAPI-boilerplate/getting-started/configuration/](https://benavlabs.github.io/FastAPI-boilerplate/getting-started/configuration/)

* `ENVIRONMENT=local|staging|production` controls API docs exposure
* Set `ADMIN_*` to enable the first admin user
> Full setup, env-var reference, and per-environment deployment guides live in the [docs](https://benavlabs.github.io/FastAPI-boilerplate/getting-started/installation/).

## Common tasks

```bash
# run locally with reload (without Docker)
uv sync && uv run uvicorn src.app.main:app --reload
# generate a fresh production-ready compose file
uv run bp deploy generate prod --workers 8

# audit your .env against the production security validator
uv run bp env validate

# run Alembic migrations
cd src && uv run alembic revision --autogenerate && uv run alembic upgrade head
cd backend && uv run alembic revision --autogenerate -m "<msg>" && uv run alembic upgrade head

# run tests
cd backend && uv run pytest

# enqueue a background job (example endpoint)
curl -X POST 'http://127.0.0.1:8000/api/v1/tasks/task?message=hello'
# install bp as a global tool (optional)
uv tool install --editable ./cli
```

More examples (superuser creation, tiers, rate limits, admin usage) in the [docs](https://benavlabs.github.io/FastAPI-boilerplate/getting-started/first-run/).
More examples (superuser creation, tiers, rate limits, admin usage, plugin authoring) in the [docs](https://benavlabs.github.io/FastAPI-boilerplate/).

## Contributing

Expand Down
Loading
Loading