Jason Von Holmes
Back to all projects

Forkline

A turn-based space trading sim for phone and PC, specified, tested and shipped in public. This page covers how it was built and the evidence behind each change.

Play Forkline Live, in playtesting

Goal

Classic buy-low, sell-high trading games have a great loop and very little depth. I wanted one that teaches something real: distance and time in space, how prices respond to supply, and what debt costs a business. It had to work for players as young as 8, so it targets an E for Everyone rating.

It's also the first product I'm taking all the way to launch, on Google Play and the web with one login, as proof of how I build systems: requirements first, every decision logged, every change tested before it ships.

The game

You run a freight probe that starts with a $60M loan. You trade across ten stops, from low Earth orbit to Tau Ceti. Travel is free, but every day adds interest and moves the markets. When the mission ends, a copy of you boots up with everything you earned.

  • Market events grow from rumors into shortages or gluts, then worsen, spread, rebound or fade.
  • Shipper freight and passenger contracts ride alongside your own cargo, so a full hold is a planning problem.
  • Prices from the stars arrive days old because of light-lag.
  • Banks, insurance, a bonded warehouse and a fork foundry give every stop a role.
  • Short tips teach each idea the first time it matters, capped so they never stack up.
Three phone screens: the market during a shortage, the route list from LEO to Tau Ceti, and the end-of-mission fork screen
Trade, fly, fork: the three steps of a mission.

System

There is no game server. The game is a single HTML file on GitHub Pages at playforkline.com; saves, records, tips and sound settings stay in the player's browser. The backend is two Supabase functions: one takes tester reports, and one runs an optional crew list for adults.

  • Tester reports need no code. The report function screens out bots first: a hidden honeypot field, a 20-second minimum, Cloudflare Turnstile, 5 reports per hour per connection and 300 a day.
  • The crew list is adults only and optional: double opt-in by email, a send cap of 90 emails a day, and one-click unsubscribe. Agents can count its rows but never read them.
  • Privacy by design: reports collect no names, emails or locations; players under 14 need a grown-up's OK; connection addresses are kept only as salted hashes for 2 days; reports are deleted after 12 months.
  • Releases go to a preview site first and reach playforkline.com only through a pull request I merge.
C4 container diagram: the player reaches playforkline.com on GitHub Pages (homepage, game, report page, crew page); the report and crew pages call two Supabase functions that write to Postgres; outside services are Cloudflare Turnstile, Cloudflare Web Analytics, Resend email and Namecheap DNS; studio operations hold AI agents, GitHub, the tracker and the Review Desk, with Jason merging pull requests and answering approvals
C4 container view: what runs where, and which outside services it depends on.
Data flow diagram with five trust boundaries: player device, public web, studio backend, data at rest and studio operations. Game state stays in browser storage; reports go through the report function to tester reports; connection addresses are stored only as salted hashes; adult crew sign-ups go through the crew function to the crew list and a confirmation email; agents read reports only and count crew rows
Data flow with trust boundaries: what player data exists, where it goes and how long it stays.

Testing

Every gameplay change runs against the previous version on the same seeds before it ships: 40 missions with a trading bot and 20 with a contract-only bot that models a cautious beginner. Results go into a balance-test log with a pass or fail verdict.

ProblemBeforeAfterBuild
Contract exploit windfall$102.7M$1.6Mv8
Beginner path ending in debt11 of 20 runs0 of 20v9
Stranding scenarios with no way out4 of 40 of 4v9
Best Trades profit estimate error−$11M to −$32Mwithin $0.8Mv11
Goods vanishing overnight10.3%0%v14
Median daily price move13.4%2.3%v14
Best-route margin160–1,070%35–62%v16
Bot missions ending negative6 of 400 of 40, every build since v20v20–v25

From v20 on, every economy change was tuned back into a fixed target: a median 45-day result of $150M–$250M with no losing runs. Medians since then: $192M, $210M, $199M, $263M (5% over the band by design, after freight and passengers added a second income stream) and $237M.

Four builds, same mission

The same seed and screen in four versions shows how the design moved from physics accuracy toward clear decisions for the player.

