Rollick OG was the original league — a close group of friends, ten teams, one draft, one sheet. It worked well enough that a second group asked if they could use the same setup. Thus Rollick 2.0.
We had two obvious options: fork the project for league #2, or add multi-tenancy. Forking is faster day one and a nightmare day thirty (any fix has to be ported twice), so we went with tenancy.
Minimal multi-tenancy
The trick was realising the only things that actually differ between leagues are:
- The roster (which players belong to which owner)
- The tab names in the shared Google Sheet
- A display name and URL segment
Everything else — scoring rules, ingestion, rendering, the leaderboard, the shareable snapshots — is identical. So we built a tiny league registry (a plain JavaScript object) that maps `l1` and `l2` to their config, and every route that needs to know reads from it.
The URL structure became /l1 and /l2, with legacy paths like /teams still redirecting to /l1 so old shared links keep working.
What didn't change
A deliberate decision: both leagues use the same scoring rules. If we let each league customise scoring, we'd have two rule sets to test, two sets of bugs, and endless arguments about "but our league awards 30 for a century". The consistency is worth more than the flexibility.
What would make us split the code
If a third league wanted substantially different rules — say, Test cricket scoring, or a Hundred/100-ball format — we'd probably pull scoring out into pluggable strategies. Until then, two leagues, one engine, zero drama.