Sept 14th - Sept 20th 2025

Another week, another set of open source work to do. Earlier in the week was the bulk of my atproto work, then I took it pretty easy after Wednesday focusing on learning some GBA development with rust. Next week might be a bit similar as well, I'm a bit tired and need a little break. But who knows, may get a second wind come Monday and knock out a lot of stuff! But that's the future, let's take a look at what I did this past week.

What days did I work on what?

May only care about certain things. So this is a bit of a guide on which days I talk about what if you wanted to skim to those parts

🧵 Stitch Counter(side quest) - Sunday, Monday, Wednesday, Saturday

❓ Missing Blobs - Monday, Tuesday, Wednesday

😘 Keep it Simple Software(opinion) - Wednesday

📄 pdsadmin Web UI Spec Draft - Thursday

👾 GBA Development(learning) - Thursday, Friday

Sunday, September 14th, 2025

Stitch Counter

I love tangled.sh . It has easily become one of my favorite parts of the atmosphere. Both @icyphox.sh and @oppi.li have done a fantastic job with it and every week bring great new features.

I have been playing around with the idea of creating a tangled.sh trending bot so I decided to give it a try with Stitch Counter .

I created the project from my Rust atrium template . Although I did butchered it some. This is a project I wrote to solve a problem I had, so it's not the cleanest code. Some other fun tidbits.

Uses rocketman as the JetStream listener

Uses constellation 🌌 for counting the stars on a repo

Uses slingshot 🎯 to grab the record for the repo so I don't have to resolve the did doc

chromiumoxide for a headless chrome to render the preview image, which is just the HTML card for trending on the tangled timeline

Currently the way it finds if something is "trending" is if a repo got x stars during y hours it will make a post about it as long as it hasn't in z hours. Which at the time of writing this it's 2 stars within 4 hours. All of those are set via env variables and the stars and when a post was made is kept in a sqlite DB. Expecting to tweak those thresholds, but will probably leave it there for now so it should make a few posts a day.

Pretty happy with how it has turned out so far!

Monday, September 15th, 2025

Stitch Counter

I ran Stitch Counter on my laptop for most of the day and it has been working pretty well! The plan is to eventually put it in a docker container and run from a Raspberry Pi at my house. Just testing right now to make sure thresholds work as expected and no other bugs. I had some concerns since it depended on headless chrome for building those card images in the post. Seems like an awful pretty big dependency to get that. Along with not sure how well it would run as a long term process, error handling, etc.

Was pretty worried about it till @chadtmiller.com had replied to a post and pointed out that thanks to his work with @slices.network he had an endpoint already creating nice open graph images of a tangled.sh repo and said I could use that! I am super appreciative to him for letting me know and allowing me to use that resource. I was happy to drop headless chrome and his preview images do look really nice. Hoping to move Stitch Counter to the rpi sometime this week.

Missing Blobs

We had A LOT of people decide to migrate to a new PDS last week. Because of this a few users were met with rate limiting during the migration process no matter the migration tool they used. Still not sure if it was fully rate limiting, or timeouts on the PDS side, or possibly a PDS was sharing the rate limit across the board (taking a guess here). Either way, we ended up with a sizable chunk of users who were missing some of their blobs all at once. We noticed it once the CDN cache for profile pictures for a few users would expire and they were asking for help a few days after the migration. Very thankful that we just deactivate old accounts on the Bluesky hosted PDS instead of deleting on migrations. Thanks to that it means we can grab the missing blobs from their old repo.

So I started working on missing.pdsmoover.com a tool for users to check if their account is missing blobs, and if so to import them from their previous PDS. It’s a pretty simple tool very similar to pdsmoover.com and pdsmoover.com/turnoff.html . Just a simple alpine.js website to help those users out.

Some tidbits

I found out that you do not have to re activate the previous account to export the blobs like I expected. Being authenticated worked. Was super happy to find that out and not have to do any juggling of activating and deactivating the old account

Logins into your current PDS and checks to see it you are missing blobs

Grabs the previous PDS you were on via the PLC log. Or has an advance button to input the PDS url if you know it, or the tool has trouble finding it

Uses your did as the identifier when logging into your old PDS since we know it from the first login. So just need your old password to login into the old account.

Also we have a new variant of the PDS MOOver cow!

Tuesday, September 16th, 2025

Missing Blobs and counting them

So like most things, the real world is never as nice and neat as your test environment. The PDS has a /xrpc/com.atproto.server.checkAccountStatus endpoint for use during migrations. Two properties are useful for blobs. expectedBlobs for getting how many blobs your account expects you to have, as in how many atproto records have a blobRef. importedBlobs is how many blobs that have been imported(uploaded) to your account. I found during testing that those would always match up pretty well, but in real life not so much. My best guess is that improtedBlobs shows temp uploads that have not cleared yet, so could not always trust that to know if users had missing blobs. Add that along with some of these users migrated over a week ago that count could really be off. Decided to switch to using /xrpc/com.atproto.repo.listMissingBlobs as the official check of if a user is missing blobs or not. I just do a check with a limit of 10, If it returns an empty array the user is good to go.

Keep It Simple Software

