I’ve been busy, so I’ve got a fun story to share today. If you’ve been following me and reading my blog, you probably know at this point that I love tinkering with my Kobo e-reader.
Unlike other e-readers, Kobo e-readers don’t need to be jailbroken if you want to mod them. It’s one of the best things about these devices. I like it very much: it’s customer friendly and definitely a good reason to get one!
In fact, if you don’t have one yet, you should probably pick one up. (I’m just a fan, I don’t get a cut of any sales, by the way.)
I’ve had my various NickelMenu customizations on GitHub for some time now, and if you’ve been keeping up with the series on typography on Kobo devices, well… you might have picked up a new font.
I love reading on these devices, but I also love tinkering with them. I may not be a low-level programmer with reverse engineering knowledge, but I do like “hacking” my devices to extend their functionality. Usually, that means other and smarter people have done the heavy lifting for me.
A while ago, I discovered kobopatch and I never really thought I needed to manually apply such a patch on a device, until I bought a Kobo Clara BW which features – on the home screen – that third row of recommendations and advertisements, some of which cause the layout to jump.1 Oops.
👋 This is the origin story of KoboPatch Web UI. If you prefer to watch a video than read, there’s also a YouTube video that I made. Not looking to learn why I made it and just want to patch your device? You can visit the website here.
Bloated home screens
Now, I’m fairly confident I do not have OCD… but I have been ruined by my profession when it comes to typography, design and layouts. I tend to pay close attention to how things are built, and I simply can’t stand a bad UI.
I also tend to have a disgusted reaction when I encounter dark patterns that are clearly meant to manipulate people.
One particular example that immediately comes to mind is Kindle’s home screen – half of which is, for the most part, one big ad for their storefront. I immediately bounced off of Kindle for that very reason, despite the hardware and the reading experience being totally fine.2
I mentioned this earlier in my blog post about moving to Linux, but I very strongly believe that we should not tolerate user interface patterns that do not respect us.
Amazon’s ad-infested home screen filled with recommendations isn’t respectful of our time and eyeballs. Recommendations on the home screen don’t help us finish our book collection.
No, this screen, filled with pretty covers was designed to make us purchase even more books. Not to showcase books we might already own, nor to encourage us to continue reading our current reads.
To be clear: book discovery can be a good thing, but you know when I want to look for the next book? When I’m done with the current one.
I consider an e-reader a novelty device with a singular feature – it’s a device with little to no distractions, exclusively intended for reading. Kobo’s home screen is far better, in my estimation.
As you can see, Kobo does a better job. There’s some advertising for Kobo Plus and the store, but it’s less oppressive. Despite this positivity, Kobo’s homescreen could be better:
- If you are reading only one book, the operating system will sometimes display a couple of other books on the right of your current read. I’ve usually found that juggling multiple books at once isn’t that fun.
- There’s a third column below My Books that sometimes displays useful information (“You’re read for a total of 50 hours!”) but usually advertises Kobo’s subscription service or store.
I like owning books, so I tend to just straight up buy them from the store when I need them. Advertising to me isn’t going to make me change my mind. My complaints about Kobo’s home screen UI are simply gone if those elements were simply something you could turn off.
Before they introduced the current home screen many years ago, you could actually dismiss individual tiles from the old home screen, which was cool.
I wish they re-introduced this functionality, but… what if you could do that today?
Patching it out
Well… as it turns out, you can. Kobo devices run their own custom software, running on Linux with their own GUI based on Qt. It’s a fairly open system compared to the locked down proprietary stuff on Kindle.3
There are custom patches that you can apply that do this. All you need is a copy of the system software (which you will need to download the correct version for your device of) the patches, and kobopatch.
The latter is a command line tool that you can point at a particular patch so you can apply it to the system software, which you can install after patching it.
Here’s how this process usually went:
- Rakuten Kobo releases a new version of their software, so you update your device. Any existing custom patches you made are now gone.
- You can usually find a
zipwith patches on the MobileRead forums. You can search for “Patches for Firmware” and then the version number of your firmware. - To do this, you must first note what operating system version you are using.
- You can then download a copy of the software via the Kobo firmware page kindly set up by Patrick Gaskin. This is also the author of
kobopatchand NickelMenu, by the way.4 - Once you have the files saved in the right location can then apply patches via
kobopatch. For up-to-date instructions, use thereadme.txtfrom thezipyou got from MobileRead. - After applying the patch, you copy the
KoboRoot.tgzfile to the.kobofolder on your actual device via the USB connection.
So, it’s not super complicated, but it’s a tad annoying to do, and I’m always a little bit paranoid that I’m going to download the wrong software files and brick my device.5
For me, I used to apply this patch in kobopatch.yaml, and only this one:
overrides:
src/nickel.yaml:
Remove footer (row3) and increase cover size on new home screen: no
Remove footer (row3) on new home screen: yes # <--- I changed this!
However, recently a new software update was released for my Kobo Libra Color, and the previously applied patch was no longer applied because it was overwritten by the new system libraries that came with the updated system software.
This is in stark contrast to my NickelMenu configuration, which persists when system updates are installed due to the nature of the injection mechanism behind NickelMenu. Also, there are a bunch of safety mechanisms built-in:
A built-in failsafe will automatically remove NickelMenu if any fatal error occurs, and will never result in an unbootable Kobo. Non-fatal errors will appear as a menu item with more details.
Super cool. For a more technical deep dive, I recommend checking out NickelHook, which is a part of what makes NickelMenu work in this way.
This involved process I documented above is what things were like until recently.
KoboPatch Web UI
But then I thought: wouldn’t it be easier if I could just connect a device and have the CLI automatically recognize what kind of device it is?
I could probably automate downloading the system software… then, patching it on the fly is a trivial and automated process because kobopatch exists.
Maybe, if I used WebAssembly, I might even do all of this patching in the browser, so I wouldn’t have to download the patches every time? I could theoretically patch my Kobo from anywhere this way.
Okay, well, that doesn’t sound too bad. If I could just click a button on a web page and it’d generate a KoboRoot.tgz patch file for me, that would literally be the easiest way to set this up, barring having to copy that file to the actual device.
That reminded me: I also remembered that Google Chrome had an API that allows you to give it access to a folder on the filesystem, so if you point it at your Kobo, literally all of this could potentially be automated.
The whole process could become a simple wizard with three steps: identify device, apply patches and copy the files onto the device, all done by the browser with a few clicks.
At that point, all it takes is connecting the device via USB and safely ejecting it when done. The WASM bit was where I was the most concerned, but thankfully kobopatch was written in Go… which is good news.
Woah. Technically, this could be doable! This could be very cool!
Now, to be clear: this was just an idea at this point. But I wanted to see what was possible, so I wrote a short and simple text file with what my technical requirements were, and got to work with my favorite LLM to see if I could get a prototype up and running and verify the actual viability of this project.
It didn’t take very long to get some promising results. These large language models sure are something, if you know how to properly instruct them and check things carefully.
Sure enough, after an hour or three of tinkering, I had a rough version up and running with the key WASM kobopatch conversion passing all of the tests.6
Wild.
So, case closed? I could probably close the book on this. This would be the easiest way ever to patch my Kobo devices with these patches.
I would just need to connect them via USB… and it all worked.
It was great. Until I had an even better idea.
Forking NickelMenu
The problem with applying the specific fixes I mentioned earlier, is that you need to re-apply these patches every time a new update comes out.
That’s annoying. A few other factors are also in play:
- How quickly Rakuten Kobo releases updates
- How quickly it takes for patches to be verified
- How difficult it is to patch your device
- How many different devices you need to patch
If I was away or on holiday and an automatic update were to install itself (as it does, sometimes, for minor updates) then my customizations for the homescreen would be gone. It’s not a super big issue, but it’d be unfortunate.
This is not an unrealistic situation – my Kobo Clara Color actually did this to me when the March 2026 update came out. I picked it up and the crowded home screen was back after an update had installed itself overnight after syncing.
Frankly, if this particular home screen tweak were to persist even after updates are installed, it’d be even better. This brings me to my better idea.
Here’s what you should know first.
I believe I mentioned NickelMenu earlier. It is actually a modification that persists after software updates, because of how it works. It patches onto the system partition a new file that never gets overwritten by Kobo’s software packages, but can uninstall itself if it deems itself incompatible.
It introduced an experimental feature in the last update that allows you to customize the navigation tab bar at the bottom of your device, even to the point of being able to hide specific tabs and renaming them.
In the NickelMenu configuration file in .adds/nm/items, you can do that like this:
# Menu button customization
# this line renames "My Books" to "Books"
experimental :menu_main_15505_1_label: Books
# this line hides the notebook
experimental :menu_main_15505_3_enabled: 0
So, I wondered: what if I could also do something similar to the relevant widgets on the homescreen – as in, hide them? I knew that Nickel, the software running on Kobo devices is all Qt-based, so in theory it should be possible.
Now, I have very little experience writing C++, but there were plenty of examples in the existing code, so all it took was adding two sections to src/nickelmenu.cc.7
I’ve annotated the code to make it easier to understand. Okay, first, the registration of the hook and the necessary type information:
// fake type alias for an unknown class so we can hook it;
// we treat it as a QWidget because we don't have the actual
// class definition (no source code access)
typedef QWidget HomePageView;
// function pointer to the original constructor
// filled in by the hook system below
void (*HomePageView_HomePageView)(HomePageView*, QWidget* parent);
static struct nh_hook NickelMenuHook[] = {
// (other hooking omitted, reformatted for easier reading)
// ...
// home page widget hiding (15505+)
// this is where the actual hook is registered
{
.sym = "_ZN12HomePageViewC1EP7QWidget", // original constructor...
.sym_new = "_nm_homepageview_hook", // replacement function
.lib = "libnickel.so.1.0.0", // in this library
.out = nh_symoutptr(HomePageView_HomePageView), // we store the original constructor here
.desc = "home page widget hiding (15505+)",
.optional = true // skip hook if not found
}, //libnickel 4.23.15505 * _ZN12HomePageViewC1EP7QWidget
// additional note
// the libnickel annotation w/ version is for the test workflow
// ...
};
After that, it was a matter of adding the actual hook itself, which accomplishes what I’ve been meaning to get working – i.e. the hiding of certain elements on the homescreen. That’s hiding, not removal – as I didn’t want Nickel to crash.
extern "C" __attribute__((visibility("default"))) void _nm_homepageview_hook(HomePageView *_this, QWidget *parent) {
// it's always good to log these kind of things
NM_LOG("HomePageView::HomePageView(%p, %p)", _this, parent);
// call original constructor before modifications!
HomePageView_HomePageView(_this, parent);
// identify which object names we will look for
const char *hide_widgets[] = {"row1col2", "row3"};
// we'll loop over those potential widgets
for (size_t i = 0; i < sizeof(hide_widgets) / sizeof(hide_widgets[0]); i++) {
// identify what key we need in the config file for this one
char key[32];
snprintf(key, sizeof(key), "hide_home_%s_enabled", hide_widgets[i]);
// read the configuration value from the config file
const char *val = nm_global_config_experimental(key);
// ensure configuration value is present and enabled
if (!val || strcmp(val, "1"))
continue;
// attempt to find the widget based on Qt objectName
QWidget *w = _this->findChild<QWidget*>(QString::fromLatin1(hide_widgets[i]));
if (w)
// and if we can actually find it, hide it at runtime
w->setVisible(false); // this is where the magic happens
else
// or log that the widget could not be found
NM_LOG("warning: could not find home page widget '%s' to hide (it may not exist on this firmware version)", hide_widgets[i]);
}
}
Once again, an LLM came to the rescue when building this and I was able to come up with this – I triple checked it for errors, made sure I properly understood what was happening (and understood the safeguards) and then tried it on actual hardware.
Sure enough, my forked version of NickelMenu didn’t cause any issues that I could see, and worked like before, but I still had to actually enable the new feature for testing and reboot my device. The hook in particular kicks in when the home screen is first rendered, so it’s important to restart your Kobo if you want this to work.
Here’s how you enable those specific tweaks:
# Hides recommendations next to current read
experimental:hide_home_row1col2_enabled:1
# Hides info text (time read, store, kobo plus ads) below My Books
experimental:hide_home_row3_enabled:1
When I added the new configuration flags to my NickelMenu configuration file and rebooted, it worked just as expected – but without needing custom patches.8

