Skip to content

League Builder

Water Polo League Builder. The full guide.

Run an entire water polo season: round-robin, single elimination, Swiss, weekly pods, multi-club. From the setup wizard to publishing your public league page, everything in one place.

  • Six league formats
  • Auto-schedule a season
  • Google Sheets write-back
  • English, French and Spanish

What’s new: May 2026

  • Phase model: split your season into phases (preseason, regular, playoffs), each with their own standings, stats and player stats.
  • Edit modal for each game: fix the score, date and time, court, exclusions, cap colors and the referee from one tile, then finalize again.
  • Action Log entry: log a full play-by-play, event by event, from a paper game sheet for games scored on paper.
  • Live Dashboard: a league-summary card: divisions, teams, players, finalized vs. live vs. upcoming, with a phase breakdown.
  • Sheet write-back: every finalized score writes to your Google Sheets workbook in seconds: Schedule, Standings, Player Stats and Game Sheet tabs.
  • French and Spanish: the scorer and the public league page localize to your league’s language, detected per league.

Get started

League Builder turns the live tournament platform (spectator pages, the live scorer, the bracket engine) into a multi-week season. Subscribe, open the Leagues tab, run the wizard, publish.

What is League Builder?

League Builder is the season-management module of Eggbeater. It takes the live tournament platform (the spectator pages, the live scorer, the bracket engine, the host backend) and stretches it across a multi-week season. One weekly preset schedules every game. Live standings update as games finalize. Spectators follow live scores as “Week N · vs Opponent,” not only “next game.” When the season ends, archive it and mint a fresh code for next year.

League Builder is live in production. Its first real season (divisions, cross-club standings, Sheets auto-sync) ran on it from the first week to the playoffs, and shaped what you read here.

Subscribe to a league plan

Pick Club League ($99/season, single club) or Multi-Club League ($249/season) for a regional season with visiting clubs. See “Which plan?” below for the decision guide.

Open the Leagues tab

Sign in at admin.eggbeater.app. The Leagues icon lives in the Tournament group of the sidebar, marked with a crown. The crown flags Eggbeater’s premium tools (Director, Leagues, Archive and Recovery all carry it), so it tells you what kind of tool this is, not what you have bought.

Set up your league

Tap Create a league. The wizard collects the league name, season label, divisions, teams, format and points policy. Auto-schedule from a weekly preset, or import from a Google Sheet. Both are covered in detail below.

Publish

Hit Publish League. A 6-character share code goes live with a public spectator address. Visiting clubs import with the same code, spectators follow at the address, and a search-friendly /leagues/{slug}/ page is published for you.

Which plan?

Two league plans, one decision. If every team belongs to your club, Club League is the right call. The moment a team from another club joins, the league becomes a multi-club event. That is Multi-Club League.

Club League · $99 / season · single club

Everything you need to run an internal or rec league where every team belongs to your club:

  • Round-robin, single elimination, double elimination, Swiss, weekly pods, or pools to bracket
  • Auto-schedule from one weekly preset
  • Live standings and configurable tiebreakers
  • Live scoring by cap number, on the record, driven by a player picker
  • 3rd-place and 5th/6th placement brackets
  • Rules to hide standings until week N
  • Public spectator page and a /leagues/{slug}/ page

Multi-Club League · $249 / season · multi-club

A regional season across multiple clubs. Everything in Club League, plus:

  • Everything in Club League
  • Participating teams from multiple clubs and cross-club standings
  • Visiting clubs’ spectators get the public spectator page free
  • Google Sheets import with reusable column templates
  • Sheets write-back for the whole event with live status sync
  • Calendars per division (Saturdays, Sundays and so on)

You only need one

Multi-Club League includes every Club League feature. You do not need both subscriptions. The admin paywall passes single-club gates for either plan. Multi-Club League additionally opens the multi-club gate. Pick the one that matches who is playing.

Build your league

The setup wizard walks four steps: league identity, divisions and teams, format and schedule, then rules and publish. Already have a schedule in a sheet? Import it instead.

Setup wizard: what it covers

