- Language & framework
- Python 3.12 and Django 5.2 LTS
- Front end
- Server-rendered templates with HTMX and under 200 lines of JavaScript. No build step.
- Styling & charts
- Plain CSS with design tokens; charts drawn as inline SVG with no chart library
- Database
- PostgreSQL 16
- Background jobs
- Celery and Redis, scheduled by Celery Beat
- Sign-in
- django-allauth with mandatory email verification, Google sign-in and Argon2 hashing
- Data sources
- eBay Browse API for live listings; SoldComps API for completed sales
- Hosting
- One Ubuntu server running five Docker containers behind Caddy, with Cloudflare for DNS
- Quality
- pytest, ruff and pip-audit, run by GitHub Actions on every push
How it is put together. One codebase split into eight modules, run as three kinds of process from a single Docker image: the website, a background worker and a scheduler. Each marketplace sits behind one interface, so adding another means writing one adapter. Every sweep keeps a raw copy of what the marketplace returned, so matching and scoring rules can be changed and replayed without calling eBay again.