Last night an AI saved my life

← PreviousMake things work, make things right, make things fast

Last night an AI saved my life. Well, not literally, and not even last night. But I really believe it saved the browser engine project I’ve been working on for years. We are steadily going through all the hard phases of trying to understand what we are building and how to build it. Turns out we were right all along: building a browser engine is really hard. But yes, we knew that already. But this is not where the AI saved us.

The thing is, we have been working a lot on this project now,and we have what we can call a proof-of-concept engine. It’s basically a HTML5 parser (passes all the html5lib tests!), a CSS3 parser, some simple rendering code and a connection to the V8 JavaScript engine that doesn’t do anything really, but at least it shows that we can run some JavaScript code from the engine. Tied together with some bits and pieces you find in a browser engine, and we have something that looks like an engine, but is not really able to “run”. So it’s hard to show your results, if results are just code, and not a rendered page on a screen.

So, we are steadily continuing until we can do decent rendering of pages but we have gotten to the point where we have just enough knowledge collected that we needed to start thinking: ok fine, we’ve got all these pieces, how can we make them fit together properly and make something we can actually show to the public?

No, we didn’t ask AI. We’ll come to that later. But, not to get in the way of the “main” progress of the engine itself, we decided to write a lot of smaller concepts and mini-engines: instead of fetching a page with the reqwest crate, we tried to design a more robust network system that can handle all the weird edge cases, deal with priorities, cancellations, streaming and buffered data and whatnot. Basically: ok, we probably know what we really need to have, let’s try and convert that into code.

Still no AI. We didn’t vibe those things. We took our knowledge collected over the many months (years, by now), and we created those components in a way we wanted to have it working in the main engine. We did that for the network stack, and
we did that for the rendering pipeline system. We created a complete system that let data travel from a dom document all the way to be composited onto a screen with different backend render systems (skia, vello, cairo/gtk etc).

And finally, we figured out how a user of our engine would be able to interact with it. We created the public API of the engine from which we think allows users to incorporate our engine into their own projects. And again, not affecting the current engine so we just could start from scratch.

So, at this point we had a few large components we were pretty happy with, eager to be connected together into the main engine. But we had no idea how to do that properly. We knew what would need to talk with what, but all had incompatible interfaces, or are using mocked systems or are just not compatible with each other.

So over the next months, we had at least four failed attempts to connect everything together. Each time, we got stuck at some point, couldn’t oversee the whole picture anymore, or had the engine in such a state, it was best to delete the work and start over again. It was frustrating. Every attempt failed and with each attempt, our enthusiasm for the project went down until it hit a little pilot-light that was about to fade out as well. Other projects became more interesting, and we had less and less motivation to work on the engine and project in general. Asking for help was (and still is) hard to get: just showing bits of a jigsaw puzzle does not get people motivated, but that’s all we had. We needed to get everything together in order to show others the whole puzzle, and we needed to show the whole puzzle in order to get help.

Basically, an information overload happened over and over again. There were too many pieces in play and we didn’t have enough context on how to connect them together. We couldn’t work on the engine, because that would be completely overhauled, and we couldn’t start a new engine, because we had the same problem of tying everything together. We were stuck.

And now we can talk about AI.

This all happened before the time of AI. Or at least, before I started to work with AI. I did some work with ChatGPT, and it gave me some good code snippets once in a while, but it never really could understand my total codebase at all. I couldn’t simply ask it to “merge these components into the main engine, make no mistakes”.

But, once I got introduced to Claude Code somewhere in the beginning of this year, all of a sudden this was not a problem anymore. I could point to my codebase, ask Claude Code to give me a description on the engine (so at least I had some kind of confirmation it understood stuff). Then I pointed to the separate components (one by one), and asked for a plan to merge them together.

And the plan actually made a lot of sense. It was not perfect, but it was a lot better than what I tried in the many failed attempts previously. We took things step by step, it took notice of the complete context so it was aware that changing something here would affect something else there, and it was able to give me a clear plan on how to merge everything together, steering things along the way.

And so we started what would become our fifth attempt. Or sixth. We’ve basically lost count. But it was the first attempt with a decent plan. A lot of things were done by Claude itself that I felt comfortable enough to let it do: copy complete crates over to my codebase, renaming all the things that connected with them etc. Things that aren’t particularly difficult, but simply take time; exactly the kind of work an automated system can do much faster, while still being easy enough to manually verify for correctness.

The more it did right, the more work I let it do on the small steps. The things it failed (remarkably few), were easily fixed manually.

And finally, after a few weeks of work, we had a working engine with all the new components in place: we have a proper API that is used by all examples and binaries that we provide. We have a render pipeline that makes sense and works, we have a proper network stack that deals with the complexities of fetching data. And we can focus again on the main engine itself. Fix and implement simple CSS things so we can directly see the result of our work. Something we haven’t been able to do in a long time.

We finally have a working engine again, and with that, we are about to show the world our puzzle. It’s not finished, but hopefully it gives more people the motivation to join in and help out. We have a lot of work to do, but we can finally show the results of our work, and that is a huge motivation boost for us.

It gave me back my enthusiasm for the project, and I can’t wait to implement more and more things so we can become an engine to be reckoned with. Instead of vibecoding a complete project, we used AI to guide us through a complex part of the project and we are really happy with the result. There are some major component changes coming up (like a new CSS3 parser), but I’m confident that we can implement this, with or without the help of AI.

← PreviousMake things work, make things right, make things fast