Case study · Todd Blocksom · 2026

HIDE/SEEK

A location-based multiplayer game that turns any neighborhood into a game board, for two to eight people, on foot, in an afternoon.

Built solo in seven weeks from first commit to TestFlight beta: product, design, iOS, backend, web, and release engineering. Now in public TestFlight beta.

Status · App Store submission in review

Role
Sole product, design, and engineering lead
Timeline
Seven weeks, first commit to TestFlight beta
Stage
Public TestFlight beta, App Store submission in review
Scope
iOS client, Postgres and PostGIS backend, spectator web app, operations tooling
Outcome
Shipped to beta with a privacy and retention architecture built for production

The origin is one sentence from the product spec, and it never changed: I wanted to play this with my kids, in whatever neighborhood we happened to be in, in a session short enough to fit a weekend afternoon.

The original spark came from Jet Lag: The Game, which proved that hide and seek turns deeply strategic once you add an information economy. Its ruleset assumes a country, public transit, and a full day, so almost nothing survived contact with a different audience, geography, and session length. Radii went from miles to hundreds of feet, hiding windows from hours to minutes, landmarks from train stations to mailboxes. The question economy had to be repriced around clues a child can act on while walking, and the round had to resolve inside an afternoon rather than a weekend.

Before there was an app, there was a summer of playing it by hand. We drew play areas on maps, dealt question cards on paper, tracked coins in a notebook, and texted photos back and forth. Each time we played, the zone got bigger and the round got more ambitious. That was the signal I trusted, and it is the reason the project was worth starting: the risky question, whether a neighborhood-scale version of this is actually fun, had been answered by people playing it before I wrote a line of code.

What was left was a tooling problem, and tooling problems are the safe kind to build. The app took over the map, the economy, the question deck, the timing, and the location updates, so that none of it had to be the point. It exists to clear away the administration and leave more room for the suspense.

  • Phone screen titled Choose your photo, listing photo challenges a Seeker team can buy with coins: Street Sign at 50, Digits at 50, Curb Appeal at 50, Tallest Tree at 30, Long View at 30, with a coin balance of 300 in the corner.
    Seekers spend coins to buy a clue. The Hider is paid the same number of coins for answering it.
  • Phone screen titled Pick your next move, showing a grid of trap and power move cards: Pickpocket, Question Tax, Smoke Bomb, and Jammer, with a Jammer card enlarged over a Buy button priced at 15 coins.
    The Hider spends those same coins on traps and power moves. Every clue the Seekers buy gives the Hider another move.
  • Phone screen showing a thermometer answer reveal. Under the question Are we getting hotter or colder, the word HOTTER fills the screen in large white type.
    Calm at rest, loud at the moment it matters.

A SwiftUI client, a server-authoritative Postgres and PostGIS backend with 37 row-level-secured tables and 158 database functions, a web spectator view, a marketing site, load-testing tooling, and the release pipeline.

Counts verified against the repo, 21 July 2026.

  • 7
    Weeks to TestFlight beta
  • 40%
    Less websocket traffic
  • 750
    Automated checks, Swift and database
  • 24h
    Default retention for player and session data
  • Phone screen showing the HIDE/SEEK lobby: a join code of BH66, a map with an orange play-area circle drawn over New York, a 45 minute round length, and a lineup of one Hider and three Seekers above a Start Round 2 button.
    Setup is a join code and a circle on a map. No signup, no email, no printed materials.
  • Phone screen showing the in-round map from the Hider's own device. A banner reads YOU'RE HIDING above a 19 minute 26 second clock, Seeker pins move along the streets, coin pickups sit on the map, and the Hider's own position is marked inside a dashed circle.
    The Hider's own view. The Seekers' map is the same board with that pin removed at the database, not at the client.
  • Phone screen celebrating a catch: a large orange map pin over the words THE CATCH, then GOTCHA in heavy white type, and the line Jack tagged Todd.
    The tag only fires when two players are truly face to face. Making that reliable became one of the hardest technical problems in the product.
A band of night sky, deep indigo shading down into luminous blue.
  • Five specced screens and a database table, deleted in one review.

    Hider invites, buddy multi-select, and buddy invite modals all collapsed into a single self-serve toggle, on the grounds that the tap itself is the consent. The invite functions and the table went with them. I would rather delete a table than ship a confirmation dialog nobody needed.

  • No anti-cheat, on purpose.

    No photo freshness checks, no GPS spoof detection, no referee flow. This is a game played in person among people who know each other, and trust lets you cut entire branches of UI and server validation. Disputes resolve the way they always have: let's just replay that round.

  • Declining end-to-end encryption, with an argument.

    It would have been the impressive-sounding choice, but the server has to read coordinates to run the game at all, so encryption would have meant either breaking the product or building a facade. The real threat model for a family app with no signup is over-retention, not a hostile server operator. So I hardened retention instead: gameplay data purges within 24 hours of a session ending, and there is no cross-session identity to accumulate. The one exception is an opt-in playtest recording, off by default and deleted after seven days.

The target users were in the room from the start. My sons helped invent the game, and their friends widened the loop once it reached TestFlight.

The Scanner started as my youngest son’s request: a tool that points you toward the Hider. The request was right and the literal solution was wrong. Uncertainty is the core mechanic, and an accurate bearing would have collapsed the game he was trying to improve.

