Not a productivity theory. This is the git history off my own laptop -- 314 commits across five codebases, 85 hours of it timestamped to the minute, and 94% of those hours falling outside a Monday-to-Friday nine to five. Plus the honest cost of holding six half-built things in your head at once.
It is not that you got faster at the work. It is that you stopped waiting.
In November 2024 I started on Pi Squared, a daily maths game. I was working on a shared repo with other people and I pulled from it, on and off, for ten months. That was my education. Everything I know about Flutter, Firebase, App Store Connect and the particular misery of iOS signing, I learned there, slowly, one problem at a time.
Then in May 2026 I started Braindex on my own. Between that first commit and the end of August I authored and shipped five more apps. Same laptop. Same day job Monday to Friday. Same two hours of soccer training most evenings.
The obvious explanation is that I got better. That is partly true and mostly not the point. The real change is structural, and it is visible in the timestamps: I stopped building one thing at a time. When a model is generating, when a build is compiling, when Apple is processing a TestFlight upload -- those are not waits any more. They are the other app's turn.
This paper is about what that actually looks like hour by hour, what it costs, and the five things I would tell anyone trying it.
Build days means days on which at least one commit landed -- not calendar days, and not hours. Braindex is the outlier because it never stopped: it is the one I keep shipping into.
| App | What it is | First commit | Span | Build days | Commits |
|---|---|---|---|---|---|
| Pi Squared | Daily maths game. My first, built with others on a shared repo. | Nov 2024 | ~10 months | -- | -- |
| Braindex | Daily AI vocabulary, then daily trivia, then leagues, friends and a live multiplayer chase. | 3 May 2026 | 119 days | 42 | 192 |
| Chip Me | Online card game. Started life as a web prototype, became a Flutter app. | 21 Jun 2026 | 42 days | 8 | 19 |
| BuzzScraper | Tap-to-fly arcade. A bee, a city, and eventually a Mode 7 kart racer. | 1 Aug 2026 | 24 days | 6 | 30 |
| M50 Speed Run | Traffic-weaving endless runner. Built as a web game, wrapped for iOS. | 5 Aug 2026 | 5 days | 4 | 29 |
| Over the Bar | GAA free-taking game. Every county, its own clubs, its own hundred levels. | 10 Aug 2026 | 17 days | 6 | 44 |
Counts are taken from the local git reflog on my machine, which is the record of what my laptop actually did. Pi Squared is left blank on purpose -- I cloned that repo rather than authored it, so its history is not mine to count.
The number I keep going back to is M50 Speed Run: four build days, start to finish, live on the App Store. Not four weeks. Four days on which I opened the editor at all. And it was not a quiet four days -- two of them were shared with BuzzScraper and one with Braindex.
Three claims about how this works, and the evidence for each from the commit log.
Claim one: the day is not the day. I have a full-time job. I am not building between nine and five. So the interesting question is not "how many hours" -- it is which hours, and what shape they are.
All five apps I authored, May to August 2026, in Michigan time. The shape is not subtle.
Peak hour is 23:00. Second is 22:00. Between 03:00 and 06:00 there is not a single commit in four months, which I take as the one piece of good news in this chart.
183 of 314 commits -- 58% -- landed between 9pm and 2am. That is the window. It is after the job, after training, after dinner. It is roughly three hours, four or five nights a week, and it is the entire budget. Everything in this paper is a strategy for getting six apps' worth of progress out of three hours.
Claim two: the unit of work is a commit, not a session. Inside that window the median gap between one commit and the next is nine and a half minutes. Half of all consecutive commits are under ten minutes apart. That is not me typing faster. That is what happens when the loop is: describe the change, review what comes back, commit, move.
And "move" is doing a lot of work in that sentence. Because the next thing you move to is often a different app.
Every commit that landed that day, in order, across both repos. Blue is M50 Speed Run. Gold is BuzzScraper. Nothing has been reordered or tidied.
Look at 22:37 to 22:39. A Firebase leaderboard lands in M50, then Sign in with Apple lands in BuzzScraper, then M50's privacy policy is updated to describe the leaderboard that arrived two minutes earlier. The two apps are not competing for attention. They are covering for each other. While one is generating or building, the other is where I am.
Note also what 16:19 and 16:29 have in common. The same job -- wire Firebase, write the rules -- done twice, ten minutes apart, in two different apps. That is not duplicated effort. That is the cheapest either of them will ever be, because I only had to remember how once.
Claim three: the switching is the method, not the accident.
Every multi-app day between May and August 2026, and which repos were open.
21% of build days. 40 recorded switches from one repo to another within a single day. The busiest -- 5 August -- ran M50, BuzzScraper and Braindex from just after midnight through to 22:22.
That 5 August day is worth pulling apart, because it is the whole method in one line: M50 Speed Run went from an empty repo at 00:02 to a working TestFlight pipeline at 00:34. Thirty-two minutes. Then at 00:40 I was back in Braindex shipping group invite codes, and at 00:42 back in M50 switching the iOS export to manual signing.
Over the Bar did something similar five days later: initial commit at 21:21, "playable on device, shipping to TestFlight" at 23:26. Two hours and five minutes from nothing to a build in Apple's hands.
Every sitting, every window, and how much of it fell outside a normal Monday-to-Friday nine to five.
I wanted to know the real number, so I worked it out properly rather than guessing. Every commit is grouped into a sitting -- a run of commits with no gap longer than ninety minutes -- and each sitting gets twenty minutes added at the front, because the first commit is never the first thing you do. Then every minute of every sitting is checked against Monday to Friday, 08:00 to 17:00.
Across four months and six apps, the answer is 85 hours. Not eighty-five hours a week, or a month. Eighty-five hours in total, from 3 May to 29 August.
Monday to Friday, 08:00 to 17:00 is treated as core hours. Everything else -- evenings, nights, weekends -- is outside.
93.8% of the total fell outside core hours. Of 51 sittings, exactly two happened entirely inside a normal working day -- 30 June and 7 August, twenty minutes each.
The 5.3 hours inside core hours is the number I find most reassuring, and it is worth saying plainly: this was not built on my employer's time. 3.4 of those 5.3 hours are a single Friday -- 3 July -- and what is left is seven short sittings scattered over four months, most of them before 09:00 or in a lunch hour.
The rest of the shape: 31 of 51 sittings ran to 22:00 or later, and 13 of them finished after midnight. The longest single sitting was 4.6 hours, on a Sunday afternoon in July. The longest day was Saturday 15 August -- 6.7 hours across three separate sittings, which is the day Over the Bar got its counties, its clubs and its Apple sign-in fix.
Windows are start to finish in Michigan time, including the twenty-minute lead-in. "Outside" is the hours of that day falling beyond Mon–Fri 08:00–17:00; "all" means the entire day did. Weekend rows are shaded. A sitting that runs past midnight is logged under the day it began.
| Date | Day | Windows worked | Hours | Outside | Apps |
|---|---|---|---|---|---|
| 3 May | Sun | 11:01–12:02 · 18:51–19:11 · 21:29–21:52 | 1.7 | all | Braindex |
| 8 May | Fri | 23:16–00:14 | 1.0 | all | Braindex |
| 9 May | Sat | 11:22–11:53 | 0.5 | all | Braindex |
| 11 May | Mon | 18:09–19:00 · 22:22–23:29 | 2.0 | all | Braindex |
| 12 May | Tue | 17:22–18:14 · 22:10–23:19 | 2.0 | all | Braindex |
| 13 May | Wed | 19:49–20:09 · 22:09–22:29 | 0.7 | all | Braindex |
| 16 May | Sat | 07:08–07:57 · 19:24–20:33 | 2.0 | all | Braindex |
| 17 May | Sun | 00:52–01:21 | 0.5 | all | Braindex |
| 20 May | Wed | 19:25–19:45 | 0.3 | all | Braindex |
| 23 May | Sat | 16:29–16:49 | 0.3 | all | Braindex |
| 24 May | Sun | 20:54–21:14 | 0.3 | all | Braindex |
| 25 May | Mon | 10:14–10:34 · 19:31–23:40 | 4.5 | 4.1 | Braindex |
| 26 May | Tue | 22:32–23:05 | 0.5 | all | Braindex |
| 21 Jun | Sun | 19:58–20:18 | 0.3 | all | Chip Me |
| 22 Jun | Mon | 20:34–21:54 | 1.3 | all | Braindex, Chip Me |
| 23 Jun | Tue | 22:32–23:13 | 0.7 | all | Chip Me |
| 28 Jun | Sun | 15:33–15:53 | 0.3 | all | Braindex |
| 30 Jun | Tue | 11:27–11:47 | 0.3 | 0.0 | Chip Me |
| 1 Jul | Wed | 17:53–18:37 · 20:52–21:12 · 22:48–23:08 | 1.4 | all | Braindex, Chip Me |
| 2 Jul | Thu | 18:19–19:03 · 22:03–23:24 | 2.1 | all | Braindex, Chip Me |
| 3 Jul | Fri | 01:23–02:38 · 11:15–13:43 · 15:04–15:58 · 17:19–17:39 | 5.0 | 1.6 | Braindex, Chip Me |
| 4 Jul | Sat | 17:02–18:18 | 1.3 | all | Braindex |
| 5 Jul | Sun | 00:54–01:14 · 10:39–11:28 · 15:02–19:38 | 5.7 | all | Braindex |
| 6 Jul | Mon | 23:53–00:13 | 0.3 | all | Braindex |
| 13 Jul | Mon | 00:22–00:42 · 21:40–22:51 | 1.5 | all | Braindex |
| 14 Jul | Tue | 17:58–18:18 · 22:16–22:36 | 0.7 | all | Braindex |
| 15 Jul | Wed | 08:05–08:25 · 21:40–23:25 | 2.1 | 1.7 | Braindex |
| 28 Jul | Tue | 18:37–19:32 · 21:01–21:21 | 1.2 | all | Braindex |
| 1 Aug | Sat | 09:33–09:53 · 15:08–15:28 | 0.7 | all | Braindex, BuzzScraper, Chip Me |
| 2 Aug | Sun | 11:59–12:19 | 0.3 | all | Braindex |
| 3 Aug | Mon | 23:00–23:20 | 0.3 | all | Braindex |
| 4 Aug | Tue | 22:52–00:54 | 2.0 | all | Braindex, M50 |
| 5 Aug | Wed | 07:38–08:14 · 20:45–22:22 | 2.2 | 2.0 | Braindex, BuzzScraper, M50 |
| 6 Aug | Thu | 17:07–17:27 | 0.3 | all | M50 |
| 7 Aug | Fri | 09:42–10:02 | 0.3 | 0.0 | Braindex |
| 8 Aug | Sat | 07:46–08:08 | 0.4 | all | M50 |
| 9 Aug | Sun | 15:17–17:11 · 22:03–23:57 | 3.8 | all | BuzzScraper, M50 |
| 10 Aug | Mon | 20:47–23:26 | 2.7 | all | BuzzScraper, Over the Bar |
| 12 Aug | Wed | 21:41–23:28 | 1.8 | all | Braindex, BuzzScraper |
| 13 Aug | Thu | 23:19–23:39 | 0.3 | all | Over the Bar |
| 14 Aug | Fri | 20:49–01:04 | 4.3 | all | Over the Bar |
| 15 Aug | Sat | 12:25–12:49 · 14:59–17:05 · 19:17–23:29 | 6.7 | all | Braindex, Over the Bar |
| 16 Aug | Sun | 00:39–01:55 · 10:44–11:04 | 1.6 | all | Over the Bar |
| 19 Aug | Wed | 13:45–14:05 · 19:30–21:04 | 1.9 | 1.6 | Braindex |
| 20 Aug | Thu | 17:55–18:19 · 21:23–00:49 | 3.8 | all | Braindex |
| 23 Aug | Sun | 09:37–10:29 · 13:18–14:14 · 15:57–16:45 · 23:05–01:25 | 4.9 | all | Braindex, BuzzScraper |
| 24 Aug | Mon | 20:47–21:07 · 22:51–23:45 | 1.2 | all | BuzzScraper |
| 25 Aug | Tue | 23:23–00:14 | 0.8 | all | Braindex, Over the Bar |
| 27 Aug | Thu | 18:40–19:00 | 0.3 | all | Braindex |
| 28 Aug | Fri | 22:21–00:55 | 2.6 | all | Braindex |
| 29 Aug | Sat | 14:06–15:03 | 1.0 | all | Braindex |
| 51 sittings | 85.0 | 79.8 | |||
Read down the Windows column and the pattern is unmistakable. 21:00-something to 23:00-something, over and over, for four months. An hour here, forty minutes there, and then occasionally a Saturday that runs from lunchtime to half eleven at night.
The average build day is 1 hour 40 minutes. That is the honest unit. Six apps did not come from marathon sessions -- they came from ninety-odd minutes a night, four or five nights a week, with two or three of them open at once.
People ask about the tooling. The tooling matters less than the arrangement.
Not tabs. Separate VS Code windows, each with its own folder, its own terminal, its own agent session, arranged so I can see which ones are thinking.
Whichever app I am actively reviewing. This is the only window where I am reading diffs line by line and making calls. It moves between apps several times an evening.
An agent working on a task I described two minutes ago. I do not watch it. I come back when it is done. The whole trick is that this window is never empty.
A Flutter build, a pod install, an IPA upload. Minutes of dead time each. Multiply by six apps and this is where the parallel gain actually comes from.
App Store Connect, Play Console, Firebase. Screenshots, declarations, review responses. This is what I do while the other three windows are busy -- it needs almost no thinking, and it is never finished.
Every repo has a TODO.md, and the busy ones have PRIORITIES.md and NEXT-SESSION.md. This is where I put the state of my own head before I leave a window.
A real device with a TestFlight build on it. Simulators lie about signing, about haptics, about how a game actually feels in the hand.
The arrangement is the point. Three windows means that at any moment, two of them are working without me. My job is to be the one thing that cannot be parallelised: deciding what should happen next, and judging what came back.
The Braindex paper covered the ordinary ones -- CocoaPods, Xcode archives, Google Play's 14-day closed test. These five only show up once you are holding more than one app at a time.
On 18 May I spent a chunk of a day on Sign in with Apple failing silently in Braindex. The Apple identity-token nonce is single-use, and the manual credential flow tries to spend it twice on retry, which Firebase rejects. Three months later, on 15 August, the exact same bug appeared in Over the Bar.
Fix Apple sign-in: the nonce was single-use and we were spending it twice. The first app pays the tuition. Every app after it gets in free. This is the actual compounding argument for building several -- not that you are faster, but that the problems stop being new.Three of the five got renamed mid-build. "No Thanks!" became "Yes Please!" became Chip Me. "HEATLINE" became "M50 Traffic Chase" became M50 Speed Run. "Flappy Dash" became BuzzScraper. Each rename is not one commit -- it is the bundle ID, the display name, the icon, the privacy page, the store listing, the Firebase project, and something you will forget.
games.davidcarr.something is invisible to users and expensive to change. The visible name can drift for free until the day you submit; the identifier cannot.When the same person builds six games in four months with the same tools, they converge. Every one of mine ended up with a leaderboard, a streak, sign-in, and a share card -- because that is what I knew how to build well, and because the pattern genuinely works. But there is a real risk of shipping the same app six times with different art.
This is the one that surprised me most. Six apps means six Apple review submissions, six Play data-safety forms, six age-rating questionnaires, six sets of screenshots at multiple device sizes, six privacy policies that must return HTTP 200, six delete-account URLs, six content ratings, six export-compliance declarations. None of it gets easier per app. It just happens six times.
On 20 August I found out Braindex was freezing on the launcher icon for some Android users. It had been live. I had not opened it on an Android device recently because I had been in three other repos. That is the honest cost of parallel: the app you are not in is the app you are not testing.
Add an Android pre-release gate that proves the app actually opens -- a script that boots an emulator, installs the build and confirms it launches, before anything ships. If you are running more apps than you can personally check, the checking has to become a machine.I would not write this paper honestly without this section.
The chart in Figure 02 is a nice piece of evidence for a method. It is also a picture of a person who commits code at eleven at night, four nights a week, for four months. Peak hour 23:00. Second-place 22:00. Twenty-nine commits landed after midnight.
Nothing about this is free. The three-hour window is real, but it is the same three hours other people spend with their families, or asleep, or doing nothing at all, which turns out to be a legitimate and underrated activity. I have shipped six apps and I have also had evenings where I could not tell you what I did between 9pm and 1am other than "moved between windows".
The second cost is subtler. Parallel building is very good at breadth and quietly hostile to depth. Three of mine went from an empty repo to shipped in under a month, and M50 did it in five days. Braindex, the one I stayed with, is the only one with leagues, friends, live multiplayer, an ELO system I have now rewritten six times, and actual users doing actual things. The other five are real, shipped, and thin. The method got them born. It is not the method that makes them matter.
The third is that switching has a floor. Nine and a half minutes between commits sounds fast, and it is -- but a nine-minute unit of work is a nine-minute-sized thought. There are problems in Braindex I did not solve for weeks because they needed an unbroken two hours and I never gave them one. If everything in your week is nine minutes long, some things simply never get done.
So the honest version is this: parallel building is the right method for getting things into the world. It is the wrong method for making one of them great. You need both, and you need to know which one you are doing this evening.
Six things, in the order they would have saved me the most time.
This is the whole skill and it is not a technical one. When you switch apps, the expensive thing you lose is not the code -- it is knowing what you were about to do. Every one of my repos has a TODO.md; the busy ones have PRIORITIES.md and a NEXT-SESSION.md that says, in plain sentences, what is broken and what is next. Thirty seconds of typing buys back twenty minutes of re-reading your own code tomorrow. Treat the markdown file as the handoff between two different people, because by tomorrow night it is.
Apple review, TestFlight processing, Google Play's mandatory 14-day closed test -- these are days and weeks where the app is out of your hands and there is genuinely nothing to do. That dead time is not a gap in the schedule. It is the schedule. Every one of my apps after Braindex was started inside somebody else's review window.
On 9 August I wired Firebase into two apps ten minutes apart. On 12 August I stripped the advertising ID Firebase had added on its own out of BuzzScraper; four days later I did the same to Over the Bar and it took one commit. Doing a job while it is still warm is dramatically cheaper than doing it fresh in three weeks. If you know two apps need the same piece, schedule them on the same evening.
Screenshots, listing copy, store uploads, review submission. It feels wasteful to script it the second time you do it, because scripting it takes longer than doing it. Do it anyway. By the fourth app you are getting the time back every week, and by the sixth the difference between "I could ship this" and "I did ship this" is entirely whether the boring part is a button.
Three of my five got renamed and every rename cost more than it should have. The user-visible name can change up to the day you submit -- that is free. The bundle identifier, the Firebase project, the package name: pick those on day one, make them boring, and never touch them again.
Parallel is for getting things born. It is a genuinely excellent method for that and I would defend it against anyone. But depth needs an unbroken two hours in one window with the others closed, and you will not get there by accident, because there is always another repo with something quick in it. Decide before you sit down: tonight I am shipping four things, or tonight I am fixing one thing properly. Both are good nights. Pretending you are having one while having the other is not.
Braindex, Pi Squared, Chip Me, BuzzScraper, M50 Speed Run and Over the Bar. If you would like to see what three hours a night for four months actually produced:
Every figure in this paper is derived from the git reflog on my own laptop -- the record of what the machine actually did, timestamped in Michigan time. It covers the five apps I authored between 3 May and 29 August 2026. Pi Squared is excluded from the counts because I worked on a shared repository there rather than authoring it, so its history is not a fair measure of my own. Hours are estimated, not clocked: commits are grouped into sittings with a ninety-minute gap threshold, each sitting is credited twenty minutes of lead-in before its first commit, and every minute is then tested against Monday–Friday 08:00–17:00. That method will undercount thinking time away from the keyboard and overcount nothing. If you want the working, it is all in .git/logs/HEAD, which is a file I would encourage anyone to go and read about themselves.