BoxerOS
AI fight-camp platform for boxers
Role
Sole developer - product, build, infrastructure
Links
The problem
Boxers manage a fight camp across a notebook, a scale, a calorie app and a group chat. Nothing knows anything about anything else, so no advice they get is grounded in their actual numbers.
The approach
One Laravel application that owns the whole picture - profile, daily logs, meals, fight calendar - with an AI coach layered on top that is handed the fighter's real context on every message. The AI is a feature of the data model, not a chatbot bolted to the side.
Tale of the tape
Live
in production since July 2026
38
feature tests, green
~1.1s
AI coach response
Decisions
Grounding the AI in real data instead of prompting harder
CORNER receives a built context block - profile, today's log, recent meals, next fight countdown, plus long-term memory of past sessions. That is what makes it more useful than a general chatbot, and it is a data-modelling problem, not a prompting one.
Choosing quality over cost, deliberately
I costed the cheaper model and rejected it: chat runs on the stronger model with a 1500-token ceiling. Cost is controlled where it does not hurt the answer instead - prompt caching on the system block, per-user daily caps, a free local food database tried before any AI call, and a data-built session opener that uses no AI at all.
Removing a feature for liability reasons
I built an injury tracker, then deleted it. Storing structured injury records puts me close to medical record-keeping and advice I am not qualified to give. The AI still discusses injuries in chat, always pointing to a doctor or physio. Knowing what not to ship is part of the job.
A backup that reported success while writing empty files
The nightly database backup piped mysqldump into gzip and reported success every night. The Alpine container ships no mysqldump binary, and the pipe swallowed the failure, so every backup was a 20-byte empty archive. I rewrote the dump natively in PHP over PDO and verified it by restoring into a scratch database. Now I verify restores, not backup exit codes.
Stack
On a phone
Also on the card