In the meantime, I’ve also opened a pull request to NickelMenu with this change. Even if this code doesn’t make it in the actual project, it’s doing exactly what I needed it to do, so I’m very happy.
Unifying both solutions
Now, I had this pretty cool Web UI project, but what if it could also install NickelMenu? That would be awesome and the best of both worlds. It’d also be a much better and (not to mention) safer default option for anyone interested in tinkering with their device.
It would also allow me to install my customizations to all of my devices, and if I decide to update the customizations, all I need to do is plug in my device and go through the wizard, which only takes a few seconds.
(I noted earlier in a footnote that I previously bricked my Libra 2 like two years ago when I attempted to downgrade my system software, and it sucks when you brick a device. You’d think I learned to stop tinkering with my Kobo devices after that happened, but no. All I’ve done is learn from my mistakes.)
I decided that I was going to integrate installing NickelMenu into the flow of the patcher. The idea was simple; at the start, you need to decide what you want to do:
- Do you want to install NickelMenu with or without a preset? This works on most, if not all devices running a modern software version.
- Do you want to apply custom patches and install those to your device? This works only on a limited selection of devices via the web UI as of right now.9
There’s definitely still some areas of improvement, and I plan on tackling those in the future, but I was able to get all of this working.
I should also note that my forked version of NickelMenu is downloaded in order to support the hiding of those home screen widgets, but should this change get merged, I will make sure to link to the original project again.
So, you might be thinking – I want to check that out and try it! I have some good news, because everything happens client-side, I was able to host a static site on my Coolify instance with a nixpacks configuration file.
I’ve hosted the project on a subdomain here:
If you don’t have a device or don’t want to use Chrome, you can always choose to generate an archive with the patches and inspect it.
I hope if you’re a fellow tinkerer, you find it useful, too. (Even if it’s only to check out the generated zip files to see how it all works.)
In the meantime, the author of NickelMenu and kobopatch had some good feedback and provided me with some additional technical guidance in the MobileReads thread where I posted about this.
I hope to be able to further improve this project in the future. There’s definitely a few more cool things that would improve the general user experience and there’s still quite a lot of automation potential.
But for now, I’m going to take a bit of a break… and finish that book that I’ve been reading.
Updates
After initially writing this blog post, I’ve made some additions. You can find these below.
First off, if you want to experience this blog post in video form, I made a few helpful videos. First, the story of this blog post is partially explained in my first video:
I also recorded a more recent video (a while after initially publishing this blog post) that you can find here:
Update
May 16, 2026
I have been updating the tool over the last few weeks to make it more easy to use, and I’ve fixed a bug that caused books to vanish. I’d like to apologize for that one, as it caused some unintentional data loss.
Initial issues like these due to edge case bugs or oversights are why I included a disclaimer to backup your sideloaded content, which I still recommend doing despite the fact that at this point KoboPatch Web UI is pretty battle-tested.
I’ve also updated my fork of NickelMenu so it’s a little more targeted when it comes to hiding elements, and it’s now also possible to hide the content next to “My Books” on the home screen.
(I should note: I previously mentioned this in a footnote. You can find the updated fork on GitHub with this new change. For historical purposes, I’ve not amended the source code of my changes here in this blog post.)
I hope you continue to find KoboPatch Web UI useful!
Update
May 28, 2026
In the meantime, I’ve also recorded a a video which acts as a demo where I apply the tweaks and install KOReader on my Kobo Clara BW. I’ve attached it inline to this blog post, above.
This is a more recent video than my original demo which also includes information about why I made this project. Both are worth a watch, but if you want to see how to quickly set things up, the video above is probably sufficient.
Update
June 14, 2026
I’ve pushed out a substantial update to KoboPatch Web UI, which will probably be the last significant one for a while. It adds support for NickelClock as an optional add-on, and gives you various new customization options.
Those who like custom patching will be happy to learn that you can now easily search for patches and edit them as needed, too. This was part of the initial feedback I got from folks on the MobileRead forums, and that’s now integrated.
To explain what has changed, I also recorded a 10-minute video:
Another thing I’ve done: in the event that my pull request doesn’t make it into NickelMenu, I’ve now created a standalone mod that does the same thing.
I’ve called mine NickelHome, and it allows you to apply the same home screen customizations that are baked into my NickelMenu fork, but without needing NickelMenu:
# Hide various home screen widgets
hide_home_row1col2_enabled:1
hide_home_row2col2_enabled:1
hide_home_row3_enabled:1
This may eventually get integrated into KoboPatch Web UI, which means I will be able to use the stock version of NickelMenu on the website, which should be easier to maintain and cause less issues and maintenance burden for the original author.
(The website using NickelHome isn’t the case right now, so keep that in mind. But it is something I am considering!)
So far, the website has been used a lot more than I’ve expected. I’ve had over 1.5k unique users complete a flow (that’s install or patch) so far, according to my anonymous analytics.
I’m confident that folks like knowing it’s easy to uninstall, because about 15% of users actually do that, too. Yay for easy and safe experimentation!
On the Kobo Clara 2E, which used Georgia as the system font, the height of these text blocks was more or less fixed at two lines. But with the new system font, Rakuten Serif, this is no longer the case on the Kobo Clara 2E, which has a display with the same screen resolution. On this new device, the layout of the homescreen tiles will now be shifted because the text now needs 3 lines due to different font metrics (Rakuten Serif is slightly wider) which was likely not accounted for. The Activity screen is similarly broken for long book titles, by the way. ↩
I’m also not that big a fan of Amazon for other reasons, but that’s not relevant to this post. My dislike of big tech companies isn’t relevant to the broader point, and Amazon is probably less problematic than others. ↩
You might be familiar with jailbreaking. Because Kindle is a closed off device, hackers try to make it so you can put your own software on there. Amazon typically tends to fix the exploits that allow this to happen. ↩
What a legend! I’m positive that without Patrick’s contributions, there wouldn’t be such an active modding community for this platform. I’m grateful that all of this stuff was open sourced. It’s also really interesting to take a technical look at how all of this is accomplished, so I highly recommend reading up on how this is all accomplished and checking out the source code. ↩
Well, maybe it isn’t paranoia, because I actually bricked a Kobo Libra 2 once. The crucial mistake I had made was that I’d installed the firmware files of an older revision on a newer Libra 2 revision when I attempted to downgrade the software. I had no idea it was a newer revision at the time, but trust me: I know better now. I double – no, triple check these kind of things now. ↩
While the technical “testing” of this initial version took only three hours, it would take three days to properly polish something that I’d call a nice 1.0 version with a decent user experience. ↩
The closest I’ve come to writing C++ is when I learned some C, which was a prerequisite for Objective-C at the start of my career in 2014 – and it isn’t like Objective-C is very relevant these days… If it wasn’t for the assistance of LLMs, this would have taken a lot of tinkering for someone unfamiliar with the language, and frankly, I might have given up. ↩
To be entirely correct: well, two out of the three toggles I added did. I had to remove one (
row2col2) because it also affected the “My Books” section, as it made individual books in the “three books next to each other” view disappear. It didn’t even properly remove the last viewed Collection – which was sort of the point – so this was clearly not the right way to identify and hide that particular widget on the homepage. (In the future, I suppose I could still try to enumerate each of the elements and see if there’s another one I can potentially disable, but that’s something for another time.) ↩I only have one fixed version that is supported in the web UI, and that version is only installable on Kobo Libra Colour, Kobo Clara Colour, and Kobo Clara BW. This may change in the future, but for now I’ve decided to limit support to those devices. ↩
This was not generated: Unless explicitly specified, the posts on my blog are my own creative work. 100% written (typos included) and edited by me; not generated using e.g. large language models.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.