Build a Task Management API
Apply every technique from every track to build and ship a production-ready REST API from scratch — using Gemini CLI at every stage of the software development lifecycle. Requirements to deployment, in one continuous flow.
What You'll Build
A production-grade Task Management API with two implementations — FastAPI (Python) and Express (Node.js/TypeScript) — built entirely using Gemini CLI as your co-pilot at every SDLC phase.
What You're Building
- Auth: User registration + login with JWT (HS256, 15-minute access tokens, 7-day refresh tokens)
- Tasks CRUD: Create, read, update, delete tasks with title, description, status (todo/in-progress/done), priority, due date
- Database: PostgreSQL 16 — SQLAlchemy + Alembic (Python) / Prisma (Node.js)
- Infrastructure: Docker + docker-compose for local dev, GitHub Actions CI
- API spec: OpenAPI 3.1 auto-generated and validated
- Automation: Pre-commit hooks, nightly security audit script
Prerequisites
- Completed all 17 course modules (M00–M16)
- Docker Desktop installed and running
- GitHub account with a new empty repository created
- Python 3.12+ OR Node.js 22 LTS (choose your stack)
GEMINI_API_KEYset in your environment
Create a fresh directory: mkdir taskflow-api && cd taskflow-api. Create a project GEMINI.md with your chosen stack, your GitHub repo URL, and your name. This context will persist across all 7 phases.
Phase 1 · Requirements
Generate Requirements Document
Skills from M05
Use Gemini CLI to generate a complete Product Requirements Document. Save the output as REQUIREMENTS.md in your project root.
Generate a complete Product Requirements Document for a Task Management REST API.
Product: TaskFlow API
Users: Individual developers and small engineering teams (2-10 people)
Include:
1. Executive Summary (3-4 sentences)
2. User Personas (2 personas with goals and pain points)
3. User Stories (minimum 15, in "As a... I want... So that..." format)
4. Acceptance Criteria (for each user story)
5. Non-Functional Requirements (performance, security, scalability)
6. Out of Scope (what this v1 will NOT include)
7. Success Metrics
Output as a well-structured Markdown document I can save as REQUIREMENTS.md.
Copy Gemini's output to REQUIREMENTS.md. Review it — add or remove user stories based on your own judgment. The goal is a document that accurately represents what you're building. Gemini will reference this in every subsequent phase.
- REQUIREMENTS.md created and saved in project root
- At least 15 user stories covering auth, tasks, and error cases
- Acceptance criteria defined for each story
- Non-functional requirements include response time (<200ms p99) and JWT expiry
Phase 2 · Design
Architecture, ERD, and API Contract
Skills from M06
Generate three design artifacts and save them in a docs/ directory.
2a · Entity Relationship Diagram
@REQUIREMENTS.md
Generate a Mermaid ERD for the TaskFlow API database schema.
Tables required: users, tasks, refresh_tokens
Include: all columns with types, primary keys, foreign keys, indexes
Output ONLY the Mermaid code block — save as docs/erd.md
2b · OpenAPI 3.1 Spec
@REQUIREMENTS.md
Generate a complete OpenAPI 3.1 specification for the TaskFlow API.
Endpoints:
- POST /auth/register — create user
- POST /auth/login — get JWT tokens
- POST /auth/refresh — refresh access token
- DELETE /auth/logout — invalidate refresh token
- GET /tasks — list tasks (pagination, status filter)
- POST /tasks — create task
- GET /tasks/{id} — get single task
- PATCH /tasks/{id} — update task
- DELETE /tasks/{id} — delete task
Include: request/response schemas with examples, error responses (400, 401, 404, 422, 500), security scheme (Bearer JWT).
Output YAML. Save as docs/openapi.yaml
2c · Architecture Decision Record — Auth Strategy
@REQUIREMENTS.md
Write an Architecture Decision Record (ADR) for the JWT authentication strategy.
Format:
# ADR-001: JWT Authentication Strategy
## Status: Accepted
## Context (problem being solved)
## Decision (what we chose and why)
## Considered Alternatives (with pros/cons)
## Consequences (positive and negative)
## Implementation Notes
The decision: HS256 JWT, 15-minute access tokens, 7-day refresh tokens stored in DB for revocation.
Save as docs/ADR-001-auth-strategy.md
- docs/erd.md contains valid Mermaid ERD with users, tasks, refresh_tokens tables
- docs/openapi.yaml passes OpenAPI 3.1 validation (use
npx @stoplight/spectral-cli lint docs/openapi.yaml) - docs/ADR-001-auth-strategy.md written with at least 2 considered alternatives
Phase 3 · Scaffold
Generate Full Project Scaffold
Skills from M07
@REQUIREMENTS.md @docs/openapi.yaml @docs/erd.md
Scaffold a complete FastAPI project for the TaskFlow API.
Stack: Python 3.12, FastAPI, SQLAlchemy 2.0 (async), Alembic, PostgreSQL 16, python-jose for JWT, passlib for passwords, pydantic v2
Generate this directory structure and all files:
- pyproject.toml (dependencies, dev dependencies, pytest config)
- .env.example (all required env vars)
- src/main.py (FastAPI app factory)
- src/config.py (settings with pydantic-settings)
- src/database.py (async engine + session)
- src/models/ (User, Task, RefreshToken SQLAlchemy models)
- src/schemas/ (Pydantic request/response schemas matching openapi.yaml)
- src/routers/ (auth.py and tasks.py with route stubs)
- src/services/ (auth_service.py and task_service.py stubs)
- alembic/ (initial config + first migration)
- tests/ (conftest.py with test DB setup)
- docker-compose.yml (app + postgres services)
- Dockerfile
Use --yolo to create all files. Save a checkpoint when done: /checkpoint save "phase-3-scaffold"
python -m pytest tests/ --collect-only to verify the test structure is valid before moving to implementation.
Expected Directory Structure
docker-compose up -dstarts without errorsalembic upgrade headapplies migration successfullyuvicorn src.main:app --reloadstarts and/docsloads- Checkpoint saved: "phase-3-scaffold"
Phase 4 · Implementation
Iterative Implementation with Gemini
Skills from M07 — multi-file context loading
Implement each service in two passes: first the auth service, then the task service. Use multi-file context to give Gemini full visibility into your models and schemas.
Implement Auth Service
@src/models/user.py @src/models/refresh_token.py @src/schemas/auth.py @docs/ADR-001-auth-strategy.md
Implement src/services/auth_service.py and src/routers/auth.py.
auth_service.py functions:
- register_user(db, schema) → User (hash password with bcrypt, check email uniqueness)
- authenticate_user(db, email, password) → User | None
- create_tokens(user_id) → {access_token, refresh_token, token_type}
- refresh_access_token(db, refresh_token) → {access_token}
- revoke_refresh_token(db, token) → None
auth.py routes:
- POST /auth/register → 201 UserResponse
- POST /auth/login → 200 TokenResponse
- POST /auth/refresh → 200 {access_token}
- DELETE /auth/logout → 204
Requirements:
- All DB operations are async
- Raise HTTPException with correct status codes
- JWT: HS256, SECRET_KEY from config, access_token 15min, refresh_token 7 days
- Store refresh tokens in DB for revocation support
- Every function has a docstring
Implement Task Service
@src/models/task.py @src/schemas/tasks.py @src/services/auth_service.py @docs/openapi.yaml
Implement src/services/task_service.py and src/routers/tasks.py.
task_service.py functions:
- list_tasks(db, user_id, status?, page, limit) → list[Task] + total count
- create_task(db, user_id, schema) → Task
- get_task(db, user_id, task_id) → Task (raise 404 if not found or wrong user)
- update_task(db, user_id, task_id, schema) → Task
- delete_task(db, user_id, task_id) → None
tasks.py routes:
- GET /tasks → 200 PaginatedTasksResponse
- POST /tasks → 201 TaskResponse
- GET /tasks/{id} → 200 TaskResponse
- PATCH /tasks/{id} → 200 TaskResponse
- DELETE /tasks/{id} → 204
Requirements:
- All routes require Bearer JWT auth (use FastAPI Depends)
- Tasks are scoped to the authenticated user (never return another user's tasks)
- Pagination: page + limit query params, default page=1, limit=20, max limit=100
- Status filter on GET /tasks
- Partial updates on PATCH (only update provided fields)
Phase 5 · Tests
Generate Test Suite (≥80% Coverage)
Skills from M08
@src/routers/auth.py @src/services/auth_service.py @src/routers/tasks.py @src/services/task_service.py @tests/conftest.py
Generate a comprehensive pytest test suite.
Create:
- tests/test_auth.py — test every auth endpoint
- tests/test_tasks.py — test every task endpoint
For each endpoint test:
1. Happy path (valid input, expected 2xx response)
2. Validation error (invalid input, 422)
3. Auth error (missing/expired token, 401)
4. Not found (invalid ID, 404 where applicable)
5. Edge cases (pagination boundaries, empty results)
Requirements:
- Use pytest-asyncio for async tests
- Use httpx AsyncClient (not Requests)
- Each test function is independent (no shared state)
- Factory functions in conftest.py for user/task creation
- Coverage target: 80% (run with pytest --cov=src --cov-report=term-missing)
pytest tests/ -v— all tests passpytest --cov=src --cov-report=term-missing— coverage ≥ 80%- Auth tests cover: register, login, refresh, logout, token expiry
- Task tests cover: CRUD, pagination, status filter, ownership enforcement
Phase 6 · Deploy
Docker + GitHub Actions CI
Skills from M09, M12
Production Dockerfile
@pyproject.toml @src/main.py
Generate a production-ready multi-stage Dockerfile for the TaskFlow FastAPI app.
Requirements:
- Stage 1 (builder): install dependencies with pip into /install
- Stage 2 (production): slim Python 3.12-slim base, copy only /install and src/
- Run as non-root user (uid 1000)
- EXPOSE 8000
- CMD: uvicorn src.main:app --host 0.0.0.0 --port 8000 --workers 2
- Health check endpoint: GET /health → 200 {"status": "ok"}
- Final image size target: under 200MB
GitHub Actions CI Workflow
Generate a GitHub Actions CI workflow for the TaskFlow API.
File: .github/workflows/ci.yml
Triggers: push to main, pull_request to main
Jobs:
1. test:
- ubuntu-latest
- Start PostgreSQL service container (postgres:16)
- Install Python 3.12, install dependencies
- Run alembic upgrade head
- Run pytest --cov=src --cov-fail-under=80
- Upload coverage report to Codecov
2. lint:
- Run ruff check src/ tests/
- Run mypy src/ --strict
3. build:
- Depends on test + lint passing
- Docker build (verify image builds without errors)
- Does NOT push to registry (local build only for PR validation)
docker build -t taskflow-api:local .succeeds under 200MBdocker-compose up— app starts,curl localhost:8000/healthreturns 200- .github/workflows/ci.yml created and pushed — first Actions run passes
- PR review workflow added from M12 patterns (auto-reviews PRs)
Phase 7 · Automation
Hooks + Nightly Automation
Skills from M14, M16
Pre-Commit Hook
Generate a prepare-commit-msg Git hook for this project.
Requirements:
- Works on both Git Bash and PowerShell
- Gets the staged diff with git diff --cached
- Passes diff to Gemini CLI to generate a conventional commit message
- Writes the generated message to the commit message file
- Falls back gracefully if Gemini CLI is unavailable (exits 0 silently)
- Include a launcher script for Windows (.git/hooks/prepare-commit-msg)
that calls pwsh if available, falls back to bash
Output: both the .ps1 script and the shell launcher file.
Nightly Security Audit Script
Generate a nightly security audit script for this Python project.
File: scripts/nightly-security-audit.ps1 (and bash equivalent)
Requirements:
- Audit all src/*.py files for OWASP Top 10 issues using Gemini CLI
- Write structured JSON report to logs/security-audit-YYYYMMDD.json
- Exit code 1 if HIGH or CRITICAL issues found
- Suitable for Windows Task Scheduler (reads GEMINI_API_KEY from System env vars)
- Log start time, end time, files scanned, and total findings summary
- Trim log files older than 30 days (keep storage manageable)
- Pre-commit hook installed:
git stage src/main.py && git commitgenerates a message - scripts/nightly-security-audit.ps1 runs without errors on the codebase
- logs/ directory created, JSON report generated
- Task Scheduler entry created (optional but recommended)
End-to-End Verification
Run through this verification checklist after completing all 7 phases. Every item should pass before you consider the Capstone complete.
- docker-compose up -dAll services start healthy.
docker-compose psshows all "Up". - alembic upgrade headAll migrations applied. Database has users, tasks, refresh_tokens tables.
- curl localhost:8000/healthReturns
{"status": "ok"}with 200 status. - curl localhost:8000/docsOpenAPI UI loads. All 9 endpoints visible with correct schemas.
- pytest tests/ -vAll tests pass. No skipped tests in the core suite.
- pytest --cov=srcCoverage ≥ 80% on src/ directory.
- ruff check src/Zero linting errors.
- docker build -t taskflow:cap .Build succeeds.
docker images taskflow:capshows image under 200MB. - GitHub ActionsCI workflow shows green on main branch. All 3 jobs (test, lint, build) pass.
- git commit -m "wip"prepare-commit-msg hook fires. Commit message is replaced with AI-generated conventional commit.
- scripts/nightly-security-audit.ps1Script runs to completion. JSON report written to logs/.
You've just used Gemini CLI for every single stage of a real software project: requirements, architecture, code, tests, CI, containerization, and automation. This is the AI SDLC in practice — not just using AI for a single task, but as an integrated tool that accelerates every phase of the development lifecycle.
Bonus Challenges
Completed the core Capstone? These three extensions push further into production patterns.
Add Redis Caching
Add Redis to your docker-compose and implement response caching for GET /tasks. Cache key: tasks:{user_id}:{page}:{limit}:{status}. TTL: 60 seconds. Invalidate on any task mutation. Use Gemini CLI to generate the Redis middleware, add it to your service layer, and generate the corresponding tests. Measure the performance difference with pytest-benchmark.
Add Rate Limiting
Implement per-user rate limiting: 100 requests/minute per authenticated user, 20 requests/minute for unauthenticated endpoints. Use slowapi (FastAPI) or express-rate-limit (Node.js). Ask Gemini CLI to generate the middleware, configure the limits from environment variables, and write a test that verifies the 429 response and Retry-After header.
Deploy to Cloud Run
Use Gemini CLI to generate the full Cloud Run deployment: cloudbuild.yaml, Cloud Run service configuration YAML, and a PowerShell deployment script. Ask: "Generate Cloud Run deployment config for the taskflow-api container, using Cloud SQL PostgreSQL as the backend, with secrets managed via Secret Manager for DATABASE_URL and SECRET_KEY." Deploy from the command line using gcloud run deploy.