What I Learned Building an Open-Source Chromium Browser
Most developers spend a significant part of their day inside a browser.
I do too.
But after using mainstream browsers for years, I kept wanting something slightly different: a browser that kept Chromium compatibility, but felt less like a general-purpose consumer application and more like a tool built around a developer workflow.
Vertical tabs. Fast keyboard navigation. Easy access to developer tools. Fewer distractions. Privacy features without installing several extensions.
So I started building one.
The result is Yalqen, an open-source Chromium-based browser for macOS.
GitHub: https://github.com/YSamed/yalqen
Website: https://yalqen.com
This post is less about announcing the project and more about what I learned while building a browser with Electron, TypeScript and Svelte.
Why build another browser?
That is probably the first question.
Yalqen is not trying to build a new rendering engine.
Chromium already solves an enormous set of problems: web compatibility, rendering, JavaScript execution, networking, media support, DevTools and a huge amount more.
The part I wanted to experiment with was everything around the web page.
The browser itself.
I wanted the UI to stay out of the way and make common actions faster.
The basic idea became:
Keep Chromium underneath, rethink the workflow around it.
That resulted in a few principles.
Vertical tabs first
Horizontal tab bars work well until they don't.
Once enough tabs are open, titles become unreadable and every tab slowly turns into a favicon.
With vertical tabs, the browser has much more room for readable titles while keeping the page itself clean.
In Yalqen, pinned tabs, navigation and window controls are designed around this vertical layout rather than being added later as an optional mode.
Keyboard-first navigation
I wanted opening a page, switching tabs and triggering browser actions to require as little mouse movement as possible.
That led to a command bar becoming one of the central pieces of the browser.
The goal is similar to command palettes in development tools: instead of remembering where an action lives in the UI, start typing.
Developer tools should feel native to the workflow
Chromium DevTools are already extremely capable.
There was no reason to reinvent them.
Instead, Yalqen focuses on making developer-oriented actions easier to reach, including a quick phone view for responsive testing.
The browser should make the existing Chromium tooling easier to use rather than hiding it behind several menus.
The stack
Yalqen currently uses:
- Electron
- TypeScript
- Svelte
- Vite
- Node.js
- electron-builder
Electron sometimes gets criticized for being heavy, and that criticism can be valid depending on the application.
For a browser project, though, the trade-off is different.
Electron already embeds Chromium.
That means instead of trying to embed and maintain Chromium from scratch, I can focus on browser behavior, UI and integration.
For an experimental open-source browser maintained by a small project, that is a very useful trade-off.
Separating browser logic from browser UI
One architectural decision that became important early was keeping responsibilities separated.
The source is divided roughly into:
src/
├── main/
├── preload/
├── renderer/
└── shared/
The main process owns browser-level functionality.
Things such as tabs, downloads, permissions, ad blocking, browser commands and other Electron integrations belong there.
The renderer contains the actual interface.
That is where Svelte is useful.
The preload layer provides the controlled bridge between the renderer and Electron functionality.
And shared contains code that can safely be used across boundaries.
This separation is important for more than code organization.
A browser handles arbitrary websites.
That means the security boundary between web content, browser UI and privileged native functionality matters a lot.
Treating everything as one giant renderer process would make the application simpler initially, but considerably harder to reason about later.
Building the command bar
The command bar started as a navigation feature.
It quickly became more interesting.
A normal address bar basically answers one question:
Where do you want to go?
A command bar can answer several:
Where do you want to go?
Which tab do you want?
What browser action do you want to run?
That makes it possible to unify navigation and actions behind a single interface.
This is particularly useful for keyboard-heavy workflows.
Instead of designing a separate visible button for every feature, many actions can remain discoverable without permanently consuming screen space.
That also influenced the overall Yalqen design philosophy.
Features should not automatically become UI.
Sometimes the better interface is a command.
Ad blocking without requiring another extension
Privacy was another area where I did not want users to assemble the browser themselves after installation.
Yalqen includes ad and tracker blocking directly.
For the filtering engine, the project uses the Ghostery ad-blocking library rather than attempting to create a filtering engine entirely from scratch.
This is another recurring lesson from building Yalqen:
Build the part that makes your project unique. Reuse mature infrastructure for solved problems.
Writing an ad-blocking engine sounds interesting until you start considering filter list parsing, request interception, cosmetic filtering, updates and edge cases across the web.
Using an existing engine means development effort can instead go toward integrating blocking properly into the browser experience.
Yalqen also includes other privacy-oriented features such as third-party cookie blocking, HTTPS-only behavior and secure DNS support.
Shipping a macOS browser is more than building an app
Getting the browser running locally is only part of the work.
Shipping it as an application people can actually install is a separate problem.
For macOS that means dealing with things such as:
- application signing
- hardened runtime
- entitlements
- notarization
- DMG generation
- application updates
The difference between:
npm start
and:
Download this application and trust it with your browsing
is significant.
A browser handles some of the most sensitive activity on a computer.
Users should not need to bypass Gatekeeper warnings or run suspicious terminal commands just to try it.
Yalqen's macOS builds are therefore signed and notarized.
The project also generates DMG and ZIP releases and supports application updates.
It is less exciting than implementing tabs, but distribution infrastructure is part of the product.
Automatic updates changed how I think about releases
Initially it is tempting to think:
I'll just publish another DMG when something changes.
That becomes inconvenient very quickly.
A browser is the kind of software where users should not remain on an old version indefinitely.
So Yalqen includes an update mechanism.
This also changes how releases can be approached.
Instead of treating every release as a major event, fixes and smaller improvements can be delivered much more regularly.
For an open-source desktop application, that creates a much better feedback loop:
release
↓
users test
↓
issues / feedback
↓
fix
↓
new release
The shorter that loop becomes, the faster the application improves.
Browser development has an unusual number of edge cases
A browser looks deceptively simple from the outside.
There is a window.
There are tabs.
There is a URL bar.
Then you start implementing it.
What happens when a website requests camera permission?
What happens when a download starts?
What happens when a certificate is invalid?
How should popups behave?
What happens to tabs when the application restarts?
How should pinned tabs behave?
What happens when a page opens another window?
How should keyboard shortcuts interact with websites?
What happens when memory usage grows because dozens of tabs remain open?
Each seemingly small feature opens another set of browser-specific decisions.
This has probably been the most interesting part of the project.
Building a browser UI forces you to think about many systems that normal web applications never need to consider.
Keeping the project open source
Yalqen is released under the MIT license.
Making the repository public was important for a few reasons.
First, browsers require trust.
Being able to inspect how an application handles browsing behavior, permissions and privacy features is valuable.
Second, browsers contain an almost endless number of potential improvements.
There will always be another workflow, edge case or platform behavior to improve.
An open repository makes it possible for those discussions to happen in public.
And finally, I think browser experimentation is interesting.
The web has largely standardized around a small number of browser engines, but that does not mean browser interfaces need to be identical.
There is still plenty of room to experiment with how we interact with the web.
What I would do differently
The biggest lesson so far is that browser features become interconnected very quickly.
A change to tab behavior can affect session restoration.
A navigation change can affect the command bar.
A privacy feature can affect page compatibility.
A window-management change can affect fullscreen behavior.
If I were starting again, I would define browser state boundaries even earlier.
The clearer the ownership of tab state, window state, navigation state and persistent state is, the easier later features become.
The second lesson is to resist adding UI.
It is easy to keep adding buttons because every browser feature appears to deserve one.
Eventually the interface becomes the thing you were trying to avoid.
For Yalqen, I am increasingly convinced that the command bar and keyboard shortcuts should absorb many secondary actions.
What's next?
Yalqen is still early.
There are plenty of things I want to improve, and I expect the direction to evolve as more people use it.
For now, the focus is simple:
Build a fast, keyboard-first Chromium browser for developers that stays out of the way.
If that sounds useful, you can try it on Apple Silicon Macs running macOS 13 or later.
The project is completely open source:
GitHub: https://github.com/YSamed/yalqen
Website: https://yalqen.com
If you try it, issues, pull requests and feedback are welcome.
And if you want to follow the development, starring the repository is the easiest way to find it again later.
