Skip to content

Journal

Journal

Everything here is a write-up of work that actually shipped. A bug that reached production and what it cost. A decision taken on a live product and what it bought. An abstraction that held everywhere but the four places where it leaked. Predictions, trend pieces and posts written to reach a keyword are not what this journal is for.

The portfolio runs on one rule, and this page runs on it too: anything that cannot be verified against a shipped build does not get printed.

Each entry is written by Wyatt McPherson, who designed and built the product it is about. None of it is commissioned or ghostwritten. Nobody who was outside the repository at the time has drafted a word of it.

01Entries, newest first

  1. 04Architecture

    5 min read

    What a Discord bot actually costs to run

    The answer for most bots is close to nothing, and the reason is a design choice made before a line is written: whether it listens, or waits to be asked.

    • Discord
    • Serverless
    • Ed25519
    • Next.js
  2. 03Engineering

    4 min read

    The reduced-motion bug that hid an entire website

    A four-line accessibility guard blanked every page for the people it was written to protect. Here is why React could not fix it, and the shape of the mistake.

    • React
    • Next.js
    • Accessibility
    • Hydration
  3. 02Product

    3 min read

    Monetisation you can defend

    Delta-V has no forced interstitials. The policy cost real revenue, made the game better, and exposed a bug that had been paying people for nothing.

    • Product
    • Monetisation
    • Android
    • Testing
  4. 01Architecture

    3 min read

    Nineteen leagues, one registry

    Scorebug covers hockey, football, basketball, baseball, soccer, cricket and Formula 1. Adding a league is one entry in one file — and four places that entry does not reach.

    • Architecture
    • PostgreSQL
    • Supabase
    • APIs

02What these answer

The short version of each one

Each write-up opens with one question and answers it in a single paragraph, before any explaining starts. Those paragraphs are printed here in full, and the structured data this page publishes is that same text.

How much does it cost to run a Discord bot?
For a bot that answers slash commands, close to nothing — it needs one HTTPS endpoint Discord can post to, which runs on the hosting a site already has and costs fractions of a cent per command, with no process awake between invocations. For a bot that holds a gateway connection, because it reads every message or handles voice, it is the price of a small server running continuously, whether or not anybody uses it. The choice between the two is made before any code is written, and most bots that were built as gateway bots did not need to be.Read the entry: What a Discord bot actually costs to run
Why does a framer-motion component pinned at opacity 0 never animate for users with reduced motion enabled?
Because branching on useReducedMotion() changes which element the component returns, and that value differs between the server and the client. The server renders the motion element with its opening inline style of opacity:0; a reduced-motion client renders a plain element with no style. React does not patch mismatched attributes during hydration, so the server's opacity:0 survives, and because no motion component is mounted nothing ever animates it away. The fix is to keep the element type identical in both renders and express the preference through MotionConfig instead.Read the entry: The reduced-motion bug that hid an entire website
Can a free mobile game make money without interrupting play with forced ads?
Yes, if the ad placements are chosen so that they only ever appear where the player already chose to stop. Delta-V disables forced interstitials entirely and ships only opt-in rewarded video and menu-screen banners, so an advertisement can never interrupt a flight. The trade is a lower impression count against a game people keep playing, and a claim about the product that survives contact with a review.Read the entry: Monetisation you can defend
How do you structure an app that covers many sports leagues without forking the code for each one?
Put every per-league difference in one registry and derive the rest. In Scorebug, colours, upstream API configuration, news sources, surface treatments and display labels are all read from a single league registry through one lookup function, so nineteen leagues share one code path instead of nineteen forks. The discipline that makes it work is simple: anything that cannot be derived from the registry counts as a defect, and gets fixed.Read the entry: Nineteen leagues, one registry

Elsewhere

The work behind the writing

The entries above all came out of something the studio built and runs today: Scorebug, Delta-V, or this site itself. The case studies are the longer version, with the specification, the stack and the figures attached.