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
Back to Docs