A few weeks ago I had ordered a few too many small SBCs (single-board computer). I was starting to struggle to use them all. I had waste, especially e-waste, so I wanted to put these little boards to good use. I also had a small desk in my living room that I wanted to use more for non-work related things like writing. My brain subconsciously did a 1+1 and I ended up with the idea to take on of the SBCs and compose a small linux distribution that’s focussed on just writing.
I have a nice keyboard and I’ve attempted to hook it up to an iPad and try to write something. But since I’m used to programming in text editors with near zero latency, i’m a bit spoiled. I get easily irritated when a character that I’ve typed doesn’t show up Immediately. Also, using modal editors is so second nature to me. It’s odd to start writing on anything different, since the shortcuts are almost baked in for me
So what was I to do? I had started another small side project trying to get Helix working as an iPad app. That way, I could have some of the perks of zero latency and modal editing back. But, this meant that I had started another side-project that I was not sure If I was able to complete.
The idea sat for a while and I had stopped writing again because of it. If something I want to do requires some kind of friction, I end up not doing them.
Requirements for the “Typewriter OS”
I have a lot of things that I want to write, but it’s really easy for me to get distracted. By other side projects, or a nice DM for a friend I haven’t talked to in a while. So it’s super important that this little computer has no distractions whatsoever.
Another thing that’s important is the zero latency typing. No heavy programs that cause my keystrokes to take more than the required milliseconds to process them and draw them on screen. Even with a small amount of latency is like psychological sandpaper while I’m writing: something I definitely don’t prefer.
It should be accessible for me to quickly jump on, write something, save my work and share it with the world ✨.
So how are we going to accomplish all of this, especially on some random SBC?
Making “Typewriter OS”
Deciding on a base
I decided to use Alpine Linux as a base to build on, since it’s very barebones and doesn’t come with any bloat at all. But, I still needed that OS to work on the SBC that I had available.
The SBC in question is the Radxa Zero 3W, a cute little Raspberry Pi Zero clone that comes with built-in WiFi and Bluetooth, super neat! It also rocks the Rockchip RK3566, a relatively fast and somewhat efficient little processor that has decent (that word doing a lot of heavy lifting) support in drivers and in the Linux kernel.
So, how do you start this? Perhaps similar to a Raspberry Pi? You just go on the internet and type in “Radxa Zero 3W image Alpine Linux” and you’ll find… nothing…
Calling this a niche board would be somewhat of an understatement. Since the company that makes it Radxa has nowhere near the amount of following that Raspberry Pi does. Yet, as far as I know, Radxa did not employ a known cop to work for them, so that’s good enough for me.
This does mean however, that we need an alternative method to get Alpine Linux to work on our little computer.
Getting started with a little help
Turns out there is this lovely person named Joshua Riek that already made images for an extensive list of Rockchip SBCs that worked Great out of the box! This was a huge relief and definitely settled some of the anxieties I had with this little side-project. The images featured the panfrost kernel module/driver. These allow the GPU inside of the RK3566 to be used more effectively, which made my zero latency requirement a lot more doable than initially anticipated! ✨
For the next step, I took one of those images, burned it to a micro SD card and went inside of the system partition that holds the “root filesystem” and deleted everything. Then I went to Alpine Linux’s download page and downloaded the “minimal root filesystem” tarball and extracted where the previous system had been. There’s no way it’s that easy right?
I wrote the files to the SD card, unmounted the partitions and stuck it into the SD card slot on the SBC and turned on to… See it boot successfully into Alpine Linux! ✨ There was however, still an issue: I couldn’t log in :/
However, there’s nothing a little bit of kernel parameter changing can’t fix! I found out that you can tell Linux to start a program before any other program when your computer boots. This way you can circumvent the login screen and immediately get “root” (Linux’s administrator) access! I did this by adding init=/bin/sh
to the kernel parameters, telling it to run a command-line (one of those >_
with the blinking underscore thingies that people used back in the 80s (and still to this day)).
Then from that command-line I could change the password of the root administrator account and reboot with the old parameters and try and login! It worked ✨.
Setting up the main system
While I was looking around to fix problems related to the Radxa’s WiFi driver. I stumbled on a small guide written by CFSworks, which showed the steps you need to take in order to have a minimal Alpine Linux system working on a similar SBC. This guide was super helpful, because I had acquired the WiFi drivers by copying it over from another image, but Alpine Linux seemingly didn’t load them. By running rc-update add hwdrivers sysinit I was able to make sure the drivers were loaded during boot! (Definitely check out the guide for more details if you need them).
Now it was just a matter of setting up WiFi through iwd and making sure that everything started up properly during boot. This way, I can assume that my device always starts up with an internet connection ✨. I did this by enabling the networking
service (rc-update add networking boot
) and by manually adding the wlan0
interface and making sure that udhcpd started up properly. Funnily enough, the boot procedure was a bit too quick sometimes, causing the WiFi chip to not be fully loaded by the time the networking
service attempted to connect to the internet. By adding a small sleep
1 into the /etc/init.d/networking
service file, I was able to patch that somewhat. It ain’t perfect, but it works :)
Making a little desktop
Now that I had the basics of my system settled, we should start with making the actual “typewriter” part of this device. We just need to make a graphical interface-y thing that we can actually do the writing on, simple enough right?
I started testing some window managers that I’ve been hearing a lot about. I made sure that they were lightweight enough to run quickly and responsively, while also being somewhat simple to setup and modify. I wanted to try doing things with Wayland window managers first, things like sway and Hyprland. Unfortunately, there’s something weird going on with the way that the device starts programs. There was a really noticeable delay of about 5 seconds whenever I start a GUI program. The animations on Hyprland seemed fancy in previews, but with somewhat limited performance by the SBC, it was quite hitchy. This might be due to the “Panfrost” drivers not extracting everything they can from my SBC’s GPU. Unfortunately, several days later I also discovered that the Hyprland project fails to not be bigotted, so I decided to avoid Hyprland in general.
There weren’t similar problems on sway luckily. I did notice a small amount of latency between my input and characters appearing on screen in my terminal and that was a dealbreaker for me. So I decided to do the next best thing: good old Xorg with i3 as a window manager ✨.
Right from the start, there was close to no notable latency while typing, which was neat! However, the weird startup latency with GUI apps was still there, likely something that goes a lot deeper than something I was ready to take on right now, so I decided to build around it.
Setting up i3 as our workspace
Now that we have our “window manager” canvas ready, it’s time to do some UX painting . What I wanted to do, is to start up the device and for it to just open into my favorite writing program, in a directory full of files for either my blog, a story, a visual novel, etc. Here’s how I did it.
I went to configure i3, but I didn’t focus on what most users would do like setting up workspaces, shortcuts, etc. Instead, I removed all of the shortcuts that I didn’t need and start up a terminal emulator with the command to start my writing program. I then altered the default theme of i3, my terminal and the text editor to match eachother. I ended up with what feels like a monitor that only displays helix-editor whenever I start up the window manager.
The last step was quite simple, getting the window manager to start whenever I booted. I simply made sure that tty1 logs into my user by default, something that is really dangerous when done on a PC. But since this device has the singular purpose of just writing and it doesn’t store any personal information from me on here, it’s fine :)
Then I just made sure that my shell checks if it’s running on tty1
and if it is, it would start Xorg ✨. I restarted my device after setting it all up and it works beautifully.
The lack of shortcuts or ability to start up any other program makes it the perfect “distraction free” writing computer. All this to make me focus on what I want to do more: write. Hopefully, this will just kind of exercise my writing muscles in my brain so I can do it without this device at some point. For now these are great lil’ training wheels for my developing writer brain :)
Closing thoughts
Building a computer for a hyper-specific use-case is a bit silly, but if it works, it ain’t silly. I really don’t like how I’ve gotten stuck in tech-y side-projects over the past year. I should be writing more, so if this tech-y way of solving the problem has tricked my brain to write more, I’ll take it!
Does this mean that you should do the same? Absolutely not, unless of course, you suffer from the exact same problem. There’s no use in reproducing a solution to which you don’t share the problem with, because it’s likely it won’t be the proper solution for you.
As for now, thank you so much for reading this very long post about how I solved a somewhat trivial problem for most ✨