Desktop HTML on a Diet

by Dan at 5/25/2023

TL;DR: Just launch a Chromium, it's probably already installed.


Recently a friend talked about making an ANSI banner for his shell's MOTD and asked if I knew the best tool. I did not, but I had messed around with automatically converting images to Unicode half blocks and took this as a sign to turn this code into a usable application.

Avoiding Electron

I decided to use sharp, a Node.js-based image manipulation library. Because sharp has not yet been built for WASM, this was also a perfect opportunity to pursue ideas regarding desktop HTML applications without the gigantic Electron, which bundles both Chromium and Node.js with each application.

Instead, I assume two external dependencies: a Chromium-based browser and Node.js. I launch the Chromium with a shell script, passing in these command line switches:


I've recently accepted a position specializing in React so chose it to keep my skills sharp. For the user interface I tried a few newer component frameworks and decided to go with Mantine, which has been very nice to work with. I've picked Zustand and Immer for state management and am building the app with Vite.

fftext 256 colors

fftext allows you to open, paste, or drop local images and convert them to ANSI-escaped Unicode half-block text. It includes a bunch of sliders to tweak the image so it works nicely with the chosen palette. The image above is using the 256-color mode, but you can also pick one of three popular 16-color palettes, or even 24-bit ANSI colors for supported terminals. It will also convert to IRC-escaped in 16 or 99 colors.

fftext 16 colors fftext 24-bit colors

It is currently alpha-quality but most features can be used (Linux-only). Source code is at Github. The resulting build is a 141K download and installs about 20MB of dependencies - still much smaller than an Electron app would be.


I am tinkering on a reusable framework for building cross-platform apps in this way called Calory. A test app, a simple text editor, is a tiny 59K download. Currently the launcher is written in C++ (fun to play with after 20+ years) but I will revert to shell scripts to reduce the resulting package sizes even more. On Windows, both CMD and PowerShell scripts open a terminal window, so I will use VBScript 😆.

Calory will be backend-agnostic, so anything that can communicate with Chrome via the Native Messaging protocol can be used - Node.js, Bun, C++, etc. I've since found a similar project which has the same perk - NeutralinoJS. This uses a WebSocket and web server to achieve the same result. By sticking with Native Messaging in Calory, however, I aim to have the tiniest possible packages.