Finally, I added some tests and fixed this. After updating the feed metadata, I now just return early and do not attempt to build an SQL multi-value INSERT statement. Easy-peasy.
@lyse@lyse.isobeef.org @movq@www.uninformativ.de @klaxzy@klaxzy.net @david@daiwei.me Iām in a similar boat, they pushed us to use it, then pushed us to keep our usage below a certain threshold (although they do allow certain āpower usersā go beyond the limit, LOL). I dragged my feet at first, but they finally broke my spirit about a month before the limits were put into place. Unfortunately, Iāve been doing more managing than coding lately, so I mostly just use it for creating JIRA tickets (I find it to be very good at producing āAgile artifactsā).
@prologic@twtxt.net This was to be expected and Iām glad that itās finally happening. I seriously hope that AI/LLM output gets swamped with advertisements or unwanted code, so people see what they have gotten themselves into, especially the āvibe codersā.
@david@daiwei.me Hahaha! The thing is, it doesnāt taste as good in summer as in winter for some unknown reason. Two or three decades ago I asked my grandma to bake some of her amazing gingerbread in summer. But she always refused, claiming that this only really works in winter. Of course, I didnāt believe that. Finally, after years of begging and pleading, she finally made a tray. And to my surprise, she was right. It wasnāt bad, no, no, not at all. It was really yummy. But the gingerbread in winter was just better. :-/
Maybe I should give it a shot myself. Perhaps she slightly changed the recipe on purpose. So that I will never break the tradition of seasonal food again. :-P It worked, at least I never asked her to bake gingerbread in summer again. :-D
I finally built a prototype of a marking gauge with a cutter wheel out of some scraps.
https://lyse.isobeef.org/tmp/streichmassprototyp-mit-messerrad/
It had been a long time in coming, I bought some replacement cutting wheels three years ago for exactly that purpose. I also found out that I need more M3 countersink bolts for future marking gauges that I want to make (maybe two or three more). Luckily, I had exactly one. I thought I got way more than that, but M3 is very, very scarce in my collection. My M3 bolt was barely long enough to attach the cutting wheel to the bar. But itās okay for the prototype.
I was pleasantly surprised that I managed to drill the 2.5mm diameter hole almost perfectly in center in the 8mm diameter aluminium round bar. Center finder, drill press and vise with a vertical prism for the win!
I knew upfront that the M5 steel bolt to lock the bar in place definitely needs to be replaced with a brass or aluminium one (maybe with a knurled head). Otherwise, it cuts into the aluminium bar and leaves ugly marks. These burrs might even scratch the workpiece. But, of course, I donāt have any brass on hand either. Alternatively, I swap out the aluminium bar for a steel or even stainless steel one. Stainless might be tricky to precisely drill and tap, though.
I already learned a few things by making this prototype. The final wooden fence can be even a bit bigger. This round thing behind is also too short, Iād like it to be a tad longer and thicker. The final one will be made from hardwood, not spruce. Other than that, itās great and already more practical than my store-bought marking gauge with its round fence. This only causes the tool to roll around on the workbench. Or even roll off. Stupid design.
jenny stuff aside, I received zero bug reports or code contributions since leaving GitHub in 2018.
@movq@www.uninformativ.de Finally, your software is just perfect and finished by now, no need to report non-existing bugs or send in code changes. :-) How many tickets and merge requests did you get before moving to your own server?
I have to admit that I use git format-patch so rarely, I always have to pull it up from my shell history. Havenāt used git send-email even once. I definitely have to look into that soon. Wanted to do that for several years. I typically upload the patch to my server and send a link via IRC.
Maybe I was just very unlucky, but my experience is that you can perfectly ignore people and their work who only do it for the āfameā. Itās almost always been from inferior quality to say the least.
@movq@www.uninformativ.de Luckily, Iām not an autist. If you walk next to a busy road or airport, I totally get the annoying noises. Iād plug my ears, too. But I meant in the woods where there are almost only nature sounds. Maybe they miss the jackhammers etc. :-D
@david@daiwei.me Hell yeah, letās finally reintroduce the big predators! :-D
After many months of hard⢠work, Iāve finally been able to get Mu (µ) lang to a point where the duplication of machine code / assembly between the ARM64/AMD64 and Mach-O and ELF formats are not all eliminated. This now means that writing a new backend target os/arch for Mu is now relatively simple to do, or far less duplicated work/effort.
Hurray! Finally, the thunderstorm is right over us. The last days we always got skipped. The rain smells so great. :-)
@david@daiwei.me Ha, I just noticed that I changed Newsboatās defaults. Right from the factory, new items are just bold, while read ones arenāt. No different colors, white on black. Focused items are bold yellow on blue. No matter the read status. I think thatās why I started to play with the config to differentiate them. Itās been so long ago that I didnāt know anymore I even messed with that.
And yes, youāre right, the red on black is borderline readable. Also, my white on green focus is rather silly. But Iām sooo used to it, I donāt realize how bad the contrast is. To be fair, I donāt spend a lot of time in the lists. Aha, there are new articles, Enter to hit the artice view, read it, press n to immediately jump to the next unread article, rince and repeat, finally Iām back in the article list view.
Default theme, read focused:

