Every FastAPI project starts the same way: copy-paste from the docs, manually set up CORS, figure out Pydantic models, write a Dockerfile, remember how TestClient works.
I got tired of doing this every time, so I made a clean starter template. Here's what's in it and why.
The structure
fastapi_starter/
├── main.py # CRUD API with models, CORS, error handling
├── test_main.py # pytest suite with TestClient
├── Dockerfile # Production container
├── requirements.txt # Pinned deps
└── README.md # Quick start guide
main.py — the whole API in 50 lines
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = FastAPI(title="API", version="1.0.0")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
class Item(BaseModel):
name: str
description: str = ""
price: float
items: dict[int, Item] = {}
next_id = 1
@app.post("/items", status_code=201)
def create_item(item: Item):
global next_id
items[next_id] = item
next_id += 1
return {"id": next_id - 1, **item.dict()}
@app.get("/items/{item_id}")
def get_item(item_id: int):
if item_id not in items:
raise HTTPException(404, "Item not found")
return {"id": item_id, **items[item_id].dict()}
CORS is on by default (you'll forget otherwise). Pydantic handles validation. HTTPException gives clean error responses.
test_main.py — 5 tests that actually matter
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_create_and_get():
r = client.post("/items", json={"name": "Widget", "price": 9.99})
assert r.status_code == 201
r2 = client.get(f"/items/{r.json()['id']}")
assert r2.json()["name"] == "Widget"
def test_not_found():
assert client.get("/items/999").status_code == 404
Run with pytest test_main.py -v. No external DB needed — the in-memory store makes tests fast and isolated.
Dockerfile — one command to deploy
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
docker build -t myapi . && docker run -p 8000:8000 myapi — done.
What I'd add next
- SQLAlchemy + Alembic for a real database
- OAuth2 + JWT authentication
- Rate limiting middleware
- Background tasks with Celery or ARQ
But the template is deliberately minimal — it gives you a clean starting point without opinions you'll have to undo.
Full starter template (main.py + tests + Docker + README): payhip.com/b/2ptFz ($7)
Also available:
- Python Automation Toolkit — 10 standalone scripts ($12)
- Regex Cookbook — 50 patterns ($9)
- AI Prompt Pack — 50 prompts for Claude/ChatGPT ($9)
- Python Cheat Sheet ($5)
Top comments (0)