Skip to main content

Independent product

Every point has a story

Bowman World Cup Pool

Who owns Spain? Can I still win? I built a family World Cup pool around the questions that make a match personal, then kept refining it through scoring rules, a visual rebuild, and a deliberate archive. I directed the product, design, and development with three coding agents.

Stephen's owner scoreboard with rank, total points, remaining teams, and points by team
Open full-size image (opens in a new tab)
Your place in the pool and the teams behind it. The inspected application was showing bundled snapshot scores, as labelled beside the fixture status.Original capture of Bowman World Cup Pool · 17 September 2026
Contribution
Product design and AI-assisted development
Facts
Build story
June–July 2026 · from a team draw to a tournament companion
My work
Product direction, interface design, and development with coding agents
Built with
React, TypeScript, and Vite
Data
ESPN's unofficial public endpoints, local cache, and a bundled snapshot

A few teams to make every match personal

I wanted the family pool to answer the questions around the television: who owns that team, what did that result change, and is there still a way to catch the leader? Ten owners and a shared draw gave the tournament a smaller, more personal story.

The first version was a team generator. Once the draw was agreed, generating another one became the wrong feature. I fixed the allocation and removed regeneration. From that point on, the site’s job was to follow the agreement.

The draw became the starting point

The original draw grid assigns four teams to each owner across four tiers
Open full-size image (opens in a new tab)
The draw made the competition personal: four teams to follow, with the rank and slot behind each assignment.Original draw artifact · project archive

Start with the person following the tournament

A tournament table tells you who is winning. A family pool needs another layer: which teams are yours, what their results earned, and how far you are from the leader.

I organized the experience around owner pages. Each page brings rank, total points, the gap to first place, and team status into one overview. From there, you can inspect individual teams without losing the context of your place in the pool.

Open the score and see where it came from

At first, the plan still depended on a scorekeeper. I removed a dormant shared scoresheet, then went further: why ask someone to type results that were already public? The next decision removed manual score entry and derived points from match data.

That shifted the work from maintaining totals to making the rules understandable. A family pool needs a score people can question and an explanation they can find.

A total you can inspect

Brazil's expanded points breakdown with seven scoring events adding to 23 points
Open full-size image (opens in a new tab)
Opening Brazil's points breakdown reveals match results, group placement, and advancement bonuses. These seven entries account for the displayed 23 points in the captured snapshot.Original capture of Bowman World Cup Pool · 17 September 2026

A single total hides the rules. I put the scoring events behind an expandable summary, keeping the overview short while making the calculation available when someone wants to check it.

The scoring model derives points from match results and tournament progression. It replaces manual score entry with a shared set of rules applied to the tournament data.

The rules were part of the interface

Original scoring card listing match and advancement points and the fixed draw seed
Open full-size image (opens in a new tab)
The early rules card put the point values and draw seed where everyone could inspect them. This is an earlier rule version, not a reference for the current calculation.Original rules artifact · June 2026 project archive

The first design was not the last word

The early Night Match interface leaned into the atmosphere of a sports broadcast. As standings, fixtures, player data, and research accumulated, the page needed a clearer reading order. I moved toward a light sports desk with quieter styling and more direct labels.

The iteration changed more than the palette. “Pool pressure” gave way to “Today at a glance.” I kept standings beside matches, retained the direct owner links, and simplified the language around them.

Earlier: a broadcast-style dashboard

Early dark World Cup interface with a pressure summary above the leaderboard and match desk
Open full-size image (opens in a new tab)
The earlier Night Match design used a dense pressure summary, colored owner chips, and broadcast styling. This historical render contains a different scoring state from the later design.Earlier interface preserved in the project’s Story assets

Later: standings beside their explanation

Later light sports desk with owner navigation, standings, match results, and a latest-points list
Open full-size image (opens in a new tab)
The later sports desk pairs standings with the matches that explain them. Owner navigation stays close to the top; the points trail and rules support a deeper read. Historical capture; displayed scores are snapshot values.Original desktop capture · July 2026 project archive

I wrote the visual standard into the repository so the next coding session had the same reference. Tokens, page hierarchy, and copy guidance made the design direction available to every agent.

Who can still win, and what has to happen?

Near the end of a tournament, the useful question changes. Knowing who leads is less interesting than knowing whether anyone can catch them. I added a possible-finishes view that connects the remaining match outcomes to the final pool table.

The scenario engine enumerates the two semifinal winners, the champion, and the third-place winner. With all four matches still open, that creates sixteen result paths. Each path runs through the same scoring model as the actual standings, then contributes to each owner's best and worst finish, points range, and number of winning paths.

From tournament outcomes to family standings

Possible finishes view pairing owner finishing ranges with semifinal, final, and third-place selections
Open full-size image (opens in a new tab)
The scenario interface in its completed snapshot state. All four results are fixed, so the choices are disabled and only one standings path remains. The sixteen-path behavior for unfinished matches was reviewed in source, not exercised in this capture.Original capture of Bowman World Cup Pool · 17 September 2026

The number of winning paths is a count of possibilities, not a probability. The engine does not assume every outcome is equally likely. Completed matches constrain the remaining paths, and the interface can identify a locked podium or a fully settled table.

That makes the bracket personal. A match matters because of what it can change for the people in the pool, rather than simply because it occupies a slot in the tournament.

Follow a team into the match behind the points

