By default, the OTWArchive codebase blocks all imports from AO3, a problem for every fork. My fix includes removing AO3 from PERMITTED_HOSTS, writing a custom Ruby story parser that extracts only the story content from AO3 work pages, and extending the same parser to support imports from other OTWA-based archives!
The append-only index format that saved RubyGems.org, inspired Cargo's sparse index, and could speed up npm and PyPI too.
Go's module system accidentally created a universal, content-addressed, transparency-logged package CDN. You could abuse this for any language.
A Jekyll plugin that adds a stats command to show word counts, reading time, posting frequency, and tag distributions.
Ruby implementations of PURL, VERS, SBOM, SWHID, and SARIF specs.
Since June 2023, I’ve been running a service written in Ruby (Sinatra) that provides several Bluesky custom feeds (initially built with a feed for the iOS/Mac developers community in mind, later expanded to many other feeds). If you don’t know much about Bluesky feeds, you make them by basically running a server which somehow collects and picks existing posts from Bluesky using some kind of algorithm (chronological or by popularity, based on keyword matching, personal likes, whatever you want), and then exposes a specific API endpoint. The Bluesky AppView (API server) then calls your service passing some request parameters, and your service responds with a list of URIs of posts (which the API server then turns into full post JSON and returns to the client app). This lets you share such feed with anyone on the platform, so they can add it to their app and use it like any built-in feed. (If you’re interested, check out my example feed service project.) In order to provide such service, in practice you need to connect to the Bluesky “firehose” streaming API which sends you all posts made by anyone on the network, and then save either those which are needed for your algorithm, or save all of them and filter later. I chose the latter, since that lets me retry the matching at any time after I modify the keyword lists and see what would be added after that change (and also some of the feeds I now run require having all posts). I also use the same database/service to generate e.g. the total daily/weekly stats here. All posts made on Bluesky is much less than all posts on Twitter, of course, but it’s still a lot of posts. At the moment (October 2025), there are around 3.5M posts made on average every day; at the last “all time high” in November 2024, it was around 7.5M per day. A post is up to 300 characters of (Unicode) text, but since I also store the other metadata that’s in the record JSON, like timestamp, reply/quote references, embeds like images and link cards, language tags etc., it adds up to a bit less than 1 KB of storage per post on average. In addition to that, the firehose stream (if you use the original CBOR stream from a relay, not Jetstream, which is a JSON-serving proxy) includes a lot of overhead data that you don’t need in a service like that, plus all the other types of events like handle changes, likes, follows, blocks, reposts, and so on. The total input traffic is around 15 Mbit/s average right now in October 2025 (or around 5 TB per month), and it used to be around twice that for a moment last year. (Jetstream sends around an order of magnitude less, especially if you ask it to send filtered data, e.g. only the posts.) On disk, the millions of posts per day add up to a few gigabytes per day. Since I was running this on a VPS with a 256 GB disk (Netcup, RS 1000 – reflink), I have a cron job set up to regularly prune all older posts and keep only e.g. last 40 days worth of them (since I don’t really need to keep the older posts …
A conference can be so much more than just its talks. These were my experiences at Friendly.rb, as a once-skeptic.
An annoyance I came across when running tests in my app, leading to poor visibility.
Robby Russell shares the origin story of Oh My ZSH and how Planet Argon evolved alongside the terminal customization revolution he sparked.
I’ve been still pretty busy with various Bluesky- and social-related projects recently, so here’s a small update on what I’ve been working on since my November post, if you’re interested: Skythread – quote & hashtag search I was missing one useful feature that’s still not available on Bluesky: being able to see the number of quote posts a post has received and looking up the list of those quote posts. The Bluesky AppView doesn’t currently collect and expose this info, so it’s not a simple matter of calling the API. But since everything’s open, anyone can build a service that does this, they just need to collect the data themselves. Since I’m already recording all recent posts in a database for the purposes of feeds and other tools, I figured I could just add an indexed quote_id column and set it to reference the source post on all incoming posts that are quotes, and later look up the quotes using that field. Skythread, my thread reading tool, seemed like a good place to add a UI for this. When you look up a thread there, it now makes a call to a private endpoint on my server which returns the number of quotes of the root post, and if there are any, it shows an appropriate link below the post. The link leads you to another page that lists the quotes in a reverse-chronological order, like this (it doesn’t currently do pagination though). You can open that page directly by appending the bsky.app URL of a post after the quotes= parameter here: https://blue.mackuba.eu/skythread/?quotes=. In the same way, I also indexed posts including hashtags, since hashtags were being written into post records since the autumn, but it wasn’t possible to search for them in the app. However, this has now been added to the Bluesky app and search service, so you don’t need to use Skythread for that. I hope that the quote search also won’t be needed for much longer :) Handles directory One very cool feature of Bluesky is that you can verify the authenticity of your account by yourself, by proving that you own the domain name that you’ve used as your handle. So for official accounts like The New York Times, The Washington Post, or Alexandria Ocasio-Cortez, it’s enough if they just set their handle to their main website domain (or a subdomain of house.gov in AOC’s case) to prove they’re legit – they don’t need to apply anywhere to get a blue or gold tick on their profile. I was thinking one day that it would be nice to see how many e.g. .gov handles there are and notice easily when new ones show up. So I grabbed a list of all custom handes from the plc.directory and started recording new and updated ones from the firehose. In the end, I decided to build a whole catalog of all custom handles, grouped by TLD, and show which TLDs are the most popular. At first I only included the “traditional” main TLDs and country domains, but a lot of people liked it and I got a lot of requests to also include domains like .art, .blue, .xyz and so on, so in the next update I’ve add…
DHH discusses the genesis of Ruby on Rails, the philosophy behind beautiful code, and his vision for the future of web development at 37signals.
I had different plans for this year… then, Elon Musk happened. Elon took over Twitter in October last year, which set many different processes in motion. A lot of people I liked and followed started leaving the platform. Mastodon and the broader Fediverse, which has been slowly growing for many years but never got anything close to being mainstream, suddenly blew up with activity. A lot of those people I was following ended up there. Then, Twitter started getting progressively worse under the new management. Elon’s antics, the whole blue checks / verification clusterfuck, killing off third party apps and effectively shutting down the API, locking the site behind a login wall, finally renaming the app and changing the logo – each step made some of the users lose interest in the platform, making it gradually less interesting and harder to use. Changes, so many changes… and things changing meant that I had to change my workflows, change some plans, build a whole bunch of new tools, change plans a few times again, and so on. My GitHub looks like this right now, which is way above the average of previous years: As usual, I ended up writing way more Ruby and JavaScript than Swift, which goes a bit against my general career plans – but I’ve built so much stuff this year and I had a ton of fun doing it. So in this blog post, I wanted to share some of the things I’ve been working on lately. The Dead Bird Site 🦤 I had a bunch of private tools written for the Twitter API. For example, I had a script that downloaded all tweets from my timeline and some lists to a local database. I was also running various statistics on tweets, e.g. which people contribute how much to the timeline and list feeds, and automatically extracted links from tweets from some selected lists. And then Elon shut off access to the API (unless you can afford $100 per month for a “hobbyist” plan), which meant I had to try to find other ways to get that data. I quickly got the idea that I could somehow intercept the JSON responses that the Twitter webapp (I refuse to call it the new name, sue me) is loading from the JavaScript code. The JSON responses are very complicated with a lot of extra content, but they do contain everything I need. The problem is how to get them; I wanted to get data from my personal timelines, so I couldn’t do anonymous requests, and I didn’t want to make authenticated requests for my account from some hacked-together scripts, for fear of triggering some bot detection tripwire that would lock my account. So the approach I settled on was to passively collect the requests in the browser, using Safari’s Web Inspector, and export them to a HAR file that can be parsed and processed like the data from the public API. (It would be even better to have a browser extension that intercepts XHR calls on twitter.com automatically, but as far I can tell, there is no way for request monitoring extensions to look at the content of responses, unless you inject scripts to …
A comprehensive guide to working with Docker in Rubymine, with troubleshooting for common problems.
Parsing lots of Excel sheets and worried about memory usage or CPU time? These benchmarks may offer a better way.
I was recently working on adding some Twitch embedding support to dev.to! Part of this was adding we
Octobox helps you manage your GitHub notifications in the same way Gmail helps you with email, it's now available on the GitHub Marketplace.
Different approaches to testing APIs in Ruby with RSpec. Code and opinions on which works best.
A little while back I got a blink(1) , which is a cool little USB light that is fully programable.
I am super excited to introduce a new gem I've been working on called Sleet ! It's still very much
Hey, thanks for checking out my blog! Got it all set up, so decided my first post should be a making
Improving web typography by preventing orphans and controlling line breaks with custom Redcarpet renderer
Building a visual bookmarks display using the Readability API, Ruby, and CSS 3D transforms
Switching from RVM to rbenv for simpler Ruby version and gem management
Transitioning from designer to Ruby developer and building a custom Sinatra-based website
I spend most of my days at work on powerful IDEs like Eclipse or Netbeans, tools so advanced in functionalities that their feature lists span over several pages. Their power, however, has its own draw...