Viewing archived v1 of 2 · 4 h ago · [back to current] · [history]

Thermalith: an open-source desktop label designer for NIIMBOT printers

I went quiet on the blog for a month because I was building this. Thermalith is an open-source desktop label designer and driver for NIIMBOT thermal printers: local-first, no account, no cloud, prints over USB or Bluetooth. Cross-platform on .NET 10 and Avalonia, with the reverse-engineered printer protocol pulled out into its own reusable GPL library.

Thermalith: an open-source desktop label designer for NIIMBOT printers

The blog went quiet for a few weeks and the site sat mostly still. This is where I went.

I keep a couple of NIIMBOT thermal label printers on my desk, a B1 and a B4. They're cheap, they're genuinely useful, and the only way the manufacturer wants you to drive them is a mobile app that wants an account, talks to a cloud, and treats the desktop as an afterthought. I wanted to print a shipping label from the machine I actually work on, offline, without signing in to anything. I also bounce between Windows, macOS, and Linux depending on the day, so running cleanly on all three was a hard requirement from the start rather than a stretch goal to bolt on later. That itch is Thermalith.

Thermalith is a desktop label designer and print driver for NIIMBOT printers. Local-first: no account, nothing leaves the machine, it talks to the printer directly over USB or Bluetooth. It runs on Windows, macOS (Apple Silicon and Intel), and Linux on both x64 and arm64. The licence is GPL-3.0 and the source is on GitHub.

The part that took the longest

NIIMBOT doesn't publish a protocol. So the first real work was capturing the traffic between NIIMBOT's own app and the printer, then decoding it byte by byte to work out what each packet meant: how a print job is framed, how the printer reports status, how the image data for a label is streamed to the print head. That reverse-engineering became Niimbot.Net, a standalone library that handles the protocol and the USB and Bluetooth transport. I pulled it out into its own GPL NuGet package on purpose, so anyone building their own NIIMBOT integration in .NET doesn't have to redo the wire-sniffing I already did. The app is one consumer of that library. You can be another.

I didn't start from a blank page on the protocol. Two open-source projects had already done real reverse-engineering work, and I learned a lot from both: niimprint, the original Python NIIMBOT driver, and niimbluelib, the TypeScript library behind NiimBlue. Niimbot.Net is a fresh .NET implementation rather than a port of either, but having their work to read alongside my own packet captures saved me from a lot of dead ends. Credit where it's due.

On top of that sits the application: .NET 10 and Avalonia for the cross-platform UI, with a SkiaSharp pipeline doing the actual label rendering. What you lay out on screen gets rasterised through Skia to exactly the dot grid the print head expects, which is the only way to get text and barcodes that land crisp at the printer's real resolution instead of fuzzy and resampled.

Printer coverage comes from profiles derived from NIIMBOT's own device catalogue, roughly 79 models. Plug in a supported printer and it resolves its real width, DPI, and density automatically instead of making you guess. I've verified the actual print path on the hardware I own, the B1 and the B4, across a pile of different label sizes and stocks including the 104 mm shipping-label width on the B4, on real devices rather than a simulator.

What you get, and what's rough

Distribution is a self-contained single-file binary per platform plus a user manual PDF. No runtime to install, no SDK. Download the one file for your OS and run it.

Now the honest part, the same one I wrote about in the last post on how I build and release. The binaries are not code-signed yet. On Windows, SmartScreen will warn you; on macOS, Gatekeeper will grumble and you'll need to right-click and Open the first time. I'm still sorting out the signing certificates under the EvilGeniusLabs identity. I shipped the thing that prints before the thing that placates the operating system, and I'd rather say so than have you find out at download time.

This is a 1.0. I've tested it hard on the hardware I actually own, the B1 and the B4, and it's solid there. The other 77-odd profiles come from the catalogue and haven't met their real printers yet, so if you're on a model I couldn't get my hands on, consider yourself the test run. Use it, and tell me what's broken.

What's next

D11 support is in progress, and more models will follow as I can verify them on real hardware.

The bigger item on the list is data merge: point Thermalith at a spreadsheet or a table and have it print a label per row, so a batch of shipping labels or asset tags stops being a copy-paste slog. After that, reusable label templates, and a drag-and-drop palette of icons and emoji so you can drop a symbol onto a label without leaving the app.

None of that is in 1.0 yet. It's the direction, and the order will shift based on what people actually ask for.

Try it, break it, tell me

Downloads and source are on GitHub at github.com/EvilGeniusLabs-ca/Thermalith. Grab the build for your platform, print something, and open an issue if it misbehaves.

If you came in from the last two posts: this is the project behind the new projects page, and the release pipeline I described is the one that builds and ships these binaries. Now you know what I was building.