Skip to content

The Rebuild

What I am building, what broke, and what it cost. Written from inside FlashFX, sent when there is something worth saying.

11 issues

№ 012 ·

The Marketing Mess

The last issue ended with a test for the week after it, and I called the test boring: keep the same cadence for seven days with no spike in them, and see whether the floor moves.

This is that week. What I found out is what cadence costs once it is multiplied by four.

What happened

After launch, every platform turned into a to-do list. Instagram, TikTok, X, LinkedIn, and a few more queued up behind them. Each one had a good reason to be there, and each one, on its own, was a reasonable thing to take on. Together they were not a marketing plan. They were a tide, and by this week I was underneath it.

Nothing broke. There is no wreckage to point at, which is exactly the shape of my last setback, and it is the reason I am writing this one down while it is still happening instead of six weeks after.

Four platforms is four jobs

The mistake is inside the phrase "post everywhere". It sounds like one task done four times. It is four different jobs that happen to share a subject.

Read this

№ 011 ·

300 Followers in a Week, and the Dip Was the Useful Part

A fortnight ago the FlashFX account passed 100,000 views on X inside a single week, which is now on the timeline as a real event. This is about the number underneath that one. Views are a measure of how far something travelled. Followers are a measure of whether anyone wanted it to happen again.

Last week the account reached 300 followers. Seven days. What I did not expect is that the interesting part would be a day in the middle where the number went the wrong way.

The shape

Up sharply at the start. Then a day where the count went backwards instead of forwards. Then up again, past the dip, to 300 by the end of the week.

I want to be precise about how that felt, because the feeling was wrong. On the day it dropped, the obvious reading was that I had posted something bad and was being corrected for it. That reading is almost never right, and it is worth knowing why before it happens to you.

Unfollows lag follows, and that is the whole explanation

Read this

№ 010 ·

A Hundred Commits, and Almost No Decisions

Today FlashFX opened to the public and became a company, which I have written about separately in Launch Day, and the Company Underneath It. This is about the other thing that happened today, which is that I made a hundred commits.

I have never done that before and I do not expect to do it often. It is worth writing down while the details are still exact, because a day like this looks, from the outside, like a story about effort. It is not. The effort was the least interesting input.

The day, measured

Nine milestones shipped: M1 through M10, with M1 landing late the night before and M2 through M10 across today. Eight of the hundred commits are the milestone commits, the ones named in the devlog; the other ninety-odd are the work underneath them.

Eight new verification harnesses: transform HUD, measurement, equal-gap, nudge, fuzzy search, tangent, bend, path cleanup. Typecheck held at 0 errors and lint at its 127 baseline through every single commit.

Read this

№ 009 ·

Launch Day, and the Company Underneath It

Everything comes down to today. FlashFX is open to the public, and it is finished in the sense that matters: you can sign up, open it, and do the whole job inside it without hitting a wall where the feature you need was on a roadmap.

That is the difference I would draw against every earlier release. Things have shipped before. v1.0 went out last November and people used it. But there was always a sentence attached: this part is coming, this works but not with that. Today there is no sentence. The product is the product.

The six weeks before this

I am not going to relitigate them here, because they have their own issue. In short, from late June to the first week of August I drifted: thirteen hours a day on my phone, tasks going untracked, six weeks of runway spent on nothing, against a launch date that was never going to move. It broke on 5 August, two days ago.

If you want the honest version of that, with the causes named and the recovery described as the slow, unremarkable thing it actually was, it is in My Worst Setback Was Also My Mildest. It is the more useful of these two issues. This one is the good news; that one is the part that explains why the good news was nearly late.

Read this

№ 008 ·

My Worst Setback Was Also My Mildest

I have had setbacks that cost more than this one. A channel with six hundred videos deleted overnight. A codebase lost to a file path, with two hundred borrowed euros inside it. Measured in destroyed things, the last six weeks cost nothing at all.

I would still call them the worst setback I have had. That is not a paradox and it is not modesty about the earlier ones. It is a straightforward consequence of what a setback actually is, and it took me until this week to state it plainly enough to be useful.

What happened, measured

Late June into the first week of August, roughly six weeks. My phone reported an average of thirteen hours a day of screen time. Tasks slipped to tomorrow, then stopped being written down, which is the part that matters: an untracked task is not a delayed task, it is a deleted one. There were days I did not open the repository.

There was no decision anywhere in that. Nobody chooses a six-week drift. It assembles itself out of individually reasonable days, and by the time the shape is visible from the outside it has already been the shape for a month.

Read this

№ 007 ·

Photoshop Became Canva. After Effects Becomes FlashFX.

Photoshop became Canva. Premiere became CapCut. Illustrator became Figma, more or less, and nobody argues about it any more.

Motion design did not move. After Effects is still a desktop install, still a subscription, still an interface that takes months before you can make something move the way you meant. It is the last major creative category where the browser version does not exist.

