Project write-up · juniortrackcycling.com
Building juniortrackcycling.com
A reference hub and a training platform for junior track racers and the parents behind them: rules kept as data, an analysis engine built for the velodrome, a coach that lives inside Claude, and gates at every step because the users are minors.
- 11
- race disciplines explained, each at three levels
- 26
- help pages: every number explained and dated against the code that ships
- 25
- tools a rider, a parent or a coach can use from Claude
- 548
- test files across the site and the analysis engine
juniortrackcycling.com is an independent reference for competitive junior track cycling in the United States, and the training platform behind it. It explains the things nobody had written down cleanly, gearing and rollout limits, equipment by age, every race discipline, the road from a local velodrome to nationals, and it gives a family two free tools a general cycling site does not have: a rollout calculator that checks a bike is legal before an official does, and ride analysis built for the boards rather than the road.
It is written for the junior and the parent at a velodrome, or at the kitchen table the night before a race, trying not to be relegated over a rule nobody explained. Coaches and clubs come second. It is a small, devoted niche, and the site is meant to read as neutral and trustworthy, which is why it is deliberately not a vehicle for any one rider, including mine; his site is a separate project.
01A number that relegates a kid
Junior track racing has a rule most parents meet the hard way: a gear limit, measured as the distance the bike travels in one pedal stroke, that changes with age. Get it wrong and the child is relegated after the race, and nobody at the velodrome has time to explain the arithmetic. The rules exist, the tables exist, and the explanation did not, not in one place and not in plain words.
That was the gap, and it set the order of work. The first commit is from 19 June 2026, and the first real work four days later was not a page: it was the analysis engine for velodrome rides, because the tools were the reason to come back, and the content was the reason to arrive. The content collections followed a week later.
02Two products, one site
The product document describes three modes. Persuade: the home page, which leads with the two free tools and dropped the nationals from its hero the week after the event ended. Read: the hub, four long guides, eleven disciplines each explained for a beginner, an intermediate and an advanced rider, eight equipment buyer’s guides, the nationals pages and a results archive. Operate: the platform, where a rider uploads rides, joins a club, works with a coach and, with the right consents, a weekly plan from an AI coach.
The stack is locked in the project’s instructions, with the rule that the AI must not re-propose it: Astro with content collections, hand-written CSS from a small set of design tokens, islands only where a page genuinely needs them, Cloudflare Pages for the site. The platform needed more than static files, and it got exactly what it needed and no more: a Postgres database with sign-in and storage, and one Python service for the analysis and the coach. The domains stay at the registrar; nothing is hosted there.
The design tokens are the lines on a velodrome: the red of the sprinter’s line, the blue of the Côte d’Azur, a near-black ink and paper. In August the display typefaces were retired for one typeface for words and a monospace face for data, the same rule as on Leo’s site; in October came a redesign under the lights, with view transitions, a command palette and a motion layer that switches itself off for anyone who asked for reduced motion.
03Rules as data, not memory
The content accuracy rule is the first non-negotiable in the instructions file: no rollout number is ever written from memory. The limits are configurable data, with the date they were last checked against the governing body’s rules, and the disclaimer that the site is not affiliated with that body is always shown. The calculator reads the data; the help page explains the calculation; the guide tells the story; none of them carries its own copy of a number.
The help system is the part I would show a hiring manager. Every feature and every calculation, down to its constants, has a help page, and each page carries the date it was last verified against the code that ships. Since September that is enforced: a pull request that changes a behaviour, a formula or a constant has to update the matching help page and bump its date, and a test fails when it does not. If a number cannot be supported, the page says so rather than guessing. The documentation cannot drift from the product because the build does not let it.
04Built for minors
The users are children and the people responsible for them, so the platform’s rules about consent and data are not a privacy page; they are gates in the data path. Nothing can be uploaded or analysed until consent to analyse is recorded. Consent to the AI coach is separate, and for a rider under thirteen it needs a guardian’s typed signature. A rider’s public page, which aggregates a child’s name, licence number and birth year, is indexed by search engines only when the rider opts in, with a guardian.
- The coach is judged by a second model. Everything the AI coach writes for a minor passes through a safety judge, a different model that checks for advice about weight and body, fails closed, and is never asked to judge its own author’s output.
- Review before advice. Since October the coach does not read a ride until the rider has confirmed every effort label, rated the effort and written a short debrief. The rider’s account of the ride comes before the machine’s.
- No location leaves. Payloads to connected apps never include GPS, and a test proves it. A browser harness in the repository proves that photos of minors are stripped of their embedded location before they are stored.
- Funnel measurement without an identifier. The site needs to know whether readers become users, and the design for that measurement keeps the promise that no visitor is identified.
05Analysis built for the boards
Every popular training tool assumes a road. A velodrome ride is different: short efforts at a fixed gear, standing starts, flying laps, a session made of repeats rather than one long ride. The analysis engine is a Python service, ninety-one modules, that parses the file a bike computer writes, segments a velodrome session into its efforts, classifies the session and each effort, and computes the things a coach wants: power curves, critical power and the anaerobic reserve above it, training load over days and weeks, repeatability, starts and pacing.
The part I am proudest of is the corrector: a small model trained on the corrections riders make when the engine mislabels an effort, so the labelling improves from use rather than from me guessing at thresholds. It is also where the tests live: two hundred and twenty-nine Python test files with about three thousand tests, because a number on a child’s training page has to be right.
The engine’s one honest limitation is in its deploy notes: it is pinned to a single machine that never stops, because its job store is in memory. That is a trade I made knowingly for a service that is not yet open, and I will unmake it when the numbers say so.
06A coach inside Claude
In August the platform grew an MCP server, so a rider, a parent or a coach can connect the Claude app to their own training data from the profile page. Twenty-five tools: eighteen that read, seven that write. Reading is the default. A write, planning a week, moving or skipping a workout, setting a rider’s threshold, needs a token with write scope and a two-step confirmation signed by the server and valid for ten minutes, and every write is logged and tells the rider and the guardians.
- A skill tells Claude how to coach. It must read the rider’s profile first, because racing age and the gear limit change every answer. Adherence is counts, never a grade. Targets come from the rider’s measured ceiling, never from a percentage of a threshold. And it must say when the data has gaps.
- Weekly planning closes the loop. The planner proposes a week, and afterwards matches each planned session to the ride that followed it, so the next plan starts from what happened, not from what was intended.
- Previews, then confirmation. No tool that changes data acts on its first call. It returns a preview and a confirmation code; the person says yes; the second call does the work.
The reason to build it was to find out whether an AI coach for juniors could be done responsibly. The answer so far is: only with the gates in the section above, and with them, yes. An answer about a week of training that is grounded in the actual rides, with the guard rails visible in the conversation, is a different thing from a chatbot with a training plan. Leo is on a break and about to start training again, and I am using it to build out his weekly schedule, fine-tuning the coach as we go.
07You catch it, not me
That heading is a section of the instructions file, and it is the rule that changed how I work with an AI agent. The agent does not ask me to check a layout; it runs a script that renders the real pages at four widths in both themes, fails on overlap, overflow, clipped text, poor contrast and console errors, and reports zero errors with screenshots before it reports anything else. Signed-in pages are checked through temporary harness pages. When a bug slips through anyway, the rule is to extend the checker and reintroduce the bug to prove the checker now catches it. The same check gates every deploy.
- Database rules are tested. Every table gets row-level security in its own migration, and a test fails when one does not. The agent pushes migrations to the cloud itself and verifies them with live probes, because a merged-but-unpushed migration silently breaks features; it also checks migration numbers for collisions, after three collided.
- Security is checked by a machine, twice. The database provider’s security advisor runs against a throwaway database on every pull request, against production daily, and against production again before every deploy. Reviewed exceptions live in a baseline file; nothing merges until both checks pass.
- One full audit. On 27 August a full-surface security audit was written, every finding reproduced live, fixed in a series of pull requests and re-verified against production by the next day. It was the second audit; the first was eleven days earlier.
The agent is held to the standard I held my teams to: show me the number, show me the screenshot, and when something gets past you, fix the check before you fix the bug.
08Behind the curtain
The site is built and it is not open. Visitors see a holding page; a first group of junior riders is using the platform on the real track before the doors open, and the lock is one constant in the code that fronts every request. It is a product decision, not a technical one: a reference that promises “every number explained” has to have earned it on the boards, and a platform for minors has to be tried by families who know me before it is tried by families who do not.
09How it was built
Four months, 2,033 commits on 82 working days, 1,227 of them co-authored with Claude. The method is the same every time: brainstorm with me, write a spec, get it approved, write a plan, execute the plan task by task with subagents, verify against the real site, commit. The repository holds a hundred and forty specs and a hundred and forty-one plans, each with its date and its status line, which is how I can write this piece without guessing. The themes by month tell the story: analysis and activities in June, clubs and admin in July, media, coaching, the MCP server and nationals in August, availability and the AI coach in September, and in October the redesign and the loads a rider carries.
The instructions file grew into the product’s constitution: the locked stack, the hosting rule, the help-in-sync rule, the verification rule, the migration rule, the security gates, the content accuracy rule, the safety rules, and the order in which the site will make money if it ever does: the platform first, then equipment links, then premium content, then sponsorship, and never ads. Three project skills sit beside it: how to design a page for this site, how to verify a page visually, and how to coach from the MCP tools.
10Best practices
- A fact is data with a date. A rule or a constant lives in one place, with the date it was last checked, and nothing else carries a copy.
- Documentation the build enforces. A test that fails when a formula changes and its help page does not is worth more than a documentation policy.
- Consent and safety in the data path. Gates at upload, at review, at the model and at every write, not a paragraph on a privacy page.
- Judge the model with another model, and fail closed. When the reader is a child, a second opinion on every word is cheap.
- Make the agent prove its work. Screenshots, zero-error checks at every width, security advisors on every pull request, and a rule to extend the checker when a bug gets through.
- Earn the launch. A holding page and a first group of real users are better than a launch that has to be walked back.
11What’s next
The doors open when the riders on the track say the numbers are right. Then the funnel from reader to rider: saving a calculator setup, a newsletter on the hub pages, a sample analysis anyone can read. The weekly planner still needs workout export to the trainers people own and a scheduled re-plan, and the security backlog that every real system has is tracked in the audit and worked through in order.
This write-up is refreshed from the project’s repository after every check-in; the numbers in the header are counted from it.
Ask the assistant something a recruiter would ask.