Default theme, unread focused:

Lyseās schlimmbesserung, read focused:

Lyseās schlimmbesserung, unread focused:

@movq@www.uninformativ.de Iām with @prologic@twtxt.net on this one⦠I spent nearly a decade as an āenterpriseā Java developer (servlets and JSPs and Spring, oh my!) before I finally swore it off, and Iāve been Ora-clean ever since (8 years and counting).
I wonāt go back.
š„³ Finally! After nearly 4 years, yarnd v0.16.0 āSilver Sojournerā is out! š Twt Hash v2, SQLite FTS5 search, HTMX-powered UI, first-time setup wizard and literally hundreds of bug fixes š
Release notes: https://git.mills.io/yarnsocial/yarn/releases/tag/0.16.0
Upgrading is fully automatic ā the Twt Hash v2 migration re-fetches all feeds on first start, so expect the first cycle to be a bit heavier. Images on Docker Hub as prologic/yarnd:0.16.0 š
cc @kat@yarn.girlonthemoon.xyz @abucci@anthony.buc.ci @shinyoukai@yume.laidback.moe @eldersnake@we.loveprivacy.club š
@prologic@twtxt.net Well, 15 shows the site. On the left, I had a roll mat on a tarp. I borrowed some āNVA tarpsā from the scouts for this trip. The scouts got them from the National Peopleās Army, the German Democratic Republicās armed forces after Germany was reunited. Theyāre 1.75m x 1.75m in size and weigh 1.3kg, quite heavy, but super awesome. One tarp on the bottom, another one to cover up the clothes, shoes and sleeping bag in order to protect against the thaw. Finally, a mosquito net over all that, hung from a rope between two trees.
My mate just used a hammock with a mozzie net on the right hand side. The third tarp served as the luxurious bedside carpet. :-)
We sat on my second tarp to chill and enjoy the sunset and surroundings. It was nice to notice birds etc. die down. It took a really long time for the last light to fade away. Since we have a very high risk of forest fires, we of course couldnāt have a camp fire. But after all the exhaustion, I didnāt even miss it for one second.
Since we had dinner at home before leaving, all we brought were two lye rolls, two grain rolls, two brezels, some sausage and chocolate biscuits for breakfast. From the 2.5l of water, I ended up using 2l. Itās always good to have a little extra, despite the unnecessary weight. We had brekkie a few kilometers further on a bench in the shade. The first bench was already in direct sun.
Our camp site was maybe 30m to the side and a few meters down of a summit path hidden behind some trees and bushes. We were quite lucky, the other side of the hill got quite a bit of a breeze at night. We could hear the leaved treetops making much more noise behind us.
@movq@www.uninformativ.de Yes, these kind of dogs should really be strictly forbidden!
Itās not illegal if you own the forest or ask the owner. :-)
@david@daiwei.me Yeah, no clue. But my mate said the dog is disqualified from such adventures in the future. :-)
The temps were supposed to hit 14°C just before sunrise. Since we didnāt bring a thermometer, I canāt tell for sure. I was rather hot in my sleeping bag, so I had to pull out my arms every now and then. My mateās sleeping bag was a little lighter and, unfortunately, the zipper jammed up. Since it didnāt close all the way, it felt quite a bit cold I was told in the morning. When we got up at 6ish (we said, we donāt care about time at all), it was probably already 16°C if not more. I brought a jumper, but a t-shirt was already nice enough to wear. The jumper just served as my pillow. The mercury raised by the minute then.
Yeah, I circled the spot with a biro to keep an eye on it. Until now, thereās absolutely nothing to see. Looks like I got lucky.
@balloonfu-sen@yarn.girlonthemoon.xyz many reasons, all of which make sense. Same reason why automobiles today do not have an inner tube either. Now, about bicycles:
Tubeless bicycle tires drastically reduce punctures because internal liquid sealant instantly plugs small holes while you ride. Eliminating the inner tube also removes the risk of āpinch flats,ā allowing you to safely run much lower tire pressures. This lower pressure provides superior traction and a noticeably smoother ride on rough surfaces. Finally, without an inner tube rubbing against the tire casing, rolling resistance drops, making your pedaling more efficient.
Bottom line, smoother ride, better traction, less flats.
Perhaps unsurprisingly, last nightās Magic games were dominated by the new Marvel set.
In game 1, I was running my new (unlisted) 5-color tribal Super Heroes deck (led by Nick Fury, Agent of SHIELD) against a lightly-modified Avengers Assemble deck, a tribal Super Villains deck (fronted by Thanos, the Mad Titan), and 2 āclassicā magic decks (Fractals and Artifacts). The heroes held their own quite well, but that game went way too long (thanks to Thanos snapping away half the board every other turn). It finally ended when everyone quit after yet another board wipe (giving the wiper her first win).
I slept for over 10 hours last night and today. Finally caught up for the many nights going to bed at 02:00, and waking up at 05:00.
What a week!
It looks like I mostly missed the #twtxthashgeddon (so happy belated twtxthashgeddon day, to those who celebrate), although Iām glad that twtxt-lib appears to have come through it more-or-less unscathed.
Also, today is (was) July 4th, so happy US Independence Day (to those that celebrate). I didnāt feel much like celebrating, myself, so instead I went and played Magic (results tomorrow).
Finally, today is (now) July 5th, so happy X-Day (to those that celebrate). I canāt help but feel like this would be a great time for the saucers to comeā¦. Just sayinā. š½
BTW - welcome to twtxt @GabesArcade@gabesarcade.com!
Finally done with the Van! Ready to roll out tomorrow morning š
box (command-line container runtime). It works great š
@movq@www.uninformativ.de CEF turns out to be pretty easy. I had to write a bit of C and Go to bridge, but once that got going I was able to write it into my pure Go go-wayland wlui library for final rendering. The delegating the entire CEF part was a good idea though because it keeps all the complexity in a container Image, leaving me with just the Go + C stubs/interface and SHM/IPC parts.
I complain about this a lot:
https://movq.de/v/e7cb49eefb/hiccupfx
But to be honest, my blog did the same thing ā to some degree.
This is fixed now. The trick is to add width and height to all <img> tags. That way, modern browsers know how much space to reserve for the image. Without this, they just reserve zero space, so when the image finally loads, you get jumpy layout.
This effect is even worse when you use <img loading="lazy"> ā which I can finally use, now that the jumpy layout has been fixed. š„³
Finally finished another meme one, I always wanted. It took forever, to get it right, so I really hope people get the reference.