I have spent two years on the assumption that this is a timing problem rather than a category problem.

Why it held out

The honest answer is that motion design was genuinely too heavy. Compositing is expensive, effects stacks are expensive, and for most of the web's life the browser had no serious access to the GPU. You could not have built this in 2016. People who tried built toys.

So the category kept a real technical justification for staying on the desktop long after the others lost theirs. Photoshop moved when raster editing got cheap enough. Video editing moved when codecs landed. Motion design was waiting on GPU compute and low-level media access, and those arrived quietly and recently.

Read this

№ 006 ·

I Lost My First Project to a File Path

I wrote my first line of code on 3 January 2024. I was fifteen. I had never programmed, I did not know what a repository was, and I was building a browser-based video editor because I did not know that was an unreasonable thing to start with.

It was called Vision AI Demo. For about six weeks it ran.

What happened

I reorganised the files. That is the whole story.

I moved things into folders that made more sense to me, which broke every import in the project simultaneously. I did not know how to trace an import error. I did not know how to undo it, because I had no version control; I did not know what version control was. There was no backup, because it had not occurred to me that there might need to be one.

The codebase was unrecoverable. Not corrupted, not lost from disk. Just in a state I did not have the knowledge to reverse, which from where I was standing is the same thing.

The part that actually hurt

Read this

№ 005 ·

Why Your Picture Leads Your Sound

Audio bugs do not get reported as audio bugs. They get reported as "it feels laggy" or "something is off" or, most often, not at all; the user just quietly decides the tool is cheap.

Three of these came out of one session. None of them is complicated. All three are the kind of thing you only find if you go looking.

The picture is early

Schedule a sound to play now and it does not play now. Audio hardware has a pipeline: a buffer, a driver, the device itself. The sound you schedule is heard some milliseconds later, and how many depends on the machine.

So if you read your clock and draw the frame for that reading, the picture is ahead of the sound by exactly that pipeline. On a good desktop that might be 20 milliseconds. On a laptop with Bluetooth headphones it can be 200.

The fix is to draw the frame for the clock reading minus the output latency, not the raw reading. The browser will tell you what that latency is. The temptation is to treat the clock as truth; it is not, it is truth about sound that has not happened yet.

Read this

№ 004 ·

Testing Code Your Dev Environment Cannot Run

Audio-synced playback is the kind of feature that either works or is embarrassing. There is no middle state. Twenty milliseconds of drift and everybody feels it even if nobody can name it.

It is also, in my setup, completely untestable. Where I develop there is no WebAudio, no WebCodecs, no WebGPU. Not "flaky in CI" untestable; the APIs are simply not there.

The trap

The obvious response is to write the feature, push it, open the app, and look at it. Then change something, push, look again. I have built things this way and it is miserable. Every iteration costs a full round trip, you cannot check edge cases, and you end up asserting correctness with your eyes on a case you happened to try.

For sync work specifically that is hopeless. "Does the audio lead the video" is not something you can eyeball reliably at 40ms.

What I did instead

The realisation is that almost none of the hard part actually needs the browser.

Read this

№ 003 ·

The WebCodecs Frame Limit Nobody Documents

Video playback in FlashFX froze a few seconds in. Not a stutter, not a dropped frame. It played, and then it stopped, and nothing in the console had anything to say about it.

I want to write this one down because I lost real time to it, and because almost nothing on the open web describes the actual failure mode.

What it looked like

Decode a video, hold the frames, draw them as the playhead moves. Standard. The decoder was configured correctly, the chunks were going in, and for a few seconds the frames came out.

Then the output callback simply stopped firing. No error. No dequeue event. No state change on the decoder. It sat there in configured, accepting chunks, emitting nothing.

What I assumed

Memory. Obviously memory. I had a byte budget of 512MB across decoded frames, and my first instinct was that the budget was wrong, or that something was retaining frames past their eviction.

So I went looking for a leak. There wasn't one. The budget was being respected. At the moment playback froze, I was comfortably under it.

Read this

№ 002 ·

What Four Rebuilds Actually Cost

I wrote my first line of code in January 2024. Three weeks later I lost the whole project to a file-path error, and the €200 I had spent on it was borrowed from my younger cousin. That is where this starts, and I think it matters more than the part where it works.

The first one

Vision AI Demo was a browser-based video editor built with an AI assistant and bolt.new, by someone who had never programmed. It ran. For about six weeks it genuinely ran.

Then I restructured the files, broke every import in the project at once, and had no version control, no backup and no idea what any of those words meant. The codebase was unrecoverable. I want to be precise about this, because it is the only part of the story people tend to soften: it was not a hard problem. I simply did not know the thing that would have saved it.

The pivot nobody saw

Between the crash and anything resembling FlashFX there were five prototypes and none of them shipped. What came out of that stretch was not code. It was the realisation that I had been building in the wrong category: timeline video editing is crowded and solved, and motion design in the browser was not.

Read this