A multi-vendor marketplace API built with FastAPI. Vendors list and sell products (physical, digital, or services) with shared auth, unified checkout, and order tracking.
Status: v1 proof-of-concept. Auth, catalog, and basic order flows are implemented. Payments are delegated to external PSPs.
- Python 3.13 + FastAPI + SQLModel (async SQLite, designed for Postgres)
- Auth: JWT access tokens + server-side refresh tokens, Argon2id passwords
- Testing: pytest + pytest-asyncio + schemathesis
- Tooling: uv, ruff, ty (static type check), beartype (runtime), pre-commit
# Clone and install
git clone <repo-url> && cd bango
uv sync # installs deps + creates .venv
# Set up environment
cp .env.sample .env # edit with your values (or use defaults)
# Run the server
uv run uvicorn app.main:app --reload
# Health check
curl http://localhost:8000/healthAPI routes live under /api/v1/.
Set in .env (loaded via pydantic-settings):
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
sqlite+aiosqlite:///./bango.db |
Database connection string |
JWT_SECRET |
dev-secret-change-in-production! |
JWT signing secret |
DEBUG |
False |
Debug mode |
DB_ECHO |
False |
SQL echo |
# Tests
uv run pytest # run all (async, auto-detect)
# Type checking
uv run ty check # static (not mypy/pyright)
# Lint + format
uv run ruff check --fix # lint + auto-fix
uv run ruff format # format (single quotes)Pre-commit hooks run ruff, ty, and pytest automatically on commit.
app/
├── main.py # FastAPI app, lifespan, routers
├── shared/ # Cross-cutting: config, db, auth, errors, jwt
│ └── models/ # Shared data models
└── features/ # Vertical slices (feature-first)
├── authentication/ # handler, service, repository, schemas
└── catalog/ # handler, repository, schemas, models
tests/
├── conftest.py # Async client + per-test SQLite DB
├── endpoints.py # Shared endpoint path constants
└── features/ # Tests mirror app/features/
docs/
├── adr/ # Architecture Decision Records
├── agents/ # Agent workflow docs, coding standards
└── dependencies.md # Why each package exists
Features follow vertical slices — each feature in app/features/<name>/ with:
handler.py— HTTP layer (routes, request parsing, response shaping)service.py— Business logicrepository.py— Database queriesschemas.py— Pydantic request/response models
Shared code lives in app/shared/. Features import from shared but never modify it directly.
- Test-first. Write a failing test before any production code. No exceptions (skip only for trivial one-liners).
- Use
uvfor deps. Never hand-editpyproject.toml— useuv add/uv remove. - Endpoints in one place. Define path strings in
tests/endpoints.py, import where needed. - Type checking. Use
ty(static) +beartype(runtime). Do not use mypy or pyright. - Keep
CONTEXT.mdupdated. It's the living domain glossary — add new terms as you work. - ADRs for decisions. Architecture decisions go in
docs/adr/as numbered markdown files.
design/ → to-tickets → .scratch/<feature>/ → implement → app/
- Design API contracts in
design/ - Generate DAG-ordered tickets with the
to-ticketsskill - Implement test-first, walking the ticket DAG one at a time
See docs/agents/coding-standards.md and docs/agents/vertical-slices.md for detailed conventions.
- Registration, login, logout, refresh tokens (family rotation + theft detection)
- Product browsing and listing
- Failed login lockout (5 attempts / 15-min window)
- Rate limiting on auth endpoints
- Password change with token revocation
- Password reset via signed JWT links
Email verification, email sending, account deletion, OAuth/social login, per-vendor commission rates, multi-currency, multi-storefront.