← Work / Software

UMA Companion

A support-card manager that grew into a local-first desktop ecosystem. The project is finished; the engineering story is not disposable.

Sunset 2025–2026 · development ended August 2026

Rust / TypeScript / TSX / SQLite / Python / PySide6 / Playwright

UMA / application boundariesExplanatory diagram
01 / InputsCatalogue data

Cards · skills · scenarios

Your collection

Owned cards · saved decks

02 / Decision engineSearch.
Score.
Validate.

Beam-search optimiser

03 / ApplicationDeck planning

Rust + TypeScript / TSX

Local-first state

SQLite · shared collection

Explanatory diagram · relationships described in the retrospective.

The problem

Choosing six support cards in Uma Musume means balancing a collection, a borrowed card, scenario requirements and interacting effects. I wanted those decisions to be explainable rather than scattered across reference pages.

What I built

Collection and deck management, catalogue and track tools, a beam-search optimiser, desktop releases and a web platform. Later OCR and live-capture work explored bringing game state into the companion without manual entry.

Architecture & approach

The Python prototype moved from CustomTkinter to PySide6, then toward a Rust core with a TypeScript/TSX interface. SQLite held catalogue and user-owned data. The earlier web platform used Next.js and FastAPI; that belongs to its historical architecture, not a claim about the final deployment.

Important decisions

Separate the executable from catalogue data packs. Keep scraping and data preparation on the maintainer side. Merge catalogue tables without replacing the user’s collection and saved decks.

What went wrong — and what changed

An early database update could overwrite user data. Separating catalogue and user tables addressed that boundary. Bundling Playwright made distribution unwieldy, so scraping moved to maintainer jobs. OCR introduced uncertain input that needed validation rather than blind trust.

Current outcome

Active development ended in August 2026. Maintaining the application, changing game data, releases and OCR no longer justified the remaining value. The optimiser remained distinct even as official guidance improved. The archive is a record, not a promise of compatibility with later game updates.

Lessons learned

Architecture becomes clearer through use. A plausible optimisation result still needs evidence. Uncertain inputs need explicit boundaries. Choosing to stop maintaining a project can be a deliberate product decision.

Project notebook

A Year Building UMA Companion: Why I Sunset the Project Article

From UmaOptimizer to UmaCompanion: The Earlier Architecture Article

Historical project website ↗