On the Leagues tab, click Create a league. The wizard steps through four screens. You can go back at any point, but it is a modal, not a saved draft, so finish it in one sitting:

  1. League identity. A league name (for example “Harbor Spring League”), an optional season label (“Spring 2026”), and a league ID (a lowercase slug, generated from the name). The ID becomes part of the public address: eggbeater.app/leagues/{slug}/.
  2. Divisions and teams. Add one or more divisions, each with a name (“Division 1”, “14U Girls”) and a list of teams. Paste team names one per line, or import from a sheet later. Up to 16 teams per division. Reorder for seeding.
  3. Format. Pick one format per division (see League formats below). The most common are round-robin (every team plays every other once) and Swiss (paired round by round).
  4. Schedule preset. One weekly preset schedules every game: first game date (Eggbeater calculates the rest), day of week per division, game slots (start times, court names, game length), and minimum rest between a team’s games.
  5. Points and tiebreakers. Default points policy W=3, T=1, L=0 with optional shootout adjustments. Default tiebreaker chain: points, head-to-head, goals against, goals for, goal differential (capped), name. Move any tiebreaker to reorder.
  6. Generate and save. Tap Generate Schedule. Every game lands on your schedule with court stamps, team IDs and division IDs. Review on the Leagues tab, and when it looks right, hit Create & publish league. That writes the season and puts it live in one action.
Afterwards, Edit league changes the name, season label, tier, divisions and teams. Format, schedule and tiebreakers are set at creation. To change those later, import the config again as JSON or rebuild the affected games.

League formats: pick what matches your season

Eggbeater supports six league formats. Each division can run a different one:

  • Round-robin: every team plays every other once (or twice, double round-robin). Best for 4 to 12 teams.
  • Single elimination: a bracket of 4, 8 or 16, losers out. Optional 3rd-place game and 5th/6th. Best when you want a clear winner.
  • Double elimination: a winners bracket and a losers bracket. A team must lose twice. Forgiving for teams with one bad loss.
  • Swiss: teams paired each round against opponents with similar records. No team is eliminated. Best for medium to large fields (6 or more).
  • Weekly pods: each week is small pods with mixed, court-ordered games. Different opponents every week. Good for casual rec leagues.
  • Pools plus bracket: pool play seeds a playoff bracket. Eggbeater generates the bracket from final pool standings with the Auto-Build Playoff Bracket button.
Swiss leagues: when the regular round finishes, click Generate Next Round on the Leagues tab. Eggbeater pairs teams with similar records and avoids rematches where possible. Run as many rounds as you planned in the preset.

Importing from a Google Sheet

If your league schedule already exists in a Google Sheet (or Excel or CSV), skip the auto-scheduler and import it. The wizard maps your columns to Eggbeater’s game fields and saves a reusable column template, so importing again next season is one click:

  1. Open the import wizard. On the Leagues tab, tap Import from Sheet (in the Leagues setup actions). It opens as a modal.
  2. Paste the sheet link or CSV. Paste a Google Sheets link anyone can view, or paste rows directly. Eggbeater detects the header row automatically.
  3. Map columns. Match each detected column to an Eggbeater field: Date (required, ISO or M/D/YYYY), Time (24-hour or AM/PM), Court / Pool / Venue, Team 1 / Team 2 (required; must match teams defined in your league), Division (optional; defaults to the only division), Week / Round (optional, recommended for season-aware views).
  4. Preview and save. The wizard previews every parsed game and flags team-name typos that prevented an import (in red). Fix the error or field. Your column mapping is preserved.
  5. Save the column template. Tap Save mapping as template and name it (“Harbor Spring Format”). Next season, importing the same sheet applies the template automatically.
Team-name matching is strict: “Pacific Waves” and “Pacific waves” are different teams. Use the team-rename feature in the setup wizard if your sheet’s name differs from your roster, or fix them at the source before importing.

Standings

Standings recompute on every finalize, with a fully configurable points policy and a tiebreaker chain you can reorder. Hide them until you are ready, and run cross-club leagues where visiting clubs follow free.

How standings are computed

Standings recompute automatically every time a game finalizes. Each team row tracks:

  • GP: games played (final scores only; games in progress do not count)
  • W / L / T: wins, losses, ties (regulation)
  • SCW / SCL: shootout wins and losses (when enabled in your points policy)
  • GF / GA / GD: goals for, goals against, goal differential
  • Pts: calculated from your points policy. Default: W=3, T=1, L=0, SCW=2, SCL=1

Configurable points policy

The points policy lives in your league config. Edit it any time to change:

  • Regulation: W, T, L point values
  • Shootouts: separate values for SCW and SCL (when shootouts are enabled)
  • Forfeits: point values for forfeit win and forfeit loss
  • Bonus points: for goal-differential bonuses, blowout caps and so on

Phases: segment your season (added May 2026)

Leagues with multiple stages (preseason exhibitions, regular season, playoffs) configure phases so standings and stats segment correctly. Each phase has:

  • ID: a slug (regular-season, playoffs)
  • Name: a display label (“Saison régulière”, “Saison éliminatoires”)
  • Type: regular, playoff, preseason or exhibition
  • Counts toward standings: yes for regular and playoff, no for preseason
  • Each game has a phase field. Use a game’s Edit button to change which phase it belongs to. Mark a game Exhibition and it will not count toward standings. Phase pills on the standings and stats tables let spectators filter by phase.

