tech stack
Tech Stack
All technology choices are finalized.
| Component | Choice | Notes |
|---|---|---|
| Framework | Flask (Python) | WSGI; Blueprint-based multi-tool structure |
| Templating | Jinja2 | Server-rendered HTML; no client-side framework needed |
| Database | SQLite via SQLAlchemy | Download tracking, clone metrics; same pattern as icarus-prospects |
| HTTP client | httpx | Sync HTTP client for GitLab API calls and streaming proxying |
| WSGI server | Gunicorn | Production WSGI server; already used by icarus-prospects |
| Reverse proxy | Caddy | Already on the gateway; handles SSL automatically via Let's Encrypt |
| Analytics | Umami | Self-hosted, privacy-respecting web analytics; no cookie banners needed |
| Deployment | systemd service | Portal runs as Gunicorn on port 8000 behind Caddy |
| License | GPL v3 | Copyright © 2026 David Beauchamp |
Rationale
Flask + Jinja2 (not FastAPI)
The prospect editor — the most complex piece of the portal — is already a complete, tested
Flask application. Migrating it as a Flask Blueprint requires minimal rewriting. Flask's
Blueprint system maps cleanly to the per-tool structure (/pets, /prospects, /catalog).
Server-rendered HTML is simpler, faster to build, better for SEO, and requires no
JavaScript build pipeline.
SQLite via SQLAlchemy (not aiosqlite)
Flask is synchronous (WSGI), so aiosqlite is unnecessary. SQLAlchemy with SQLite gives
consistent patterns across the portal and aligns with how icarus-prospects already
manages its database. The metrics workload is low-volume writes and simple aggregate reads
— SQLite is perfectly adequate.
httpx (not requests)
httpx supports streaming responses, which is essential for proxying large file downloads
and git pack transfers without buffering them in memory. The sync API is used here since
Flask is WSGI.
Gunicorn (not uvicorn)
Gunicorn is the standard WSGI server for Flask in production. It is already deployed for
icarus-prospects on the same server, so no new operational tooling is needed.
Caddy (not nginx)
Already deployed on the gateway. Automatic HTTPS is a significant operational simplification. The Caddyfile syntax is readable and the config needed here is minimal.
Umami (not Google Analytics)
Self-hosted, GDPR-clean, no data sent to third parties, no cookie consent banners needed. Runs as a lightweight Node/Docker process on the same server.
Python Dependencies
flask>=3.0.0
gunicorn>=21.0.0
jinja2>=3.1.3
sqlalchemy>=2.0.0
httpx>=0.27.0
python-multipart>=0.0.9
Shared core library (UE4 parser/serializer)
Both icarus-pets (desktop) and the prospects Blueprint depend on the same UE4 binary
save parsing logic. This is extracted into core/ within the portal repo and shared:
core/
├── ue4_parser.py
├── ue4_serializer.py
└── save_io.py