In 2020, Ron (my co-founder) and I set out to build a web browser. We had just sold our startup accounting business out of YC and wanted to take a swing at building generational software. Although we weren’t successful, I think the journey is a great story worth sharing.
Browsers are interesting to me because they serve as the runtime of modern software. If you own the runtime, you get direct access to data and the ability to shape how people interact across software. That opens up a lot more surface area and freedom compared to what’s possible in a web app, which has to negotiate interoperability through integrations and only controls the experience within its own domain.
A problem that was bright in 2020 was the difficulty of remote work. We believed a multiplayer experience at the browser level would remove a lot of friction in remote collaboration. To put it another way: If the market had multiplayer at a 6, we believed that there was demand to crank it up to a 9.
Laying the foundation
How does a team of 4 build a novel default browser?
Life of a pixel in Chromium
On one hand, browser products have a high “buy-in” cost. People expect videos to play, mountains of tabs to be performant, and extensions to work. Open source makes this possible, but not easy. Chrome is on a monthly release schedule.
On the other hand, we were pre-pmf (product market fit) so iteration speed must be high. New learnings needed to turn into product updates, quickly.
We came up with two design goals to reflect this:
- Make edits cheap, especially to the interface
- Keep maintenance burden low
One of our first decisions was deciding between Electron and forking Chromium. Electron was attractive since it allows for UI to be written in web technologies, which we were well versed in. Unfortunately, it also strips out major features from Chrome like extensions and tab performance optimizations.
Learning from Brave’s run with Electron, we decided to fork Chromium instead1. We quickly found Chrome’s interface, built on the C++ Views framework, difficult to edit. I started researching ways to replace Views with a web renderer and write our browser interface in web technologies.
Our final setup allowed us to write all of our interface in React and treat tabs as nodes in our DOM. This is partially enabled by Chrome Apps and open source work done by Vivaldi. In a way, our setup is similar to Electron, except we didn’t take out all the parts that made Chrome a good browser. Going from 5 minute C++ links to HMR made us smile!
One of many browser prototypes
To keep up with Chrome’s monthly release cycle, we followed Brave’s approach of maintaining our fork as a set of patches. This mostly made rebases pain-free, although big changes that collided with our patches like the MPArch refactor proved challenging.
Figuring out how to build a browser with a small team was our ticket of admission. Now onto the game…
Creating multiplayer
Multiplayer came next. We wanted a Figma-like multiplayer experience across the entire internet. To accomplish this, we ended up building a novel way of streaming the DOM instead of video from one person to another.
Here’s how it worked at a high level:
- When a user joins a shared tab, Sail would snapshot the DOM on the host and rebuild it on the viewer. Subsequent changes to the page were captured using mutation observers and sent to the viewer over WebRTC data channels.
- On the viewer side, the DOM was reconstructed as a tab. A slew of event listeners monitored for mouse and keyboard events. These events were streamed back to the host and applied, completing the multiplayer loop.
Initially, everything was built on p2p WebRTC. This worked great with a few people, but didn’t scale past that. We eventually moved to a SFU-based architecture to support large rooms.
Here’s a demo in action:
Shipping product
Between 2021 to 2024, we shipped three major browser products. I’ll go into each one briefly, but for a more detailed look, Ron has a fantastic writeup including sharing internal materials for each product.
We held two strong convictions across all the products we built:
- People only have the appetite for one browser. We built everything with the intention of being default.
- Multiplayer and shared spaces remove friction in teamwork. We weren’t interested in building single player browsers.
Our first release was Sail, a browser with a traditional layout and multiplayer tabs. Multiplayer tabs was an exciting demo! But almost everyone rejected setting Sail as their default browser and instead saw it as a meeting tool.
Multiplayer tabs on a browser
We followed with a second release of Sail, built around a multiplayer canvas where websites can be placed alongside notes, images, and comments. A subset of users loved the product for themselves but couldn’t activate their teams. Frankly, fitting a browser into a canvas made the product too complicated and niche.
Sail with tabs on canvas
Finally, we built Muddy, a browser and chat in one. The goal was to replace Slack and Chrome with a single app, since most people were spending time switching between them.
Chat and browser in one
We launched publicly, hitting #1 on Hacker News and received 80k views on X. This convinced a lot of people to give Muddy a spin. As the weeks went on, it became clear that the majority of people struggled to get their coworkers and friends to work in Muddy. Many active users we interviewed wanted to use Muddy entirely by themselves because they liked tabs on a timeline.
Look! We're at the top
Winding down
While we felt like we got closer after 3 shots on goal, we weren’t able to reliably convince people to make a collaborative browser their default one.
I personally found that while people had a lot of paper cuts with Chrome and Slack and often were loud about them, neither was problematic enough to clear the high hurdle of championing something new. Our emphasis on multiplayer was met with lukewarm to ice cold reactions, with most people feeling uneasy about always-on multiplayer.
With each product, there was an opportunity to build something that grows but sacrifices one of our convictions (default or multiplayer). Ron and I always turned down these opportunities since we didn’t believe in where it led.
Ultimately, we ran out of ideas on how to move Muddy forward. It was a good time to close this chapter and move forward.
On AI browsers
I frequently get asked by friends what I think about the new crop of AI browsers rising today. I'm generally optimistic and will share some thoughts shortly!
Thanks
To all of our friends, family, and internet strangers that gave Sail / Muddy a shot – thank you!
We were very fortunate to have the support of great investors. I am forever grateful.
Lastly, I would have nothing to write about without our team that worked unreasonably hard to take a crack at building a new browser.
Appendix for browser nerds
- Life of a pixel - Google Chrome
- Chrome University
- Chromium Docs
- Letter to Arc Members - Josh Miller
- Mighty retrospective - Chase Lambert
Footnotes
-
This also gave us an excuse to own a cheese grater Mac Pro, one of the finest creations in the 21st century ↩