TeamCaddy

Why we built it

Software for a car park, in the rain, one-handed.

Almost every decision in this product comes from the same picture: a parent standing beside a pitch at 9:40 on a Saturday, holding a phone in one hand and a folding chair in the other, in daylight bright enough to wash out a screen. That person has one question, and they need it answered in four seconds.

The moment the product is for

Youth sport is not a project-management problem. It is one short, repeating exchange, played out between twenty households and one volunteer, every week, for nine months: when is it, where is it, who is coming.

Everything else in a team-management product — the payments, the waivers, the standings, the photo album — exists because that exchange keeps happening and generates administrative debris. So we built the exchange first and made it excellent, then built the debris handling around it, rather than the reverse.

A team-management product that hides the headcount behind a paywall has misunderstood which part of it is the product.

Why the interface is light first

Dark interfaces have been the default signal of software craft for about a decade. They are also close to unusable in direct sun, which is where this particular software gets used. A near-black panel on a phone at nine in the morning in June is a mirror.

So the canvas is a warm, very slightly off-white — pure white glares too — and the whole type ramp was contrast-checked against it rather than against black. Dark mode exists and is a genuine second palette, built and tested separately, because inverting a light theme produces muddy greys and a brand colour that fails contrast. It is a choice offered, not a default assumed.

Every foreground and background pair we ship is verified against WCAG minimums by a script that reads the design tokens directly. A contrast failure is treated as a bug in the token, not as a threshold to negotiate.

Why the brand colour is violet

The most-tapped control in this product means going, maybe or out. That triad owns green, amber and red, and those three must never be ambiguous — a coach reading a roster at a glance is reading colour before words.

Most software in this category is branded green or orange, which puts the brand colour directly on top of the one signal that has to stay unmistakable. Violet sits far from all three in hue, so a brand-coloured button can never be misread as an attendance state. It is a functional decision that happens to also look like nothing else in the category.

Colour is never the only signal, either. Each attendance state carries its own glyph, and the three are separated in lightness as well as hue, so they still read as three for the roughly one man in twelve with a red–green colour vision deficiency.

Why numbers get their own typography

Scores, clocks, jersey numbers, counts and money are not text. They are read as quantities, often while changing, and often at a glance from a distance. So they are set as a distinct typographic role: tabular, slashed-zero, heavier, and tracked tighter — which is why a digit does not shuffle its column when a score ticks over.

It is a small thing that shows up constantly, because a product about schedules is a product full of numbers.

Why the free plan is complete

A single team with no club above it is a real, common, permanent situation — a parent who volunteered to coach and now has twenty families to organise. It is not a trial of a club account and it is not a lead to be converted.

So the free plan carries the entire core loop: unlimited roster, unlimited events, full attendance with the who-has-not-answered list, threaded chat, a public team page and a calendar feed. The paid plans add money, legal signatures and organisational scale — things a volunteer coach genuinely does not need on a Tuesday.

Why every default is closed

A roster is a list of children, with their ages, their photographs, their home suburbs and a weekly timetable of exactly where they will be standing. Treating that as ordinary application data is a category error.

  • A public team page shows the schedule and the results. The roster and the photo gallery are off until an administrator turns them on.
  • Medical fields, health check-ins and injury reports name in the schema exactly which roles may read them, and the API enforces it. A coach sees “cleared to play”, never the reason.
  • There is a fan role for grandparents and boosters that sees the schedule and the score and no contact details at all.
  • Every permission check in the API resolves through one table. Role checks scattered through route handlers are how a product ends up letting a spectator delete a roster.

Why there will never be advertising

Advertising against a youth roster is not a banner. It is a data sale: the targeting is what has value, and the targeting is children's ages, locations, sports and weekly movements. There is no version of that we are willing to run, at any tier, including the free one.

This is the reason the free plan is a genuinely free plan rather than an ad-supported one, and it is the reason the paid plans are priced to cover the cost of the free one. You are the customer on every plan, including the plan that costs nothing.

What we will not build

Public live video of youth athletes, by default, on a shareable link. The infrastructure is not the obstacle — the safety model is. If we ever ship video it will be access-controlled to the rostered families first and public never, and we would rather say that now than quietly ship the easy version later.

We also will not charge per administrator. Charging per seat is how a club ends up with six volunteers sharing one login, which destroys the audit trail exactly where a club most needs one.

See what it costs

Start with one team. Add the club later.

A single team is free, forever, with the whole core loop — schedule, roster, RSVP, chat, public page. Nothing is held back to make you upgrade.

No credit card. No ads, ever.