I built a race bib generator for my own birthday run
Last year I organised a small birthday run for friends. Nothing serious — a loop, a start time, and afterwards something to drink. But I wanted everyone to have a proper numbered bib, because a number pinned to your shirt is what turns a jog with mates into an event.
That turned out to be surprisingly hard to arrange.
The two bad options
Every route I found was one of two things.
The first was a print shop. They do beautiful work, and they want a minimum order of two hundred. I had eleven runners.
The second was doing it myself in Word. This half-works right up until you add a logo, at which point the layout quietly rearranges itself and every number sits three millimetres off. I spent an evening on it, printed a test sheet, and threw it away.
There was nothing in between: no way to take a list of names, pick two colours, drop in a logo and get a print-ready PDF back.
So I built it
The first version did exactly that and nothing else. You paste in names, choose the colours, upload a logo, and download a PDF sized for A5 paper. No accounts, no dashboard, no settings screen. I used it for my own run, the bibs came out of a normal office printer, and eleven people pinned them on.
It worked. That should have been the end of it.
What I did instead
I kept building. Over the following months I added event management, participant imports from CSV, a design preview, seasonal templates for Halloween and Christmas, landing pages for running clubs and triathlons and parkrun, and a blog. I set up a queue system, background PDF generation, error monitoring, a static analysis pipeline and continuous integration.
What I did not do, not once in fifteen months, was tell anyone it existed.
The numbers
Since launch, Bib-Gen has taken five payments totalling €65.
That is the real figure and I am publishing it deliberately, because the build-in-public posts I learn most from are the ones with small honest numbers rather than large vague ones.
Here is the part that took me a while to see. Those five people found it on their own, through search, and paid without a single marketing post existing anywhere. That is not a failure of the product. That is five strangers telling me the product is fine and the distribution is missing.
What it cost and what broke
Running costs are close to nothing: a small server, a domain, a mail service with a free tier. The expensive input was my evenings.
Things that broke along the way, in rough order of how long they went unnoticed:
- PDF generation would occasionally hang on a large participant list, and because the job failed silently the user just saw a spinner forever.
- I discovered recently that the table which records failed background jobs was created with a schema that could never accept a row. It was empty for over a year, and I had read that emptiness as "nothing is failing" when it actually meant "nothing can be recorded".
- The pricing was wrong in a way I could not see from the inside. €9 for a tool that saves a race organiser an evening reads as unserious to someone who has already spent hundreds on timing chips and medals. It is now €19 for a single event and €49 for unlimited events, which is closer to what it is worth to the person buying it.
What I would do differently
Ship the first version, then spend the next month talking to runners instead of adding features. The eleven people at my birthday run were a focus group and I never asked them anything.
I would also charge from the start rather than treating money as something you earn the right to ask for after enough polish. A payment is the only feedback that cannot be polite.
If you organise something small
The tool is here and it does the thing I originally wanted: a list of names in, a print-ready PDF out, on a normal printer, without a minimum order. If you are putting on a club run, a charity 5K, a school sports day or a birthday loop with friends, that is exactly the case it was built for.
And if you try it and something is annoying, tell me. There is a feedback button on every page and it goes straight to my inbox. I read all of them, which is easy to promise at this volume.