Skip to content
Writing

Notes from the build.How the things on this site were actually put together.

No tutorials and no listicles. Mostly how something was built and why it was built that way: the architecture behind a feature, the systems that keep an app consistent, and the checks that run before anything ships.

TOPICS

  • Architecture
  • Reliability
  • Measurement
  • Security
  • Supabase
  • Postgres

FROM THE PIECE

“The phone is a subscriber to the job, never its owner. Once that is true, closing the app is not an event worth handling.”

On why the phone can never be the thing that owns the job.

30 Jun 20268 min readAI

Running a long AI job from a phone

Video generation takes minutes, and a phone can be backgrounded, killed or lose signal at any point in them. So the phone cannot be the thing that owns the job.

A request that takes three minutes cannot be an HTTP call from a mobile client, because the client will not survive it. The job goes in the database, a worker picks it up, and the phone subscribes to a document. Everything else follows from that.

Read the piece
EVERYTHING, NEWEST FIRST15 PIECES
  1. 22 Aug 2026

    8 min read

    The cheap design that measurement ruled out

    A pollable endpoint looked like it would do the job. Seventy-eight minutes of measuring two real accounts showed it was wrong by up to forty-three minutes, and that decided the architecture.

    Every serverless design for this was ruled out by measurement rather than by preference. The endpoint that looked sufficient advanced once in fifty-four minutes while the user was demonstrably active, and read two accounts in identical states fifteen minutes apart.

    ArchitectureReliabilityMeasurement
  2. 19 Aug 2026

    9 min read

    Auditing a Supabase app with its own public key

    The anon key ships inside every build. Before a release I take it, point it at the database, and go through every table and function asking what it will tell a stranger.

    Reading the code tells you what you meant. Pointing the app's own public key at production tells you what you shipped. It is an afternoon's work, it is the only version of this exercise that finds anything, and it belongs on the checklist before every release.

    SecuritySupabasePostgres
  3. 14 Aug 2026

    7 min read

    A two party record, and a one party delete

    Every app eventually grows a delete-my-account button, usually because a store demands one. In any app where a row describes two people, that button is a data-modelling problem wearing a settings row.

    Delete everything belonging to this user sounds like a complete specification and is not. A row with two user ids in it belongs to two people, and only one of them is asking to leave. Here is how that goes wrong, and how to check for it before it can.

    PostgresData modellingArchitecture
  4. 12 Aug 2026

    4 min read

    The word was the feature

    The fairest way to split a tip-out was the option nobody chose, because it was labelled with its mechanism instead of its reason.

    The control said "By overlap", which describes how the calculation works. It does not tell a tired person at midnight why they would want it. Renaming it to "Fairly" and adding one line underneath changed which option people picked, and no arithmetic changed at all.

    ProductCopyDesign
  5. 11 Aug 2026

    6 min read

    What I check on a paywall before a release

    It is the one screen where a defect has a price, and the one screen you are least likely to open twice. So it gets its own checklist.

    The paywall is the one screen where every defect costs money directly. Mine had a close button that did nothing, a layout that settled a moment after it appeared, and no path back for somebody the store already considered a subscriber.

    RevenueCatProductiOS
  6. 06 Aug 2026

    6 min read

    Two databases, and a boundary you never cross

    An app that ships its own content has a problem: every update replaces that content, and the user's notes are sitting in the same file.

    One database is read-only, bundled with the app, and replaced wholesale on every update. The other lives in the user's documents and is never touched by an update. Keeping them apart is not tidiness. It is the difference between an update and a loss.

    SQLiteArchitectureOffline-first
  7. 05 Aug 2026

    6 min read

    Start with what people already own

    Why Rhovie opens with your bathroom shelf instead of a shopping list.

    Most skincare apps open with a store, because a store is how they make money. Rhovie opens with a question about what is already in your bathroom. A routine you can start tonight beats a routine you have to buy first.

    ProductRhovieDesign
  8. 27 Jul 2026

    7 min read

    A motion system, instead of animations

    Animations added screen by screen never agree with each other. Tokens, a shared entrance and one transition vocabulary make an app feel like one object.

    Every screen animating in its own way is not a designed app, it is a collection of screens. The fix is the same one that worked for colour and type: name the durations, name the curves, and let screens spend them rather than invent them.

    MotionDesign systemsReact Native
  9. 26 Jul 2026

    8 min read

    Shipping a component library into production

    Building one is easy. Using your own library in an app real people rely on is where you find out what's wrong with it.

    Liquid Glass went into TeamTipOut about four weeks after I started it. The first week broke two things I would never have found in a preview: a New Architecture crash on a fractional slider value, and a segmented control that measured itself before its labels had loaded.

    Native modulesReact NativeSwift
  10. 14 Jul 2026

    5 min read

    Twelve sheets, one heading

    Nobody files a bug that says the fourth sheet uses a different typeface. It is the kind of drift you only find by lining all of them up.

    Eight sheets set their heading in one typeface and four used another. No user would ever report it, and every user would feel it. Consistency debt is the sort that never gets paid unless you go looking for it deliberately.

    Design systemsReact NativeCraft
  11. 02 Jul 2026

    6 min read

    The redesign, and the room it is actually used in

    The first version of TeamTipOut looked like every other app built quickly. It worked, it was forgettable, and it was harder to read than it needed to be at midnight in a loud room.

    A generic dark interface is the default look of something built fast. It is not a decision, it is the absence of one. Rebuilding it around a warm editorial system made the app easier to use in the room it is actually used in.

    DesignProductTeamTipOut
  12. 30 Jun 2026

    8 min read

    Running a long AI job from a phone

    Video generation takes minutes, and a phone can be backgrounded, killed or lose signal at any point in them. So the phone cannot be the thing that owns the job.

    A request that takes three minutes cannot be an HTTP call from a mobile client, because the client will not survive it. The job goes in the database, a worker picks it up, and the phone subscribes to a document. Everything else follows from that.

    AIFirebaseArchitecture
  13. 29 Jun 2026

    10 min read

    Liquid Glass in React Native

    Apple's native effect on iOS 26, a fallback everywhere else, and how to make one component decide which is which.

    iOS 26 added Liquid Glass and it looks superb. In React Native you cannot use it on older iPhones, and you cannot use it on Android at all. So I built a component that uses Apple's when it is there and mine when it is not, and never asks the app author to care.

    SwiftReact NativeiOS 26
  14. 24 Mar 2026

    7 min read

    The last two weeks before review

    Everything I thought was left was small. None of it was the work. The work was the compliance surface nobody demos and every reviewer opens first.

    Shipping v1.0 was not the features. It was iPad touch-through on a blur layer, an account deletion page a store required, source maps, rate limits on a one-time code, and a dozen other things that appear on no roadmap.

    App StoreReleaseTeamTipOut
  15. 19 Mar 2026

    6 min read

    The appliance that was never in the room

    I built a coffee machine app without a coffee machine. The constraint turned out to be the most useful decision in the project.

    Every connected-appliance app is straightforward right up until the appliance is not there. Writing against a device protocol rather than a device meant the hardware could arrive later without the app being rewritten around it.

    BluetoothArchitectureReact Native

More when there is something worth writing down. There is no mailing list, because I do not run one.

Taking on new projects

Tell me what you’re building.A written scope and a fixed quote before any money moves.

I reply to everything within one working day. If I’m not the right person for it, I’ll tell you straight away rather than three weeks in.