VarsityApex is a demo, experiment and idea all at once. If you read through this entire post, you'll discover -- both through words and some grisly screenshots -- why this idea is kind of novel in its own way.

These days, local papers are decimated and even the big dailys of major cities are massively paywalled. Gone are the days mom and dad picked up the paper and did a cutout because you were featured in it.

Even small local publications don't let you view much without a subscription, because they have to pay one freelancer to traverse the area taking photos at games, writing news stories and covering things they think will get press. Without this layer of infrastructure, school sports wouldn't be covered by anybody.

If you're a casual who just wants to check-in on your second cousins cross-country meet from across the country? You might be out of luck though.

Knowing how difficult it is to get good data and having looked at a few high school state association websites, not to mention my own league not having anything online, it was a problem I've been familiar with in my 10+ years as high school coach.

Because this wasn't my first foray into designing a high school rankings-style site, it was a little easier to know what to do.

As an active high school coach, I built oregontennis.org, which is the only statewide high school team tennis ranking anywhere in the the US, such systems are common for team sports like basketball or football, but not a grafted together team sport like tennis which is a bunch of individual matches aggregated into a dual meet.

How VarsityApex Works

The short version of what's going on here in the demo:

Your school, your league, and your state association can each run their own site and the results still flow between all three. Nobody has to buy the same product or be a customer of the same company.

It reads the files schools already produce. Hy-Tek meet printouts, swim exports, scorebook spreadsheets, dual-match cards. Most sites will let you upload them, but it's difficult to extract data from them. It's a lot easier now and makes it more user friendly than sending people to 100 different sites to view high-level results.

It works for every sport. Most systems are built around "two teams, one score each," which cannot express a track meet — so track, swimming, wrestling, golf and cross country get a PDF while basketball gets a website. VarsityApex models three shapes — meets, duals, games — which covers all of it, including the activities associations sanction that aren't sports at all: marching band, choir, debate.

Records belong to the school. They live in the school's own repository, in an open format, not in a company's database. Built to publish as standard.site records, so the results are subscribable, not just viewable. If you want to leave, you already have everything.

An athlete has a page that tracks their results across sports, for all four years of high school. This was just a feature I wanted for myself, a kid who plays three sports could see their player page with all of the sports on it.


High school sports don't have one universal way results get recorded. Some sports are still basically manual data entry: somebody enters the final score, individual player statistics or each line of a tennis match into a website, spreadsheet or scorebook.

Swim results in AP format

VarsityApex can read that published file back into structured results.

Once they're normalized, the rest of VarsityApex doesn't need four separate ideas of what a result is.

Underneath it there are three broad contest shapes: GAME, DUAL and MEET. A football or basketball game is a GAME. Tennis and wrestling can use DUAL. Track, swimming, skiing, golf and the activities with larger fields use MEET. Sports supply the details on top of those structures.

Even the concept of a "score" gets slippery. A mark might be a time, distance or height. Golf and bowling use tallies differently. Gymnastics and competitive spirit have judged scores. Music can have adjudicated ratings. Debate can care primarily about placement. The schema has to preserve what the result actually means instead of coercing all of it into the same numeric field.

Getting the file parsed still isn't sufficient. The imported names also have to connect to the schools already in the system.

A school might appear with High School on one export, an abbreviation on another and a name physically chopped off at the edge of a PDF column somewhere else.

VarsityApex runs those names through a resolver using exact names, normalized forms, known aliases and progressively looser matches. It records how the match happened. Most importantly, it can decline to resolve something. If Copper Lak could reasonably mean Copper Lake, Copper Lake East or Copper Lake West, it reports the ambiguity.

So the workflow looks something like:

whatever people already use → extraction → normalization → identity resolution → validation/review → durable contest record

and only after all of that do you get:

school site / conference / state association / standings / bracket / feed

This is also why I think the ATProto part has some legs beyond sports. ATProto becomes useful at the point where you've turned the messy thing humans already produce into a durable, attributable record that several different organizations and applications may need to use.

There are so many legacy modernization projects that are stalling heavily, largely because approaches to cleaning old records don't jibe well, and it's the sort of consequential choice that if you choose wrong, it costs you time, momentum and perhaps your job.

Thankfully, this is an important yet benign use case for looking at that kind of complexity and that's why I like itas a first-run test case for improving data portability.

The ATProto piece isn't required to make this idea work, but it's a really good way to introduce the idea of data portability into a sector that's not really as aware of it.

If a school wanted to migrate their data, they don't have to drop all their historical records that someone might have handtyped at some point, they can just pack up their PDS and find another provider, design another site or integrate it elsewhere.

So now what?

I think we'll continue to build this out a bit, but the prototype itself is basically done. I've added a tour to enable me to show all of the various page types to someone and the functionality, but working with a potential conference, school or even state association to implement a real version of this is what would be next.

I have those relationships, but like I said, there's no real money in doing this, the associations and schools are cash strapped. Leagues are even poorer because they're funded by dues from the various schools, but operate on less than a shoestring budget. If you were rolling this out, it would almost have to be civic brigade style or grant-funded in some way, to make it worthwhile to prove the broaded capabilities of an ATProto powered school site.

I mostly wanted this as a proof of concept that I can tweak as time goes on.

The live site has a tour that lets you see the various page types in action, otherwise the site and its data are highly synthetic and fictional, but it's meant to create a realistic view of what a site like this could look like at each level.