Iām just lacking that bit of quality in the final third.
Oh finally, we survived to Friday.. so ready for the weekend to start..
From Missing the Playoffs to the NBA Finals ?~L~X https://thenewleafjournal.com/b/E3N
Oh god, finally: The thumbnail generator for my blog now renders a typical āplayā icon for videos.

Saves me the need to write āthis is a videoā every time. š¬
@movq@www.uninformativ.de Yes. The author tries hard not to break existing code, but apparently he did this time. In his defense, itās not an official release, I just updated to master. Which is exactly what I always did in the past as there are no real versions (I even think that in one ticket he wrote years ago that master is always stable). That has finally changed a year ago, though: https://github.com/rivo/tview/releases/tag/v0.42.0
@prologic@twtxt.net Awesome work!
Iāve been thinking about learning Go for a while, maybe this will be the thing that finally gets me to do it.
Every now and then, I think that I have carefully proof-read my message enough times and hit the āAdd messageā button in tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up ttās cache. This is rather tidious:
- Recall the
sqlitebrowser ~/.local/share/twtxt/tt2.sqlitefrom my shell history.
- Switch to the āBrowse dataā tab.
- Go to the
messagestable and wait a second or two until itās loaded.
- Sort by the
created_atcolumn twice, so that I get descending order.
- Select the first message, which is typically the one in question.
- Find the āRemove currently selected rowā button in the tool bar.
- Commit the changes.
- Close sqlitebrowser.
So, I finally implemented the removal of messages from the cache in tt. I can now hit d and confirm the removal. Bam! Should have done that ages ago!

