July is pretty boring, holiday-wise, but—from a celebration of Apollo to Apollo 11—landing a human on the Moon without killing him is pretty impressive. That’s fifty-one years ago, today.

Buzz Aldrin

Plus, I managed to get a few things accomplished.


I’ve started moving (and retesting) code out of the main application file. There’s a point of diminishing returns, though, so I may not bother to trim this down to the recommended three hundred lines, just because of the hoops I’d need to jump through to get it all working. It’s a worthwhile exercise, though, since I noticed that the paging code doesn’t set a maximum number of pages when looking at the general timeline. So, I don’t think I trimmed any lines out of that, but it’s one less bug.

Speaking of finding bugs while taking care of other things, Uxuyu now delays looking for feeds that haven’t been available in a while. The changes turned up a few small bugs, which are now fixed. It uses the following code, in case anybody wants to spot-check my work.

const age = (mostRecent - lastSeen) / 86400000;
let cycle = Math.round(Math.log2(age + 1)) + 1;

if (!Object.prototype.hasOwnProperty.call(workerData.following, h)) {
  cycle *= 5;

if (getAll) {
  cycle = 1;

if (iterations % cycle !== 0) {

Ignoring some error avoidance, we take the difference between the date we most recently found any feed versus the date we last saw this particular feed; taking this difference avoids penalizing someone for not using Uxuyu for a few weeks, which would skew the numbers and fail to update anybody. We then take the log (base-2) of the number of days the feed hasn’t been seen, 86400000 being the number of milliseconds in a day: 24 x 60 x 60 x 1000. That gives us our base number. Feeds we see frequently will have a cycle value of 1, and broken feeds will have a larger cycle number.

If the user is someone we don’t follow, then multiply the cycle by five, because we don’t care about those users as much as we care about the users we do follow, like before. This (ideally) conserves bandwidth, though probably not much. However, if we set the flag to get all users (like when issuing the /peer command), we ignore everything to set cycle back to 1 in order to force the retrieval.

Finally, if the iteration count is a multiple of cycle—which is why 1 is so important, here—continue. Otherwise, skip this user until next time.

For reference, twtxt launched in February 2016, which is over 1600 days ago. So, if your feed hasn’t been seen since then and you have impossibly been using Uxuyu since then, the feed’s default cycle number would be 12. If it’s not a feed you follow, then you would only investigate that feed one out of every sixty sweeps through the network. You may never check it again, sure, but after four and a half years…that feed is probably not coming back.

If I’m not mistaken, this is the last of the features that I wanted in my twtxt client, so I’ll shift direction on the project, soon.

VSCode Rat

I added the configuration code, as described on Wednesday, so that project is basically done. If my project idea comes together for what to do with this continual tracking, I may create a new Visual Studio Code extension to go with it with a more reasonable name. But otherwise, while VSCode Rat certainly has its problems, I got the information I needed from the experiment, and so consider the extension to be a completed project.

Also, I finally updated the README files for VSCode Rat and URL Rat to point to the relevant blog posts, so that visitors can understand the projects’ constraints and realize that neither is for production use.

Entropy Arbitrage

For the blog, I made some minor CSS tweaks to make it possible to represent keyboard shortcuts (such as Ctrl+C) and improve the experience when one post is meant to update an older post.

The “invisible text” has frustrating, too, so I finally got around to researching that. Pages now pre-load the fonts using some variation of this tag.

<link rel="preload" as="font" href="/blog/assets/Exo2-Light.ttf" type="font/ttf" crossorigin="anonymous">

More importantly (as I understand the difference), I’ve added font-display: swap; to each of the @font-face declarations, so that browsers will render the page with default fonts until the custom fonts are loaded. Between the two changes, the reading experience should be significantly less obnoxious, now…assuming that’s now how you describe my writing, I mean.


As I mentioned above, I now consider Uxuyu to be feature-complete, as a project, so I need to give some thought on turning the project into a “product,” for lack of a better term. That is, it should be something I can point a casual user to, without needing to explain the Node.js ecosystem. So, I’ll continue cleaning up around the code. That will include writing coherent documentation and working out whether it’s possible to package the application into something I can offer to a non-technical user. If the packaging works, it’ll be an upcoming tech tip.

While I don’t know if I like the idea, yet, I want to think a little bit about one more feature: Saving posts to the database when reading feeds, too. The big arguments in favor of doing so is that the messages are available when Internet access is spotty, messages don’t disappear when users stop paying their server bills, and groupings like mentions can be populated instantly using cached information. The big argument against is that Uxuyu starts to look more like a surveillance system for twtxt waiting to throw someone’s words back in their face, rather than an easier client. Like I said, I want to think about whether it’s worth doing.

Oh, it also finally occurs to me that the feed URLs should be the key Uxuyu uses to distinguish people, not their handles. Fortunately, that’s not encoded in the database as a key, so it should be an easy change.

In addition, it may not happen this week, but now that I have some experience providing a decent user interface to an offline-first distributed social network, I want to revisit an old, abandoned project of mine, Zoea, meant to be a lightweight desktop client for Scuttlebutt 🦀. I don’t think that Proton Native is a good choice for it—unfortunately, because I really enjoy working in it—but the general philosophy of operating across multiple worker threads seems like a better idea than the slop I threw together last time I worked on the project…

Other than that…I’m not sure, and I guess it depends on the outcomes of some experiments that I probably won’t post, this week.

Credits: The header image is Buzz Aldrin on the Moon, with Neil Armstrong seen in the helmet’s reflection, in the public domain by NASA policy.