This is about the Tidbyt, a hardware display device I bought and am using to show some numbers and charts in my apartment as ambient data. I think it’s pretty cool.
I really like alternative display technology. eInk displays, unlit LEDs, like on my AlphaSmart, or flip-disc displays, vane displays, split-flap displays - I wish it was all more widespread. Sure, those flip board displays have mechanical failures more often than traditional screens, but they look and sound so nice.
Most alternative display technology is expensive and inconvenient, especially when compared to the absolute marvel of supply-chain efficiency that is modern traditional LED displays. You can buy a decent 39” TV for a little over $200 today. A 31” eInk panel will run you $1,500, and a flipboard display costs around $3k. The TV I have in my living room is a monument to the problematic but relentless optimization of free markets and mass industrialization: a handmade split-flap display is not.
The Tidbyt is a 64x32 full-color LED matrix display. You can see the individual pixels.
The display itself isn’t super-rare: you can buy two 32x32 LED panels on Sparkfun for $97. But turning those raw displays into something that can show an image will require much more hardware, and then you’ll need to construct an enclosure, deal with a power supply, and enough small tasks to easily occupy a few weeks.
The Tidbyt costs $200 (currently $180). I think it’s a steal for that price: it’s a niche product with real hardware and a walnut enclosure, produced during a pandemic with supply chain issues. The hardware feels solid, everything well-aligned, no rattling when you move it around. The panel on the back is simple and nicely finished, even though nobody will see it.
And yes, it took eight months between my pre-order and arrival, but for an early hardware project that might be better than average.
The setup flow for the Tidbyt is slick. You pair it with the iPhone or Android app, connect it to Wifi, and you’re set. It worked perfectly for me and has had no issues since. You can control it from the iPhone app and choose from a bunch of pre-built applets that will auto-rotate.
So, does it “just work”? In my experience, yes. The pre-built applets are pretty good, too: you’ve got weather, calendar events, subway departures. All of the community apps are managed in a GitHub repo and you can just submit a Pull Request. It seems like the Tidbyt team are actively reviewing and merging new apps often.
The default applets are nice, but I wanted to make something custom. The whole point of this display for me is that it feels quiet, personal, and ambient. I could string together some of the prebuilt applets, but that would make the display switch between graphics. I don’t want a new distraction.
So, I wanted to build an applet: one with all the data combined and composed. That led me to Pixlet, Tidbyt’s development tool. It’s a toolchain written in Go, that executes scripts written in Starlark. I am an expert in neither.
Thankfully, Starlark is very similar to Python, and the modules that pixlet includes (hattip starlib project & Qri) make it relatively smooth to generate some graphics. The whole widget system reminds me of React or Qt, which is really nice - this being a raster system, I expected something more like a Canvas-like API that would require a lot more thinking.
There’s an option in the CLI to test out your applets locally, which works smoothly. Really, this developer experience is pretty nice.
As you can see above, this applet includes: the time, the number of emails in my inbox, the number of tasks on my todo list, a chart of my runs in the last 7 days, and the temperature.
So all that was left was to run this on the device.
Okay, so this part was tough. As it turns out, the Tidbyt doesn’t run the applets you write in Starlark. When you set your Tidbyt to run a community applet, a server is generating the graphics and sending them to you. When you use the CLI tool to run
pixlet push and show your custom applet on the device, it’s just showing an image, generated on your computer. So it won’t update.
The responsibilities of the Tidbyt hardware are thus very narrowly defined: it connects to the network, belongs to a user, and displays some graphics. I get it - and this honestly seems like an okay design decision. This device just works, and probably a large part of that is that its firmware doesn’t have to deal with all the complexity of running and storing applets.
There is an issue lurking here: you are relying on Tidbyt’s servers for this thing to work. The device itself can accept new firmware, so I’m guessing, or hoping, that if the company goes defunct, the community will rally to implement an alternative.
But there were more immediate problems to solve: how was I going to put my own data on this device? I reviewed a few options:
libwebplinking problems, I bailed.
So, the Pi was the solution, partly to assuage the guilt of leaving a fully-functional computer lying unplugged in a drawer for years at a time. I flashed the thing with the newest Raspbian OS, went through the strangely-obtuse processes of setting up SSH & Wifi, compiled pixlet on it, and we were nearly there.
So we end up with something like this - I develop the applet on my computer, push the code to the Raspberry Pi, which renders an image every twenty seconds and pushes that image to the Tidbyt via the Tidbyt servers. It’s a little hacky, but it works well.
There are some notable gotchas around building Tidbyt applets just for yourself.
First, the whole Starlark/pixlet environment is based around a principle of hermetic execution:
Hermetic execution. Execution cannot access the file system, network, system clock. It is safe to execute untrusted code.
I’ve steered clear of microservices, so I did something weirder: I run scripts that modify the Starlark code. Like Python, you can mostly put JSON values directly into Starlark code and they’ll work, so I did something like this:
runs_line = "RUNS = %s" % json.dumps(sparks) star = os.path.join(cwd, "tmcw.star") with open(star) as f: text = f.read() lines = '\n'.join(list(map(lambda line: runs_line if line.startswith( 'RUNS =') else line, text.split('\n')))) with open(star, 'w') as f: f.write(lines)
So, every time the script runs, it includes a new “hardcoded” dataset. Works fine.
There’s also the question of configuration: as you might’ve noticed in the screenshot of the pixlet environment, there’s a configuration system in which you can define inputs for your applets. It’s pretty sophisticated. When those applets are deployed, you can configure them from your phone.
But none of that applies to private applets, so I just hardcoded everything. Here’s what the applet looks like, minus all of the hardcoded parts.
So, in short, the Tidbyt is a beautiful and well-made device that is simple to use with its prebuilt applets.
If you’re like me and want something custom on it, be prepared to do more work. But the yak-shaving hacking required to put custom data on the Tidbyt is nothing compared to starting from scratch: their system vastly simplifies the task.