Route screen in v17, v20, v22 and v25.2: fuel in tonnes and delta-v per trip, then one fuel price per trip, then travel days only
Route screen: fuel as cargo, then one fuel price, then free travel where days are the cost.
Market screen in the same four builds, ending with a How it works tip for new players
Market screen: propellant and three currencies, then dollars only, then full markets, then a first-day tip.

From report to fix

Every playtest finding becomes a tracked action with an owner and a release. Ten findings from development playtests shipped, each on the day it was reported.

FindingFixShipped
Best Trades profit far below actualPer-trade profit; trip cost shown oncev11
Forecasts wrong on arrival; buy Max showed 0Stable trend-based markets; Max fixedv14
$103M cash but a $6.8M score, unexplainedLoans and savings shown in the headerv15
A full hold stranded the probeMax leaves room; help names the real blockv19
Fuel costs breaking the economyOne fuel price, then no fuel costv20, v21
Debt still growing; thin marginsA market at every stop; event treesv22
Contracts impossible to fill in timeFillable requests; freight and passengersv23
Building forks lowered the scoreForks count toward the score, less wearv24
New players miss services and milestonesNotices system with 16 tipsv25
First outside tester (age 8–12): didn't know the goal; three words unclearGuided first trade; tap-to-explain wordsv25.6

Three decisions

Removing fuel cost

Problem
Fuel was modeled as cargo with real delta-v. It caused a run of stranding bugs across ten builds and consumed 58% of gross trade income, so players managed fuel instead of trading.
Options
Fix fuel-as-cargo again; simplify to one price per trip; remove it.
Decision
Simplify, then remove. A trip now costs days: interest, markets that move and deadlines that close.
Evidence
Removing fuel on the old price bands pushed the median to $548M. Narrowing the bands brought it to $210M with 0 of 40 losing runs; the beginner path reached $63M with 0 of 20.
Trade-off
Less physics in moment-to-moment play. The rocket equation moved into the in-game reference as learning content.

From a tester code to server-side bot checks

Problem
The report page is public. Bots or trolls could pollute the data, and collecting names or emails would add privacy and under-14 consent burden.
Options
An open form with a captcha; player accounts; a code sent after a player shares a gameplay screenshot.
Decision
First, a rotating code checked by row-level security (v25.2). The first reports showed the code step was the biggest barrier for new testers, so v25.6 replaced it with checks inside a server function: a honeypot field, a 20-second minimum, Cloudflare Turnstile, 5 reports per hour per connection and 300 a day.
Evidence
Code phase: SQL tests blocked missing and wrong codes, and codes were unreadable publicly. Bot-check phase: database tests for the rate limit and daily cap, and the first report through the new path passed Turnstile the afternoon it shipped.
Trade-off
The form now depends on Cloudflare Turnstile, and no check stops every determined spammer, so every report is still triaged before it counts.

Counting forks toward the score

Problem
In a development playtest, building three forks left the score at $154M against a $263M bot median. A core feature punished players for using it.
Options
Count nothing; count full build cost; count build cost less wear.
Decision
Build cost less wear: 1/60 per day in service, never below 20% salvage value.
Evidence
Full cost turned forks into free money, about +$120M for three forks built on day 5. With wear, bot scores were unchanged and only fork builders' scores rose.
Trade-off
Slightly more complex scoring, shown on the end screen and explained in the in-game reference.

Working with AI

Forkline is built with AI-assisted coding (Claude). The split of work is deliberate:

  • My part: requirements, playtests, every logged decision, release approval, and the call on what ships and what waits.
  • The AI's part: implementing each change as a versioned patch script, writing the bot test harness, and reporting results against the targets I set.
  • The controls: a tracker with actions, decisions, releases and balance tests; seeded before-and-after tests on every gameplay change; one commit per release.

It's the same method I apply to compliance and documentation systems for small federal contractors: the AI does the volume, and the system keeps it accountable.

What's next

  • Public playtest at playforkline.com: anyone can play a mission and send a report, and testers whose feedback ships are credited in the game.
  • Planned for v25.8: a review of outer-world pay and a calm mode for players who find the screens busy.
  • Launch gates: at 25 verified testers, with players in every age group and an average clarity score of at least 4 out of 5, accounts and cloud saves come next. At 100 registered web players, Google Play work starts.

Last updated October 30, 2026. Numbers come from the project tracker's balance-test and release logs.