Brutaldon logo: a gray, angular Mastodon elephant logo

So, it appears that I’ve (accidentally?) written a Mastodon client! It’s been public for long enough that I probably ought to write about it.

Brutaldon is a brutalist (mostly) web client for Mastodon and Pleroma. You can use it to connect to most instances from almost any web browser — I commonly use it from Lynx and w3m, as well as my day-to-day Firefox, and I’ve seen others use it on retro browsers on 1990s and early 2000s hardware. But it’s not exclusively a retrocomputing experience. I’ve tried to use it as a platform for showing that Progressive Enhancement and a document-centric focus are still viable approaches to web development in 2018. In fact, I feel that, along with decentralized non-commercial social media, they are a counterbalance to the trends that have made the web such a garbage fire in the late 2010s, which is probably the biggest reason I started writing brutaldon.

Using brutaldon

You can use brutaldon in any of three ways: you can use the hosted site, you can self-host, or you can run a copy locally on the same machine as your browser. Once your browser is talking to it one of those ways, you sign in to your instance securely, and enjoy the raw web experience. Brutaldon supports almost all Mastodon features (read home, local, and federated timelines, read threads, search, favorite and boost posts, follow, block, or mute users, and search), except for lists and editing your profile.

In text-mode browsers, media such as photos and videos are presented as links, usually with the image description as the link text. In a graphical browser, everything should be pretty much as you expect: it’s a one-column interface with separate pages for the different timelines, and a static navigation bar on the top. It works well on mobile, too.

Technical details

The main thing about brutaldon is that it is a plain server-side web application. The only things it really requires of the client are support for HTML forms and cookies. That’s why it works well in retro browsers — those requirements were introduced very early in browser history. (There are some other practical requirements, for which see “Caveats” below.) Everything on top of that is layered on, but works in browsers that ignore it. In particular, there is no requirement that JavaScript be present or working.

The brutaldon server is written in Python, using the Django framework, and it is very simple. It speaks the Mastodon API thanks to The brutaldon source is currently on github, at least until I set up alternative source hosting.

Progressive enhancement

Almost all of the themes use CSS for styling, as you’d expect, but some of them use it either very sparingly, or to intentionally produce retro styles. The most distinctive is “FULLBRUTALISM”, which tries to emulate the experience of using brutaldon in Netscape 3 circa 1995. There are also terminal-style themes, and a minimalist large print theme. But the default themes are styled with Bulma, and look basically non-threatening to anyone used to contemporary web design.

There is JavaScript used in brutaldon, only in the Bulma-style themes. It adds keybindings, it animates the hamburger menu on mobile, it adds a lightbox for media, and most importantly, it replaces the two-step confirmation process for boosts and likes with a single click. Brutaldon uses Intercooler.js to enhance common actions. Intercooler is a framework for replacing most JavaScript code in an application with declarative attributes in the HTML, and it is ideally suited for progressive enhancement.

I’m currently working on giving brutaldon very limited offline support and making it a Progressive Web Application — while still working in Lynx.

Caveats for old browsers

There are some limitations on how you can use brutaldon on older browsers. The main one has to do with deployment in a modern environment. In general, modern web servers serve pages only over modern versions of TLS, and retro browsers often only speak old versions of SSL. You can get around that by running brutaldon over just plain HTTP (on an isolated network), and letting just the brutaldon server talk TLS to the Mastodon server. If you do that, you still can’t see media, because they are served over TLS from the origin server. I’ve thought about adding a media proxy mode to help people using retro browsers, but if I do end up implementing it, I won’t have it on the hosted site because of potentially being held responsible for the content of that media.

Some other browsers may run into problems with not sending a Referer [sic] header over TLS, which is required by Django’s CSRF middleware, and also why EWW only works over plain HTTP.



I use brutaldon as my only desktop interface to Mastodon these days, and as my main mobile interface. On mobile I use a native app as a sharing target, and for faster switching between instances.

The “single-column with plenty of white space” layout of brutaldon seems calmer to me than the default Mastodon interface, and I find it easier to concentrate. The lack of infinite scroll also seems calming — it’s easier for me to feel like I’m “done” with my feed when I start seeing things I’ve already seen before, and it takes an actual action to go back another page. I may add something that changes the “older” paging button to “load more” on JavaScript-enabled themes, but I’ll never add infinite scroll.

Other users have told me that the additional effort to favorite or boost a toot (in a non-JavaScript theme) also leads to more thoughtfulness.

One additional feature that I intended, and that I think others have noticed, is that no popularity stats (follower counts, number of boosts, number of favs) are ever shown. I hope people find this restful.


Writing the base functionality was really easy, given how much is done by and Django, and how much of the layout was straightforward with Bulma. Everything that has really had me pulling my hair out has been in the progressive enhancement phase with JavaScript. It is amazingly hard to get everything working and keep it working. It feels like anything that changes breaks something. This is probably my limited JavaScript skills more than anything, but it still reinforces my perception that JavaScript is fragile.


There are about fifty regular users on the hosted site, and who-knows-how-many people using it on their own installation. Why don’t you give it a try?