DEV Community

Cover image for πŸš€ Build a Todo App API with FastAPI + uv (The Cleanest Way!)
Manish Chaudhary
Manish Chaudhary

Posted on

πŸš€ Build a Todo App API with FastAPI + uv (The Cleanest Way!)

πŸš€ Build a FastAPI Todo App the Right Way (Using uv)

Want to build a lightning-fast API without the Python packaging mess?

Let’s build a Todo API using FastAPI β€” but with a twist: we’ll use uv, the next-gen Python package manager that automates virtual environments, handles dependency resolution, and gets out of your way.


🧩 What is uv?

uv is a modern Python package manager that replaces pip and virtualenv with:

  • πŸš€ Ultra-fast dependency installation
  • πŸ“¦ Automatic virtual environment creation
  • 🧼 Cleaner project setup with zero requirements.txt

It's built in Rust and is ideal for fast, reproducible Python workflows β€” perfect for APIs, CLI tools, and data apps.


πŸ› οΈ Step 1: Set Up the Project

mkdir fastapi-todo && cd fastapi-todo
uv init --app

uv add fastapi --extra standard

Enter fullscreen mode Exit fullscreen mode

🧠 Step 2: Create the Todo Model in models.py

from pydantic import BaseModel

class Todo(BaseModel):
    id: int
    title: str
    completed: bool = False

Enter fullscreen mode Exit fullscreen mode

βš™οΈ Step 3: Build the API in main.py

from fastapi import FastAPI, HTTPException
from models import Todo

app = FastAPI()
todos = []

@app.get("/")
def home():
    return {"message": "Welcome to the FastAPI Todo App"}

@app.get("/todos")
def list_todos():
    return todos

@app.post("/todos", status_code=201)
def add_todo(todo: Todo):
    if any(t.id == todo.id for t in todos):
        raise HTTPException(status_code=400, detail="Todo with this ID already exists.")
    todos.append(todo)
    return todo

@app.put("/todos/{todo_id}")
def update(todo_id: int, updated: Todo):
    for i, t in enumerate(todos):
        if t.id == todo_id:
            todos[i] = updated
            return updated
    raise HTTPException(status_code=404, detail="Todo not found")

@app.delete("/todos/{todo_id}")
def delete(todo_id: int):
    global todos
    todos = [t for t in todos if t.id != todo_id]
    return {"message": "Todo deleted"}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Step 4: Run the Server

uv run fastapi dev
Enter fullscreen mode Exit fullscreen mode

This spins up the app at http://127.0.0.1:8000.
Try out your endpoints using the auto-generated docs at:

πŸ‘‰ http://127.0.0.1:8000/docs

home page

api docs

add todo

get all todos

delete todo

Top comments (0)