Let Me Run — Preparing Boys for the Long Run
LMR OS
Staff & board sign-in. Enter your Let Me Run email and we'll send you a 6-digit code.
Trouble signing in? Contact the operations team.
🔀
Reference

How the Public Teams List Gets Its Data

The full path a team travels from Pinwheel to a family’s screen on letmerun.org — the nightly baseline, the live layer, and where the things we own join in.

The short version: Two paths meet in the family’s browser. WordPress paints a day-old baseline of the teams from a nightly Pinwheel sync, and then a small snippet of JavaScript calls one function (get-teams-live) that reads Pinwheel live and staples on the two pieces Let Me Run owns: the Website Info note an RD writes, and the OS-assigned coaches. The family sees the two layers as one seamless list.

The picture

Pinwheel / Raceplanner where families register LMR OS (Dashboard) RDs write in Workflows → Website Info · Coach assigns nightly sync WordPress posts one per team & region shortcode Baseline cards rendered on the server — the safe fallback — live read (token stays server-side) note + OS coaches get-teams-live joins the 3 sources strips out private contact info refreshes about every 2 min live data The family’s browser 1 · shows the baseline instantly 2 · refreshes each card live — status, dates, coaches, links + the note 3 · adds brand-new teams the sync hasn’t created yet = what the visitor sees

Path 1 — the nightly baseline WordPress

Every night, a sync copies team and region details out of Pinwheel into WordPress — one post per team, one per region. When a family opens a region page, WordPress builds the team cards on the server straight from that synced copy: the status color, the register buttons, the address, the grades. This layer never touches the Dashboard. It’s the deliberate fallback — if anything below fails, the family still sees a complete list. The page never goes blank. Its one limit: it can be up to a day old.

Path 2 — the live layer Pinwheel OS

The same page also carries a bit of JavaScript. Once those baseline cards are on screen, it calls one endpoint — get-teams-live — and that function does the real assembling. It’s public and read-only, but it reaches three places and merges them:

1

Pinwheel, read live Pinwheel

It calls the Pinwheel API directly, server-side (the private token never reaches the browser), and pulls the current status, registration open/close dates, register links, school address, practice schedule, grades, and Pinwheel’s own volunteer list. This is why a status change shows up within about two minutes instead of waiting for tonight’s sync.

2

The Website Info note from the OS

An RD writes an “Additional Information” note in the Dashboard (Workflows → Website Info). It’s stored in the OS against the team’s names, and the function looks it up and hands it to the card as a tinted callout. A note that can’t be matched to a team with confidence shows up nowhere — it’s never guessed onto the wrong team.

3

The OS-assigned coaches from the OS

The coaches on a public card are a combined list: Pinwheel’s volunteers plus the coaches you approved in the OS, merged and de-duplicated by name. A coach you approved in the Dashboard who was never entered in Pinwheel reaches the public card only through this step — because coaches are ours, while the teams themselves are Pinwheel’s.

Then the browser assembles it

The function returns clean data with all director and contact email/phone removed — private contact info never goes to a public page. The browser matches each row to its baseline card and updates it in place; the note renders as plain text, so even a pasted <script> would show as harmless words. If the live call fails, the baseline card is simply left as-is.

Who owns what on a card

Field on the public cardComes from
Team name, status, registration dates, register link, address, grades, schedulePinwheel — live via the function, with last night’s sync as the fallback
Coaches listedPinwheel volunteers + OS-assigned coaches, merged & de-duplicated
“Additional Information” noteLMR only — RD-written in Website Info
Registered counts, financials, anything boy-levelNever here — that stays inside the sign-in-only tools

Good to keep in mind

  • “Live” means about two minutes. The live layer is cached for ~120 seconds so it doesn’t hammer Pinwheel, so a change can take up to two minutes to appear.
  • Hiding a team is now a Pinwheel action. The live layer will add any current Pinwheel team that doesn’t have a WordPress card yet (this is what got the Early Bird teams showing without waiting for the sync). So unpublishing a team’s WordPress post no longer hides it — the overlay recreates the card from Pinwheel. To hide a team, cancel or close it in Pinwheel.
  • The baseline is the seatbelt. Every part of the live layer is best-effort: an OS hiccup drops the note or the OS coaches but keeps the list up; a Pinwheel outage falls back to last night’s cards. The list is built never to go blank.
  • The Dashboard hosts the function, but the list doesn’t read the Dashboard’s own data. get-teams-live lives alongside the Dashboard for convenience, but it talks to Pinwheel and the OS directly — the public list isn’t a view of your Dashboard dataset.

Reference page for LMR staff & RDs. If a card ever looks wrong on letmerun.org, this is the map of where each piece comes from — start with whether it’s a Pinwheel field (fix in Pinwheel) or an LMR field (fix in the Dashboard).