Skip to content
Back to the card
Own product Live 2026

BoxerOS

AI fight-camp platform for boxers


Role

Sole developer - product, build, infrastructure

Links

boxeros.app

boxeros.app
BoxerOS

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

Laravel 12 Livewire 4 MySQL Tailwind CSS Claude API Docker Coolify Hetzner Cloudflare

On a phone

BoxerOS - mobile view

Also on the card