Moving From Nyxt to Surf

By Artyom Bologov

My pretty Nyxt starting page I will miss

I am no longer a maintainer of Nyxt. For a variety of reasons. I switched to Surf to realize my vision of focused, private, and task-centric browsing. And I'm not going back to Nyxt in the foreseeable future. My relatively popular config is likely to rot down in darkness.

Reclaiming Privacy

I am a privacy freak. Which means I often seem quite paranoid and am overly harsh on software. Because I care about our collective digital rights. Working on Nyxt and hearing "privacy is not a priority for us" was heartbreaking. But I had to bear with it. Now that I'm not tied to product and management, I'm ready to go the extra mile to secure my privacy:

What? Yes. I decided I should grant the privilege to run JS only to a select set of websites. This usually means my bank, email client, and a couple of privacy-friendly hyper/media websites.

See this Wired post as another testament to the niceness of JS-disabled browsing. The experience is incompatible with most browsing workflows, for sure. But it still has a niche it fills for me. A niche of focused private browsing for documentation or reading.

New Mode of Browsing

Now this last phrase marks an important change: I switched modes. My browsing falls into two general categories: entertainment and focus.

It goes without saying that minimizing the entertainment part makes one more productive.

Previously, I used Nyxt as a general-purpose browser. And that was quite chaotic and unproductive:

No more. Surf doesn't have session restoration, multiple tabs, or JS (given my customizations). And that keeps me focused.

Emacsy Web

Emacs is one of these kitchen sinks I'm trying to leave for more focused computer use. But Emacs is just too good and addictive to abandon. That's why I have muscle memory of the bindings. Vi modal editing is too much for me, like for many others too.

I have a StumpWM config that remaps typical Emacs bindings to CUA ones. It works almost everywhere. I made it work in Surf simply by adding CUA bindings to my Surf build. The config then maps Emacs keys to CUA bindings in Surf, giving me the experience I yearn for.

("C-n" . "Down") ("C-N" . "S-Down")
("C-p" . "Up") ("C-P" . "S-Up")
("C-b" . "Left") ("C-B" . "S-Left")
("C-f" . "Right") ("C-F" . "S-Right")
;; ...
("C-d" . "Delete")
;; Advanced text movement
("M-f" . "C-Right") ("M-F" . "C-S-Right") ; Jump one word forward
;; ...
;; Text editing
("C-y" . "C-v") ; Paste/yank
("C-w" . "C-x") ; Cut/kill
("M-w" . "C-c") ; Copy
("C-/" . "C-z") ; Undo
("C-?" . "C-Z") ; Redo
Some of my Emacsy key rebindings

I'm browsing the web with Emacs bindings now. But I don't have random JS hiccups when some Nyxt command tries to scroll the unscrollable page via JS bound to a key. Nyxt's promise of making the web Emacsy is laudable, but let's admit—CUA won. So the best course of action is to alias renderer-specific CUA bindings and deal with the annoyance.

Making User Agent Great Again

One of the most inspirational things I heard lately was Delan Azabani's Customising the web: browsers as user agents. It's a magnificent demonstration of how browsers can be molded to one's liking. Interactive, incremental, hands-on demonstration at that.

Thanks to this talk, I recalled my work on user scripts and styles in Nyxt. And how I actually suggested improving this functionality as a work vector. Unfortunately, using Chromium and WebExtensions prevailed. Making/adding/using scripts in Nyxt is still a kludge.

Not in Surf. There's a file (or a set of files, if you apply sitejs patch) you can put your JS code into. Start Surf, and it will run this code on any matching website. Want to change something on the website? Just write some new code to the file.

This is an important thing: browsers should be user agents. They should be easy to change to the user's liking. Nyxt is not (yet?) easy enough to customize. At least with regards to user scripts/styles—the most fundamental customization medium. Surf is.

Simplicity = Malleability?

And that's what brings me to the last point: Surf is malleable. Not because there's

There's none of these in Surf. But there is a really small and clean codebase. 2K lines for the whole thing. When one spends an evening reading the code, they will know everything about the browser. Hacking the functionality into Surf becomes a matter of extra function addition. That's why there're so many patches for Surf—it's too malleable to not have them.

Still, I'm somewhat uneasy about calling a C program malleable. Like, it's not dynamically moldable at runtime. Which is the conventional idea of malleable software. As a consolation and resolution, I cannot but agree with this comment on the Malleable Systems forum:

... I also kind of wish I could somehow get a language (or rather first, a programming philosophy) with the best features of all three approaches. I’d like a language and OS to be as malleable as possible (so I can change anything I want), as minimalist as possible (so I can hold it all in my head, because I can’t change what I don’t understand), and also to strictly enforce any logical laws I require it to (so once it’s changed it stays changed and doesn’t get changed by someone else).
a comment by natecull on Malleable Systems forum

Surf is small. Surf is understandable. Surf is locked and compiled once you're done with changes. QED, Surf is malleable.


Did I lose anything when switching from Nyxt? Yes, a lot. Did I gain something from switching to Surf? Yes, a lot too. My change of modality conditioned the change in tools. And I'm happy with how the tools match my requirements now. Will it be the same for you? No, but it might be worth trying Surf anyway. And do check out my fork of Surf—I've added a lot of customizations you might find inspiring!