Tiebreakers you can reorder

The default chain is points, wins, head-to-head, goals against, goals for, capped goal differential, name. In the wizard, use the arrows to move any tiebreaker up or down, or switch one off entirely.

  • Head-to-head only applies when exactly two teams are tied. It uses results of games strictly between them.
  • Capped goal differential means goal differential is capped (default ±10) to keep blowouts from skewing the tiebreaker.
  • When teams are still tied after the full chain, the final fallback is name (alphabetical). Predictable, but rarely decisive in practice.

Standings visibility rules

For fair-start leagues, you can hide public standings until you are ready. Two policy options, set in the wizard:

  • Hide until week N: standings hidden until week N’s games are finalized. Default: 0 (always show).
  • Hide until games played: standings hidden until N total games are finalized across the division. Useful when seasons start with mismatches.
What spectators see when hidden: a polite note explaining the policy, for example “Standings open after week 3.” The team’s Leagues tab still shows the live table. Only the public spectator page respects the rule.

Multi-club leagues

A multi-club league has teams from more than one club. The host club publishes the league and owns the package. Visiting clubs manage their own teams’ games, rosters and schedules from their own admin panel, all of which sync back to the host’s standings in real time.

  • Participating Clubs panel: on the Leagues tab, expand it to list every club involved. For each: a Display name (shown on the public page and the team picker) and a Club ID (the slug in the /?join=CLUB_ID links visiting clubs use).
  • Free spectator access: under Multi-Club League, every spectator from every visiting club gets the public spectator page free under your umbrella, with no separate Premium Spectator subscription needed. They open app.eggbeater.app/?join=your-league-{code} and see standings plus their team’s schedule.

Run the season

The Leagues tab is one cockpit for the whole season: dashboard, console, standings, publishing. Score live at the desk, publish your share code, and let the console catch anything that goes sideways.

The Leagues dashboard

The Leagues tab is a full-screen cockpit mirroring the Director tab’s hardware, condensed for league hosting. Every card you need is on one screen:

  • Live Dashboard: a league-summary view (May 2026): total divisions, teams, players, roster size, total games, finalized, live now and upcoming, plus a phase breakdown.
  • Live Game Console: a live grid of games. Every tile has Edit, Lock and Repair Stats actions.
  • Standings (Schedule): a unified table grouped by phase, with date and time, teams, final scores and status badges.
  • Player Stats: sortable by goals, assists or steals, default top 10 with a “Show all” expansion, rendered from the same event-by-event aggregation as tournaments.
  • Publishing: share code, public address, copy and open, export to Google Sheets, and archive when the season ends.
  • Scorer Display: toggles per league for which optional stats appear in the scorer.
  • Logo Registry: universal and club logos by team name. Powers spectator cards, notifications and Live Activities.
  • League Rosters: restore from a league import or a last-tournament import. Edit players per team.
  • Participating Clubs: the multi-club list of display names and club IDs for deep-linked spectator access.
  • Past Leagues: archived seasons with frozen standings, final game state and the original share code preserved.

Publishing your league

Hitting Publish League on the Publishing card packages the season to the Eggbeater backend, mints a 6-character share code (or restores an existing one), and exposes:

  • Public spectator address: app.eggbeater.app/?join=league-{code}. Anyone with the link sees live standings, schedule and scores. No account required.
  • Share code: 6 characters. Visiting clubs use it to import their schedule into their own admin.
  • Landing page: app.eggbeater.app/leagues/{slug}/. Generated for you and indexable by Google, with your league name, season and divisions.
After publish, the marketing site picks up your league on its next static rebuild. The /leagues/ index lists every published league. Each has its own page with division standings and club info. Rollback: the Rollback button reverts the most recent publish. Edit your config locally, then publish again.

Live scoring and the Game Console

Each league game is scored with the same guided Eggbeater scorer. The volunteer taps Score this game, chooses Tournament / League, and enters the scoring password. The board opens directly on the live game (no game-picking, no code to type). They tap the action (goal, assist, steal, save, exclusion), tap the player, and the scoreboard updates within 5 seconds on every spectator’s screen. To end the game they tap End Game and confirm. Referee sign-off is optional and off by default. Turn it on from the Scorer Display card (below) and finalizing then asks the scorer for the referee’s name, with the final showing “Signed off by [referee].” There is nothing league-specific to learn at the desk. Set the scoring password on the Publishing card.

  • Live Game Console: the host’s fallback when something goes sideways: a real-time grid of every league game in the next few hours, with one-click finalize (a scorer forgot to end the game), score override for desk corrections, and lock and reset for adjusted results.
  • Scorer Display: toggle which optional stats appear: Goals (always), Assists, Steals, Saves, Exclusions, 6-on-5. It also holds the “Require referee sign-off” toggle (off by default). Flip it on and ending a league game requires the referee’s name to finalize. Changes take effect when you next publish the league.