You've probably noticed that the pdsmoover.com tools are all pretty simple. Not a lot of moving parts, not always the most user friendly. etc. Well, I thought I would talk about that a bit. It's not complete laziness, although that is a bit of it. It takes a lot of energy to create great software for free, and I'll be the first to tell you that. Not being spiteful, just honest. I am extremely blessed to be able to do that and help others. It brings me a lot of joy to be able to help others out and make a change in the world for the better. Even if it's a small one. But there is a price to the work.

I keep these tools simple with the idea of less moving parts, less logic, and less just general UI moving around means less to break and easier to test. For example pdsmoover.com is just one long form you fill out. Doesn't really hold your hand or do a ton of checks like, is it actually a PDS, is that handle available, selectable domain endings, does it require an invite code, and etc. Instead, it fails and give yous an error if one of those edge cases are met. All of that is accessible, and there are other migration tools out there like atpairport.com and tektite.cc that do a fantastic job of integrating that which ends up providing a much cleaner user experience.

Well why don't I integrate that into PDS MOOver? Well, when I created the tool I took a look around at everything offered and the one tool I used with the most success and everyone recommended was the goat cli. But it wasn't without it's faults (minor and still a goat of a cli tool). 1, a higher level of entry with it being a cli tool. 2, a lot of times the PLC token you entered at the start would be expired by the time it uploaded all your data to the new account. I thought, what if there was a similar tool like goat, but it was more accessible to end users. goat proved that a simple approach would work perfectly for account migrations in the atmosphere.

So I set out to check these boxes for a new tool

Simple logic

Everything to happen client side

Fail early if there's an issue

Some retry logic

Would request a PLC token after the time consuming uploads are done

A pun

And that's how pdsmoover.com came to be! It's not the best tool out there, it's not perfect, but that was never the goal. The goal was to make something that would work the majority of the time for the majority of users. It has caused a bit more work on support, but overall I've been very happy with the result and have seen fewer than expected edge cases of it not working for users.

Wednesday, September 17th, 2025

Missing Blobs

I talked a bit yesterday about the different tactics of deciding how to decide if the user's account was missing blobs. I decided to go all in on the listMissingBlobs endpoint and just hide from the UI the counts everywhere but at the very end of the process. I'm hoping this makes it a bit easier on users and give a clearer "Yes you are missing blobs" or "No you are not missing blobs". Especially at the end. I saw a lot of users getting the try again even tho they had all the blobs, just the imported vs expected was off so it was always saying they should try again.

Login check now calls listMissingBlobs. If array is not empty tells them are missing blobs

Calls a 1,000 limit on the first list call. Uses that count for the "Migrating blobs: x/y" status update. If the user has over 1,000 missing it updates that second count. Was getting the missing count from the expected - imported and was off a lot of the time for users

At the end I did leave the count if they were still missing the blobs. I figured a screenshot from the user would be handy for troubleshooting if we needed to

Stitch Counter Docker Image

Not much to say here other than @stitch.selfhosted.social is now up 24/7 and safely on a raspberry pi in my laundry room and I "unhide" the tangled.org repo. Aka changed the description from "Don't worry about it". Can find the code here .

Thursday, September 18th, 2025

Not a ton of "work" happened today. Mostly just bebopped around.

pdsadmin UI

One of the goals I have for PDS gatekeeper is to host a pdsadmin UI screen that users can sign into via their atproto account and manage the PDS instead of relying on the admin password only. I wrote up a rough draft of my idea of how that would work.

PDS gatekeeper's PDS admin idea

Pardon me if I over explain, but I want to make sure to give a lot of base context for anyone reading this

GBA Development

It's been a minute since I've done any no_std rust and I also recently found out that agbrs has completed their online book on getting started. I figured it was time to check it out again.

About 2 years ago when I first heard about agb their book had about 1 or 2 chapters on building a pong clone on the GBA. I had read through it and somewhat finished it out to learn agb. Can see that attempt here . I have to say it was such an amazing feeling to see the GBA boot screen right before something I wrote.

Since then I've came back to agb with varying success various times, as seen below.

I'm taking it slow coming back. Feels like a lot in the crate has changed, but may just be I haven't looked at the code seriously in a while. I'm working through the new-ish agb book . Then will probably make a smallish game with the goal of completing it fully. I'm thinking a flappy bird clone. Nice and easy to do (famous last words).

Friday, September 19th, 2025

A chill day. Didn't do any open source per say, but I did continue learning more GBA development stuff

GBA Development

Not a ton to say other than I finished up the pong example in the agbrs book. It was a lot of fun! Was a good refresher on everything and got to learn some new things like using Rect for collisions. I can't remember if it was there before or not, but last time I messed around with agbrs I was doing the collisions checks on my own. Was nice to have a helper method for that.

Saturday, September 20th, 2025

Stitch Counter

When I wrote Stitch Counter I didn't really add a ton of error handling (whoops). So due to the minor constellation outage (ty fig for all you do with that). Then finding out it was possible for some images for repos to not be rendered there was an outage for a while for the bot and the bot missed a few new trending posts. If the bot could not find one or the other it would just not send the post. No biggie. Just made those optional and if the bot can't find them then the show goes on without them being added! I also switched to the community maintained JetStream (ty again fig ), while also giving the ability to set a custom one from the env. Can check out that work in this commit .

And that was my week! Not sure what next week holds, not making any plans with the hope to take it a bit easier. But we’ll see! Thanks for reading, see ya next Sunday-ish!