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.

tangled.sh trending's avatar
tangled.sh trending
@stitch.selfhosted.social

haetae.tngl.sh/fanfic-atproto experimenting with making decentralized fanfic archives on atproto. github mirror: https://github.com/haetae-bit/fanfic-atproto ⭐️ 13

An image showing the same text inside of the post. haetae.tngl.sh/fanfic-atproto experimenting with making decentralized fanfic archives on atproto. github mirror: https://github.com/haetae-bit/fanfic-atproto
⭐️ 13
Sep 15, 2025, 10:56 PM
0

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.

Bailey Townsend 🦀's avatar
Bailey Townsend 🦀
@baileytownsend.dev

Re worded some of the status updates for missing.pdsmoover.com Found in real world accounts that expected blobs and imported would not always match up as expected. Was causing some confusion. So now uses listMissingBlobs as the check if any are missing and hide some of the stats counts from the ui

Shows the text "you are currently missing some blobs. login with your old password ot import the missing blobs. we will automatically find your old handle." if you are misisng blobs now instead of a countShows during the migration i am doing 14/1000 (the total may incease as we find more)Shows during the migration i am doing 1008/1778 (the total may increase as we find more). Showing as more missing blobs are loaded it is listed how many t here areA screen showing that not all blobs were imported and needs to be re ran
Sep 17, 2025, 3:47 PM

  • 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.

Bailey Townsend 🦀's avatar
Bailey Townsend 🦀
@baileytownsend.dev

tangled.sh trending is now running 24/7 and running on a raspberry pi!

tangled.sh trending's avatar
tangled.sh trending
@stitch.selfhosted.social
This profile is now fully up!

The current rules are if a repo gets 2 stars within 4 hours this account will post the repo. If it has been posted already it has a 24 hour cool down. Will monitor and see how spam-y that gets, but I figured more was better.
stitch_counter by @baileytownsend.dev

stitch_counter by @baileytownsend.dev

tangled.sh tending bluesky account


https://tangled-search.bigmoves.deno.net/share-repo/at%3A%2F%2Fdid%3Aplc%3Arnpkyqnmsw4ipey6eotbdnnf%2Fsh.tangled.repo%2F3lytmcq7mvm22
Sep 18, 2025, 2:06 AM
0


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
https://leaflet.pub/9daa1fec-b0bf-49ae-951c-88cfb4c19dc9

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.

Bailey Townsend 🦀's avatar
Bailey Townsend 🦀
@baileytownsend.dev

Decided to go be frustrated at something else for a bit. Not a pico, but is still no_std rust. I updated my suika GBA game to the latest agb version. Forgot how buggy the game is. May take another stab at it and just do all the fruit as square to help with physics

Dec 12, 2024, 4:05 AM
0
Bailey Townsend 🦀's avatar
Bailey Townsend 🦀
@baileytownsend.dev

The GBA is hands down my all-time favorite console. I have not written a complete game yet, but here are some pictures and videos of a few I’ve tinkered with. Seeing the GBA start up animation before something I made was like a dream come true. All are written in Rust 🦀 using the agb crate

A split-screen showcasing a game development debugging session. The top section displays Rust code in an IDE with a breakpoint highlighted, while the bottom section shows an emulator running a pixel-art-style game where a cherry drops towards the ground with a green arrow above it. The rustic “Select Menu” UI adds charm to the retro-styled game.A dual-pane development environment featuring Rust code for a Game Boy Advance game. On the left, the IDE displays a code structure defining paddles and entities for a pong-like game. On the right, a browser shows the agb library documentation, and an emulator window displays a minimalist pong game with a glowing ball and paddle in motion.A pixel-art game editor screen showcasing a level design in progress. The scene includes grassy platforms, a flowing river, and a large mushroom-shaped structure on the right. Waypoints labeled “Player Start” and “Boar Spawn” indicate setup points for gameplay logic in this visually charming environment.A gameplay screenshot of a retro-styled fruit-dropping game. Fruits like cherries and strawberries fall from the top of the screen into a large yellow playfield, guided by a green arrow. The minimalist UI and warm color palette evoke a nostalgic arcade vibe.
Nov 24, 2024, 7:42 AM

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.

Bailey Townsend 🦀's avatar
Bailey Townsend 🦀
@baileytownsend.dev

Finished up the pong example in the agbrs book. Could use some improvement (like the CPU is a bit op). But that's alright, I got a good refresher going through it. Time to move on to making my own small GBA game agbrs.dev/book/pong/00...

Sep 20, 2025, 3:15 AM


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!