Data and sync

Logos and rosters feed every spectator card. Finalized scores write back to your Google Sheets workbook. Live Activities and push keep spectators in the loop. A clean archive freezes the season when it is done.

Rosters and logos

Build every roster and logo once, shared across every spectator card, notification and Live Activity:

  • League Rosters card: restore from a league import or last-tournament import. Each roster has Team, Cap #, First name, Last name and optional Division. When a spectator selects their team, the roster powers their “My Player” card.
  • Cap number to name lookup: the Goalie name picker in each game’s Edit modal maps cap # to player name. The resolved name is saved, so the goalie shows up by name, not number.
  • Alignments with clubs: the Alignments card maps club logos onto each cap. Each team’s two logos (light and dark) feed the spectator cards.
  • Logo Registry: universal logos (shared across every Eggbeater club) plus club overrides in your league’s team data. Powers cards, widgets and Live Activities. Paste in bulk or upload an alias list.

Sheet write-back (rewritten May 2026)

Eggbeater can mirror your league to a Google Sheets workbook that updates itself as scores finalize, in parallel with your original spreadsheet:

  1. First export: sign in and create the workbook. The first time, Google opens its consent screen and Eggbeater creates a workbook in your Drive. Click Allow.
  2. Auto-sync on every finalize. From that point on, every game finalize writes the relevant tabs (Schedule, Standings, Player Stats, Game Sheet) within about 5 seconds.
  3. What lands in the workbook. League Overview, Master Schedule, Standings (combined and per division), Player Stats and Game Sheet tabs for each game, all phase-aware if you have set up phases.
  4. Export again to refresh tabs. If you need to rebuild, the Re-export to Sheets button refreshes the workbook in place.
  5. Share with your league admins. The Publishing card has a copy-link for the workbook so other league admins can view it.
Migration path: the workbook mirrors your original spreadsheet while you verify the data matches. Once you have confirmed, Eggbeater’s workbook can become the source of truth.

Live Activities and push reminders

Every league that runs on Eggbeater gets the native spectator surfaces, phrased for a multi-week season:

  • League-aware reminder copy: when a spectator subscribes to push for their league team, reminders read “Week N · vs Opponent” so a multi-week season feels like one continuous event.
  • Lock-screen Live Activity (iPhone): the league’s live game shows on the lock screen and Dynamic Island, in the league’s language (French, English or Spanish).
  • Apple Watch: the watch app shows your team’s league game, schedule and live score on the wrist.

Season archive

When your league season ends, archive it on the Publishing card to freeze everything cleanly:

  • Archive this league: freezes final standings and the final game state, and preserves the original share code for the record.
  • Starting next season: after archiving, click Create a league to mint a fresh code. Start from scratch (new divisions, new teams, new schedule), or Clone from archive (last season’s structure, rosters cleared).
Why archive instead of renaming? Archiving preserves the historical record of the season (it lives at its /leagues/ page and stays publicly indexable), while the live tools move on to the next season. Visiting clubs and spectators see the league move from “live” to “archived” cleanly.

Questions

Common questions

Can a club run a tournament and a league at the same time?

Yes. Tournament Host and Club League / Multi-Club League coexist. The Director tab manages tournaments. The Leagues tab manages league seasons. They publish to separate share codes and do not interfere with each other.

What happens to subscribers when I archive a league?

Nothing breaks. Existing spectators keep following until the share code’s natural lifetime (about 30 days) expires. After that, they age out automatically. Archiving freezes the final standings and game state for the record.

Can I switch a league from round-robin to Swiss in the middle of a season?

Not recommended. You would be changing the format definition while games are in flight. If you must, edit the league config carefully, then export the round-robin schedule and seed it again in the new format’s structure. Better path: finish the current format, archive, and start the next season.

Do I need both Club League and Multi-Club League?

No. Multi-Club League includes every Club League feature. Pick the plan that matches your league. Choose Multi-Club and your subscription opens both the single-club and multi-club gates.

Can spectators see live scores during the season?

Yes. Every league game updates the public spectator page within 5 seconds of a scoring action, and standings recompute live on every finalize. No refresh required.

What about the iPhone widget, Apple Watch and Live Activities?

Every league that runs on Eggbeater gets the native surfaces. The Apple Watch app shows your team’s league game, and Live Activities for iPhone include the league and week. See Live Activities and push reminders above.

Ready to run a season?

Print the one-page Quick Start for your participating clubs and volunteer scorers: six steps from setup to publish on a single sheet. Or go straight to the Leagues tab.