Skip to content
Mark Garrigan

Work › nurun co.

nurun co.

My race company's site, and the admin I run race week from.

Live nurun.co ↗

Role
Owner of the race company, and the engineer behind its software.
Built
2017 → now
History
Site 1.0 in 2017, 2.0 in 2018, 3.0 (current) in 2021. nurun-admin added in 2026.
Stack
Bun · Edge · MySQL · Tailwind · Mailgun
[x] Interface[x] API[x] Data[x] Infra[x] Ops

Story

nurun co. is my race company. It puts on the Black River Trail Classic. The public site carries the race details, race updates and results by year and distance.

Behind it is nurun-admin, where I actually run the race. It replaced the spreadsheets I used to juggle. Registrations come in as CSV exports. I assign bibs per race date, track shirt sizes, write thank-you notes by household and send race emails. Then I export the entrant list straight into Bibsee for timing.

Results

  • The public site has run since 2017 and is in its third version: 1.0 in 2017, 2.0 in 2018, 3.0 in 2021.
  • Runs the Black River Trail Classic: entrants, bibs, shirts, emails and results.
  • nurun-admin (2026) replaced my race-week spreadsheets.
  • Keeps race history across years: distance mix, repeat runners and the all-time top 5.

System, layer by layer

[x] Interface
Edge templates and Tailwind 4, server-rendered, in both apps.
[x] API
Bun.serve with hand-rolled routing, a CSRF-protected contact form, and an email one-time-code login for the admin.
[x] Data
MySQL through Bun.SQL. Both apps share one schema, with self-run migrations.
[x] Infra
Multi-arch Docker images on ghcr, deployed with boxx. GET /up health checks, and Mailgun for email.
[x] Ops
A data bundle for export and import, and CSV imports with saved column layouts.

Screens

Screenshot: nurun.co, the public race site.
nurun.co, the public race site.[Screenshot]
Site
nurun.co
Status
Live
Built
2017 → now

Visit nurun.co ↗

Private tool: nurun-admin

Private · Private tool, shown as illustrations · 2026-05 → now

The tool I run race week from. I'm its only user. It isn't public, so the screens here are drawn from its real templates with invented runners.

  • Imports registrations, bibs and shirt answers from CSV, with a preview before anything is written
  • Assigns bibs per race date and flags conflicts for me to settle
  • Tracks shirt sizes: needed, ordered and printed, plus who hasn't answered
  • Groups thank-you notes by household and tracks which are sent
  • Writes and sends race emails, and publishes them as race updates
  • Keeps race history: distance mix, repeat runners, all-time top 5
  • Exports each race date's entrants straight into Bibsee
Illustration: nurun-admin: shirt sizes for a race date.
nurun-admin: shirt sizes for a race date.[Illustration]
Illustration: nurun-admin: previewing a bib file before anything is written.
nurun-admin: previewing a bib file before anything is written.[Illustration]
Illustration: nurun-admin: participant and race history.
nurun-admin: participant and race history.[Illustration]

Decisions

  1. 01

    Plan before writing

    The import wizard works out every change “before anything is written” and shows a preview, so a bad file never touches the race.

  2. 02

    Never invent a runner

    A bib file “only numbers people already registered… a row that matches nobody is skipped, never added.” When a saved bib conflicts, I choose.

  3. 03

    Keep the volunteers

    A shirt answer that matches no registrant, like a volunteer or a friend, “is kept and counted.”

  4. 04

    One schema, two apps

    The public site reads races, results and published emails straight from the admin's database, so nothing is entered twice.

  5. 05

    Ready for Bibsee

    Each race date exports “Entrants for Bibsee” with exactly the columns Bibsee's importer expects.

In the box

  • Public: race page, results by year and distance, race updates, race guide PDF
  • Admin: races, distances and race dates
  • Registrations, plus results import with unlinked-result matching
  • Thank-you notes grouped by household
  • Participant and race history
  • Shirt sizes: needed, ordered and printed
  • Marketing emails: test send, send, publish as a race update
  • Import wizard for registrations, bibs and shirts, with saved layouts
  • Data bundle export and import