Next up is the search, I think.
I went to check on the fireflies this season. But I didnāt see any. Instead lots of moths. At first, I thought it might have been still too light, but it was already dark enough for me to miss and destroy a snail shell. Bummer. Maybe it was too wet tonight. Although, itās probably just another or two weeks until my glowing friends will finally show up.
In the beginning, I passed two beautiful deer on the edge of the forest. They were just ten meters away, but didnāt run off, really cool. :-) I kept on walking. Before I eventually left the woodland, a frog or toad crossed my path. It was very dark by then, though, so all I could see was a black blob.
Back in town, the street lamps on the first third were all turned off for some reason. I was already glad that I will reach home without getting blinded this time, but unfortunately, the other lamps were all operational.
For this weekās (slightly late) #caturday, Iād like to introduce our 4th and final feline resident, the old boy we call Bugsy. Heās been with us for 8 years, and we think heās 13-14 years old (but heās not saying).
He used to sound a bit like a cartoon gangster (hence the name), but as the years have passed, he started to sound more like late-stage William Hickey (Uncle Lewis from Christmas Vacation).
Heās our sweet little old man, and he is loved.

NBA Finals Appearance Droughts ?~L~X https://thenewleafjournal.com/b/E2e
Years ago, I used Kate, no, not somebodyās wife, but the KDE Advanced Text Editor, to export source code files and fragments into HTML with syntax highlighting. I think thatās where I got the initial <b> idea from. There were also bucketloads of <span style='color:#644a9b;'> all over the place, even inside <b>. No CSS classes defined upfront, all colors inlined. The final rendering in the browser looked great, but the source code ugly as hell in my opinion. However, Iām thankful for hinting me at <b>. I think this kicked off everything. :-)
@movq@www.uninformativ.de Itās the āLyse types the entire HTML by handā generator. Yes, no kidding. I write articles so rarely, that I can do that once in a while. Itās fun to some degree, but also not.
After some time, I finally recorded some Vim macros to insert <b>ā¦</b>, <var>ā¦</var>, <span class=s>ā¦</span> etc. around the tokens. This helped a little bit. But I was still questioning my mental state doing it like that. I also had to fix a bunch of the end tags by hand, because the word movement wasnāt enough or the end movement went too far. Quite the annoying process for sure.
But I think the HTML looks a wee bit nicer and is maybe even semantically a little bit better than having only <span>s everywhere. I find the <span class="whatever"> just soo awfully long. Of course, I never look at the code again, but knowing, that e.g. there is a <b> and it saves so many bytes in comparison, makes me happy. It is a more elegant solution in my opinion. Not by much, but better nonetheless. Itās a matter of simplicity. Admittedly, even I canāt avoid the <span>s alltogether. Oh well. On the other hand, Iām sure that this does not make any difference whatsoever. I bet, nobody and nothing, like a screenreader, analyzes the HTML for that, where this would be truly useful.
Oh! Maybe text browsers, though. It just occurred to me while composing this reply. :-) Haha, I lost my bet quickly. w3m picks up at least the <b> for keywords and builtin types, <u> for filenames and <i> for comments. Yey. No different styles for <var> and <mark>, unfortunately. elinks only renders the bold. Itās cool that I had the right intuition right from the beginning, despite being unable to pinpoint it. :-)
All the <span> hell with common syntax highlighters is a downer for me that keeps me from looking more into them. If I wrote more articles, I might rig something up with Pygments. At least thatās somehow positively connotated in my brain. Not sure if it actually deserves it, but I dealt with that in some loose form (canāt even remember) years and years ago. Apparently, it wasnāt too terrible.
To prepare the table of contents, I used grep and sed with some manual intervention in the end. The entire process can be improved. Absolutely.
You wrote your own site generator, didnāt you?
Yay finally fixed some of those annoying āMark as Readā behaviours/bugs š
@movq@www.uninformativ.de Iām very curiousā¦
What I like about this whole computer stuff is that you can explore how
things work. You can dig through problems and solve them. Nothing is
more satisfying than finally understanding something after you scratched
your head for some hours.
Surely you could do the same with AI? Tinker with how it works, study it, understand it, build your own and realize what it really is (without all the big tech hype)?
Of course, @movq@www.uninformativ.de! Most of my points are also included in your list.
First of all, programming is what I really do enjoy the most. So, it doesnāt make any sense at all to not do this anymore. āBut you could use your now free time to do something much cooler and more valuable!ā, others might reply. Fuck no, I donāt want to waste my time with other shit that doesnāt fulfill me, why on earth would I want to do that?
All this hallucination reduces quality badly. In my experience, itās also happening much more rapidly than I expected. Even though developers are still supposed to own and understand whatever has been generated under their name and even be responsible for that, the sad reality is that teammates often blindly trust the AI output. āBut I asked the AI and it told me that $this was impossibleā, āIāve no idea either, but the AI just generated itā are responses I get more often. What really makes my angry is when I point out a flaw and suggest an alternative and this is the reaction. It happened several times that just trying it out and seeing it clearly work to proof my point only took me half a minute, but people still did something handwavy else instead.
The learning effect is drastically reduced. The more time I spend on a topic, the better the odds that whatever I learned actually makes it over into long-term memory. Itās like if a collegue just says ādo it like thatā or āthis solves your problemā, but neither explains the why or how. Somehow, people are still convinced that itās a completely different story when you replace the human counterpart with a computer program in this equation.
Skills are unlearned. Itās like with automation in general, just much worse. You end up in a state where youāve no clue how anything works under the hood or how to actually find out important information that are needed to solve your problem. Youāre screwed when a process breaks out of the blue. Even though it can become also rather terrible, with classical automation youāre typically still be able to decipher how exactly the thing was supposed to do something.
The energy consumption is sooo high, I absolutely do not want to be a part in burning down our planet. Iām sure I find (and probably have long found without knowing) other ways to contribute to worsen our climate crisis.
The scraper part is already covered in detail in your list. :-)
Iām convinced that license and copyright violations are only played down or even refused entirely because companies want to make big money quickly. With the work of others of course. Their double standards are obvious, they still try to actively keep their own stuff secret and out of any training sets. At most for internal use only. Virtually noone in charge is interested in good long-term solutions. Short-term for the win, when disaster eventually strikes, the causers are long gone, the responsibilities in other hands.
Vendor lock-in is something that lots of folks are only realizing very slowly. Itās completely crazy to me. This drug dealer routine should be well-known by now. Itās fucking everywhere. Yet, people are always surprised when they found themselves caught in it.
Adding new AI stuff only increases complexity. But complexity is the enemy that everybody should fear and reduce as much as possible. Of course, this is not limited to AI at all. And everywhere I look around, people in charge looooove to make things way more complicated than they ever need to be. Yet, simplicity is the real art and much harder to achieve.
I donāt understand why we have to go back full force to the ambiguity of natural languages. This alone should be more than enough to realize what a stupid idea all that is. Linked to that is that the āinstruction setā is interpreted differently with newer model versions. I mean, is has to be. Why else would somebody want to upgrade in the first place than to get more Powerful⢠Featuresā¢?
Some people argue that with AI the democratization is empowered. However, in my view, the exact opposite is the case. Models are getting so large that you can basically not run them locally or even train them. So, you have to rely on whatever the vendor offers you and runs for you. In the end, this only gives the owners more power, the multi billionaires. Not exactly what I understand by democratization.
Finally, technology assessments are missing completely. Or they are faked such that mostly only the (questionable) benefits are listed. But all the negative impact is just ignored.
Letās keep some popcorn around for when this all explodes. :-)
Print to Shift+Print a long time ago to launch import and upload the screenshot to my server. I was constantly hitting that stupid key on accident when I actually wanted to press [AltGr].
@lyse@lyse.isobeef.org ⦠this reminds me that I should finally write that tutorial on how to make your own X11/Wayland keymaps. That helps a lot in mitigating stupid design issues like these.
@lyse@lyse.isobeef.org movq.de took ages to come up, but it finally did. Weird.
My Gemlog now finally has an Atom feed for Gemini as well as for the web at marcorocco.net/atom.xml.
I left at full sunshine and completely forgot to bring my bicycleās headlamp. The taillight is always on the bike, but the front one gets charged in the house after every trip. Luckily, I found a torch and roll of duct tape in my hiking backpack. It finally paid off that I always carry all this silly gear around.
A few weeks ago, I actually thought about removing the torch, because itās been a hot minute when I last used it. Fortunately, I did not. :-)
@klaxzy@klaxzy.net I should cancel Netflix as well. Back when they started their streaming service, it was a revelation: Finally, I could watch interesting shows in English, without having to wait for years, and legally (I like to be a paying customer, if itās good). But this is long over. The interesting shows are gone or, once again, I have to wait for years until theyāre available on Netflix. So, why bother anymore? š¤·āāļø
Just a couple of shots from our trip to Bald Rockāfinally got reception so I can share them!

