← All productsLaunch pending

WikiRace

Follow your curiosity. Fill your board.One match, many competing actions.

A multiplayer Wikipedia bingo game. Navigate articles, complete objectives, and race with friends while spectators follow the board.Article visits arrive from several players at once. WikiRace orders scoring in PostgreSQL, commits the result, then updates each player’s own view without mixing their progress.

RuntimeA Chrome extension sends page visits to Fastify. PostgreSQL stores the match; WebSockets tell clients when to refetch state.

Multiplayer scoring · implemented

From a Wikipedia page to everyone’s board.

Hover, focus, or select a step
  1. 01Read the articleExtension → FastifyTitle + categories + links
  2. 02Evaluate under lockPostgreSQL transactionPlayer + deadline + board rules
  3. 03Commit the resultPostgreSQL transactionCompletion / claim + win + revision
  4. 04Notify & refetchWebSocket → each clientChange notice → scoped state

PostgreSQL decides claims and wins. The socket announces a committed change; each client fetches its own view.

Step 01 · Extension → Fastify

Read the article

The content script reads the article heading, category labels, and page links. The background script checks the article URL and sends the event with the current player session.

Mechanism
DOM extraction is capped at 500 categories and 5,000 links.
Tradeoff
The payload comes from the client. It is not independent proof of fair play.

Step 02 · PostgreSQL transaction

Evaluate under lock

The API locks the game row, checks expiry and player identity, then compares the page data with the current board. Competing actions for that game wait their turn.

Mechanism
SELECT … FOR UPDATE orders mutations per game.
Tradeoff
One busy game serializes its writes; network arrival order can affect who claims first.

Step 03 · PostgreSQL transaction

Commit the result

Normal mode records progress per player. Lockout records only unclaimed squares and resolves player or team ownership. The result and any winner commit before notifications.

Mechanism
Changed state increments the game revision.
Tradeoff
A duplicate visit cannot earn an already-owned square again.

Step 04 · WebSocket → each client

Notify & refetch

The socket sends GAME_STATE_UPDATED, not the actor’s entire board. Each client refetches its own view; the extension rejects older revisions and responses from an old session.

Mechanism
Reconnect triggers a fresh state read.
Tradeoff
An extra read costs more than pushing one payload, but avoids replacing another player’s independent progress.

One broadcast cannot contain everyone’s progress.

In Normal mode, two players can have different completed squares on the same board. Sending the actor’s response to the room would overwrite the others’ views.

Broadcast a change notice and rebuild each recipient’s state instead.

Expiry must survive a rejected move.

If the round has expired, mutateGame commits the finished state first, sends its notice, and re-enters the action. A later rejection cannot roll the clock back to an active round.

The extra transaction keeps the deadline transition independent of action validation.

Simplified control flow

A move arrives after the round deadline.

Expiry must survive even if processing that move throws an error.

transaction 1:
  lock game → detect expiry → commit FINISHED
notify clients
transaction 2:
  read FINISHED → reject scoring write

Expiry and the rejected action use separate transactions. Normal and Lockout also retain different win rules: a bingo versus a majority of owned squares, with a full-board draw possible.

Tests & limits

  • Integration tests cover duplicate visits, independent Normal progress, finished-round immutability, team-majority wins, and full-board draws.

Source and tests were inspected, not rerun here. Public hosting and an external-device match still need qualification.

Source files & authorship

extension/content.ts and background.ts; games.routes.ts page-visit handler; game-mutations.ts; game-engine.ts; integration/games.test.ts. Source inspected 29 October 2026; no new multiplayer or public-host qualification was performed.

Product direction: Jaxson Mercer. Development uses AI assistance.

Screenshots

The idea

What if a Wikipedia rabbit hole became a shared game?

WikiRace brings a playful experiment into the collection: browsing Wikipedia becomes a shared competition. The interesting part is the connection between discovery and strategy—what you find, what you claim, and what the other players do next.

WikiRace turns browsing into a multiplayer bingo challenge. The page you visit can satisfy an objective on the board, while the other players’ choices change what happens next. A separate spectator view makes the match understandable to people watching.

Follow a link. Make a move.

In use

From a page visit to a shared result.

  1. 01

    Get into the same game.

    Players join a lobby, ready up, and start a round with a 25-square board. The local implementation supports individual and team play.

  2. 02

    Browse toward an objective.

    The Chrome extension reports Wikipedia page visits. Normal mode tracks each player’s progress toward bingo; Lockout makes claims a shared competition.

    See player board
  3. 03

    See the match unfold.

    Players receive state updates, while a separate live board presents progress for spectators. The screenshots use a synthetic two-player match.

    See spectator board

Who it’s for

Built for people who want to explore Wikipedia competitively, with a viewing experience for friends or a stream. The game is implemented locally; public hosting is still pending.

The next question

Qualify the game on its intended host and real extension/browser setup, including reconnection and the spectator display, before opening a public play link.

Launch pending

WikiRace’s public launch is pending hosting setup. The local game is implemented; a public play link is not available yet.