So it shipped as a Seeker tool costing 30 coins, returning one deliberately fuzzed bearing per five-second scan on a two-minute cooldown, computed server-side so the exact hiding spot never leaves the server. The feedback is haptic rather than numeric: the pulses tighten as you point closer, so you sweep the phone across the horizon and feel for it instead of reading a number off a screen. He got the feature he asked for. The game kept the uncertainty it needed. Users report the problem accurately and the solution approximately, and telling those apart is the job.

My other son proposed the Jammer: a way for the Hider to block questions and push the Seekers off the trail. It shipped as a placed zone that blacks out the map and locks the question menu, with a nested disable ring the Seekers have to physically walk to and then clear with a minigame. A feature request became a different kind of play, one that pulls people off the obvious path and back into the neighborhood.

Then the loop got wider than I planned. My kids sent the TestFlight link to their friends without being asked, and I started hearing about a new hide and seek app from other parents I had never told about it. That is not launch-scale growth and I would not dress it up as any. It is unprompted spread inside the intended audience, which for a pre-launch product is the strongest signal available.

Giving feedback is deliberately cheap. A tester can screenshot from anywhere in the app and file it, and the build notes ask for a third category alongside broken and confusing: or just not fun. That third bucket is the one worth having. Broken produces a fix. Not fun changes the roadmap.

  1. The Hider’s location had to be unknowable to Seekers. That is a database property.

    Seekers never receive the Hider’s coordinates, not live, delayed, or approximated. Game state is server-authoritative, and Hider pings are withheld at the database layer. The one directional hint in the game, the Scanner, is computed on the server and returns a bearing. The position it was derived from never leaves the server.

    During beta hardening I tested the live access model from a Seeker’s role, and found the locked hiding coordinate readable through three independent paths: a direct query against the round row, the realtime publication fan-out, and an ungated function. I closed all three.

    The lesson is where they were. Row-level security governed which rows a player could read, and said nothing about which columns rode the realtime publication or who could execute a function. Postgres grants EXECUTE to PUBLIC on every new function, and a changed signature creates a new function rather than replacing the old one, so a lock-down does not carry forward on its own. Each path needed its own control, and revoking default function access became a standing convention.

    A wide browser view of the spectator screen: a dark city map with Seeker pins and their walked trails, coin pickups scattered across the play area, a join code and QR code in the top corner, and a bottom bar reading find time 35 minutes 39 seconds, 185 coins, last answer HOTTER.
    The party screen at watch.myneighborhoodgames.com. It polls, and it shows the board from the Seekers’ perspective. The Hider is not on it unless the Hider or their buddy shares a separate reveal link.
  2. GPS cannot tell you that two people are standing next to each other.

    The tag is the emotional peak of every round, and GPS accuracy under trees and between buildings is tens of meters. So the catch mechanic does not use GPS. It uses ultra-wideband peer ranging through Apple's NearbyInteraction framework, the same technology behind AirTag Precision Finding, which gets sub-meter accuracy under two meters. Devices without the hardware fall back to Bluetooth signal strength with a wider radius.

    Then the product decision that cuts against the technology: the app deliberately does not help you find anyone. The takeover only fires under a meter and a half, by which point the two players are already looking at each other, so it works as a celebration rather than a guidance tool. Finding is the player's job. The app's job is the moment.

  3. Cost was not the first scaling constraint.

    I built an instrumented match simulator that reproduces the real client’s network behaviour, so scale was measured rather than estimated from a spreadsheet: actual HTTP calls, realtime messages, database writes, and concurrency. The useful finding was that the infrastructure bill is not what breaks first. The realtime message rate is.

    Peer positions had been riding change events on the highest-volume table in the system, which produced oversized write-ahead-log frames and a pipeline that fell over at a realistic player count. I took that table out of the Postgres publication and replaced it with a throttled broadcast, asymmetric by design: Seeker ticks carry a position and apply on receipt, while Hider-side ticks are empty pokes that trigger a policy-filtered refetch. The Hider’s coordinates never ride the broadcast wire at all. Websocket traffic fell 40%. Privacy and performance wanted the same architecture, which does not happen often enough to pass up.

A band of crimson brushwork sweeping diagonally into grey.

The output came from a practice, not ad-hoc prompting: specs and implementation plans committed to the repo as first-class documents, written behavioral guidelines for AI contributors, a separate git worktree per feature, and pure logic factored out of stateful classes so it could be tested without the hardware.

What stayed human was the part that decides: scope, architecture, which tradeoffs were acceptable, and whether the result was good enough to ship. AI shortened the distance between deciding something and having it. It did not do the deciding.

The honest framing: the AI did not build this. The judgment calls were the actual work.

The beta has produced a strong qualitative signal and not launch-scale product metrics. The spec sets targets: session completion, a median hide of fifteen to thirty-five minutes, whether the economy gets used rather than ignored, and families starting a second session within the month. Those are targets, not results. They have not been instrumented at scale, and the next phase is finding out whether the experience holds outside the community that invented it.

What is instrumented is pointed at decisions rather than at a dashboard. The shop logs one row per card appearance, including the cards players look at and decline, because the pass rate is what exposes a pricing or balance problem. An opt-in playtest mode can record a whole session for design review, off by default, behind a consent banner and a persistent recording indicator, and held for seven days rather than the ninety originally specced.

HIDE/SEEK is in public TestFlight beta. The operating model behind it is the work I want to take forward.

I’m looking for a principal product leadership role where product strategy, technical architecture, privacy, and execution have to be held in the same frame.

Discuss a role

Join the beta