@movq@www.uninformativ.de Yeah. Unfortunately. :-( I tried to bring up the subject of dependency upgrade reviews a few times, but nobody else cared. We finally experienced a supply chain attack (luckily, didnāt turn out too horrible for us, could have been worse) and this got the discussion slowly rolling again. So, publication of this article is perfect timing. Letās see. Admittedly, I donāt have high hopes. And I bet someone suggests to use AI agentsā¦
Thank you, @bender@twtxt.net!
My mate and I took advantage of the public holiday and went on a hike. At first, the 14°C and only slight wind werenāt all that terrible, especially since there were only a few clouds. Later, the sun got covered more and more and also the wind picked up. I was really glad that I brought my jacket along. In the beginning I was contemplating about leaving it at home, but then still wore it and stripped it a few minutes into the trip. It was very windy at the summit, so for our second lunch break wearing it was an absolute must. It was a very beautiful trip and I enjoyed my mateās company.
Finally, Azabache showed up, too. I didnāt bother videoing with all the wind. Didnāt feel like fixing the audio. Maybe tomorrow.
Finally finished The Long Way, by Bernard Moitessier. Itās good, but his first two are better ā ā ā š
I thought that YouTube finally destroyed all the feeds, because I didnāt get any new entries in my newsreader for days. Now I realized that Newsboat somehow just froze. No idea what happened. This is the very first time ever in all those years. Havenāt updated the version for literally years. I reckon I will compile the upcoming version then. This will require a new Rust toolchain, thatās going to be great fun, Iām sure. Already looking forward to thatā¦
Welp, finally dug out after the snow. Iām officially ready to spring
sqlparse is also unsuitable for me: https://github.com/andialbrecht/sqlparse/issues/688
Iām supporting incremental SQLite schema changes to just upgrade from an older database version to whatever the current software version supports. In the past, I already noticed that this is quite expensive in unit tests when each test case runs through the entire schema patches and applies them one by one.
To speed up test execution I now decided that I finally go through the troubles of maintaining both a set of incremental patches and a full schema setup in one go. A unit test verifies that both ways end up with the same structure. This gives me a set of SQLs to check the structures:
SELECT type, name, tbl_name, sql
FROM sqlite_schema
ORDER BY type, name, tbl_name
Unfortunately, the resulting CREATE TABLE SQL queries are formatted differently, depending on whether the full schema was set up in one big step or the structure had been modified with ALTER TABLE. Mainly, added columns are not on their own lines but appended in one physical line. Thatās why I wanted an SQL formatting tool. Since I didnāt find one that works decently, Iām now doing some simple string manipulation. Joining consecutive whitespace into a single space character, removing spaces before commas and closing parentheses and spaces after opening parentheses. This works surpringly good enough. Of course, if it fails, the ādiffā is absolutely horrendous.
Now for the cool part, my test execution dropped from around 5:05 minutes to just 1:32 minutes! I call that a win.
I just stumbled across PRAGMA table_info('tablename') https://sqlite.org/pragma.html#pragma_table_info, PRAGMA foreign_key_list('tablename') and friends. I guess, I have to play with that, now. Itās probably much better to use than the SQL text approach.
@rdlmda@rdlmda.me In case youāre into terminal clients, you might like tt. We finally managed to abolished our GitLab instance, so I would need to make the code available to the public differently.
Letās finalize https://git.mills.io/yarnsocial/twtxt.dev/pulls/28/.