The application extends beyond the leaderboard into group tables, team pages, match previews, and player statistics. Owner markers connect that wider tournament information back to the pool.

In the match-preview implementation, the owners' stakes appear before recent form, head-to-head history, and likely lineups. Additional match statistics and research events carry their own source notes. Missing context has an explicit unavailable state.

The statistics area separates scoring and assists from physical performance and research datasets. Speed, distance, expected goals, and team possession answer different questions, so their labels and units travel with the values. These are source-reviewed capabilities; availability depends on the corresponding feed.

Make the matchup personal

Phone-width match page showing Jake’s Spain versus Emily’s Argentina before form and lineups
Open full-size image (opens in a new tab)
Jake’s Spain versus Emily’s Argentina: the owners’ connection comes before form, past meetings, and lineups. The screenshot shows the archived application’s match data.Original 390px match capture · July 2026 project archive

Keep exploring beyond the table

Phone-width player statistics with scoring tabs and owner names beside players
Open full-size image (opens in a new tab)
The player desk connects individual performances back to the pool with owner labels. Scoring, running, and research remain separate views. Values shown belong to the archived snapshot.Original 390px player capture · July 2026 project archive

Add context without changing the score

Keep supplementary match and player data separate from the pool calculation. A richer preview should never silently change the rules behind someone's points.

Three coding agents still needed a design director

I worked with Claude, Codex, and Cursor. My contribution was deciding what to build, setting the visual direction, reviewing the result, and deciding what needed another pass. Shared repository guidance, scoped tasks, and verification checks made those decisions usable across sessions.

The build record documents a blank page despite passing automated checks. The lesson changed the process: inspect the actual page at desktop and phone widths, and keep screenshots beside the review. A passing check could no longer stand in for seeing the interface.

A review changed what “finished” looked like

Finish Ledger review comparing an approved final-state target with an implementation showing only two locked podium places
Open full-size image (opens in a new tab)
Target on the left; implementation on the right. The target shows three podium labels, but the reviewed implementation awards only the two places already locked. Third place keeps its numeric gap.Original target and implementation comparison · 15 July 2026 design review

The same decision at phone width

Phone-width review capture with Winner and 2nd labels while third place still shows a 28-point gap
Open full-size image (opens in a new tab)
A closer view of the reviewed behavior: the first two places have labels, while third still shows a gap. The mobile layout shortens the labels without announcing an unsettled result.Original 390px implementation review · 15 July 2026

The Finish Ledger is a specific example. The target pictured a complete podium; the implementation had to respect an unfinished competition. The July 15 review approved winner and runner-up labels while third place retained a gap. Celebration had to wait for the scoring model to establish the result.

I also recorded decisions to decline additional data integrations. Those written decisions kept later sessions from repeatedly reopening the same scope questions.

One set of results has to tell the whole story

Combining feeds created a less visible design problem. One source might know a match had finished while another still had yesterday's group table. Mixing them could award result points while losing the qualification bonuses that belong to the same tournament state.

I kept results, qualification, and final group placement together in one tournament object for scoring. The documented contract requires the fallback snapshot to contain both matches and group rows. Static fixture metadata can enrich the page, but it does not decide whether a match is final or a team has advanced.

This is the engineering behind a simple promise in the interface: the total and its explanation should agree. The same calculation supports the owner page, standings, and hypothetical finish paths. Repository guards and integration tests encode that boundary.

The application reads ESPN's unofficial endpoints in the browser. It keeps a local cache and a bundled snapshot as fallbacks. That avoids a separate scorekeeping backend, but makes the age and source of the displayed scores part of the interface.

The September portfolio review encountered the fallback state: owner totals and scoring details remained available, with a snapshot label and Retry. That recovery behavior is distinct from the deliberate archive described on the product’s Story page.

Make the source visible beside the score

Preserve the last available view and explain its status. A readable scoreboard should not imply that its data is current when the feed is unavailable.

Give the pool an ending worth keeping

As the remaining possibilities narrowed, the interface changed from following a competition to remembering it. The finish view replaced gaps with locked podium labels and kept the path through the results available.

The build record describes a deliberate July 20 freeze, and the product’s Story page labels its record archived. The live-data fallback remains a separate behavior in other inspected views. Preserving that distinction matters: an old score can be a recovery state or an intentional record.

The final screen remains part of the story

Preserved home screen with settled podium labels and no scheduled fixtures
Open full-size image (opens in a new tab)
The preserved finish screen gives the pool an ending: settled places and no scheduled fixtures. This older capture still carries a live badge; the current Story page separately labels its record archived.Original finish-state capture · project Story assets

What began as a draw became a place to follow your teams, question the score, and explore what could happen next. The strongest lesson for me was that the product kept improving when I changed the question—from “what else can I add?” to “what does someone watching this match need now?”

Results

  • A deployed family-pool application connecting the fixed draw, owner standings, scoring receipts, match context, and possible finishes.
  • A documented design evolution from the early dark interface to the lighter sports desk, with target-to-implementation reviews.
  • An archived build story preserving the product’s decisions, iterations, and finish state.

Evidence limit

Original project artifacts and September 2026 browser captures are shown alongside the build record and source review. Images contain application snapshot values, not independently verified tournament results. Historical targets, implementations, and current deployment states are labelled separately. Scenario enumeration and scoring contracts were reviewed in source; the upstream test suite was not rerun. No adoption, uptime, or measured usability improvement is claimed.

Resume and contact