Sept 7th - Sept 13th 2025

I've really enjoyed checking in on @bad-example.com weekly updates on microcosm. So I thought I might give it a try as well with some of my open source work! Also gives me a chance to try out leaflet.pub. I will most likely keep these semi short and a bit more casual with the idea I spend about 30 minutes writing up the retrospective of the previous day.

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

📅 at://advent - Sunday

🔒 PDS gatekeeper - Monday

👾 Hollow Knight - Monday, Thursday

🧰 AT Toolbox - Monday, Tuesday, Wednesday, and Thursday

🐮 PDS MOOver support - Wednesday

🌃 Blacksky.community - Wednesday

🧹 PDS Dashboard (side quest) - Friday

✍️ Wrote a Blog Post (side quest) - Saturday

Sunday, September 7th, 2025

at://advent challenges framework

A bit of a foreword if you're not familiar with at://advent. It's a project me and a few others are working on. The goal is Code of Advent like thing, but for atproto! The hope is some fun challenges to help people learn more about the protocol and have some fun.

I finished up my PR for the challenges framework for at://advent. Took an LOT longer than I was expecting. But I finally got it in! Can see what that looked like over at @oppi.li/at-advent PR #3. Ended up being a lot of code, but the end goal was to make a simple way for challenge creators to a.) use rust code to create logic to verify a challenge has been completed. b.) an easy way to create custom views to show those challenges.

The TLDR for each is I used a trait for the rust code so the challenge creator has full control over how it works, gives some helpers, and allows re usability on the web routes. Can see that trait here and an example of how it is used here. The view for the challenges themselves are just in markdown and you can use handlebars templating syntax to customize them a bit, can see one here

Monday, September 8th, 2025

I spent a good chunk of time and energy on the at://advent challenges framework over the weekend and last week. So this week I'm going to take things a bit easier (HA HA HA HA - Bailey with 20/20 vision on Sunday morning before publishing)

AT Toolbox

I've had my eye on wanting to do a small AT Toolbox update lately to add a few new shortcut actions. @bad-example.com kicked it off by kindly sharing a bug they found in the action to get a serviceAuth token (JWT token signed by your user that is verifiable on protocol)

So I figured it was only fair since I nerd snipped them last week to return the favor and be nerd snipped this week. So thus started "the fig update" for AT Toolbox! Main goals were fixing that bug and adding shortcut actions for constellation 🌌

Work done:

Fixed the bug found. in my getServiceAuth endpoint. I was using the user's did as the audience parameter instead of a did:web provided by the user 😬

Cleaned up a swift client I had written a while back for constellation 🌌 api end points

PDS gatekeeper

@rude1.blacksky.team reached out about a bug on PDS gatekeeper. I had implemented rate limits on the sign in endpoints since they do verify password hashing. It's using tower_governor which works in allowing bursts. Example, given a burst of 5 and 60 seconds as settings this means that after 5 tries in 60 seconds it takes one off and you can try again, or if you wait 5 minutes can try all 5 at once.

Well it appeared that it was being a bit more aggressive on those limits. Turns out since it was being a reverse proxy by caddy it was using that local IP (127.0.0.1) as the key for rate limiting, so everyone on the server shared the same rate limit (whoops). Was a pretty easy patch and got that out the door. Can see that here.

Hollow Knight

I never played Hollow Knight, but with all the hype around Silk Song I wanted to give it a shot and playing a bit here and there. Sat down Monday night and defeated the first boss. So far I like the game, just wish it was a smidge more accessible for casual gamers. The fear of playing and not finding a bench to save before I have to go is real, but that is also some of the charm of it.

Tuesday, September 9th, 2025

AT Toolbox

I finished implementing the constellation 🌌 endpoints into shortcut actions. I'm pretty happy with them all. The /links/all endpoint is a bit awkward since it returns a dynamic object with the collections as the keys, and the keys of it as paths. So the shortcut version returns counts, a semi friendly way for shortcuts to view that info as Collection: com.my.collection, Path: .subject.uri along with the JSON response. The hope there is it is enough they can get the collections and paths to know what to use on the other constellation 🌌 endpoints, and the full JSON response is there if they need it.

Here's an example of what a shortcut to see how many people have verified a user may look like demoing a new action that uses constellation 🌌.

I also started playing around with the ability to make custom xrpc request from an action. The idea is this will let users create requests for other /xrpc endpoints that are not implemented yet (like app.bsky.bookmark.getBookmarks). I did a bit of a sneak peak here of it

couple of info bites:

When you select a user it uses that users PDS as the baseurl

the lexicon method then appends /xrpc/{lexicon method}

GET queries and POST bodies can be passed in via shortcut dictionaries.

Audience allows you to set the atproto-proxy to a did web with a service like did:web:myneatapp.view#service_name so that the request can be proxied to another appview as described here

Still heavily wip and hoping to do some more testing on Wednesday and maybe even get a Test Flight build out for some extra eyes on it.

Wednesday, September 10th, 2025

AT Toolbox

I had written most of the code yesterday for XRPC proxying so today was doing testing and bug patching A fun little bug I hit was I kept getting "Bad Token Method" for trying to proxy a request to the chat.bsky.* before I realized that I had not set "Allow access to your direct messages" when creating the App Password 😬. Took me reading the source code before I realized. In my defense, the error code did make it sound like it might have been something else and I would expected an error about permissions...

pipethrough.ts#L65

if (
credentials.type === 'access' &&
!isAccessPrivileged(credentials.scope) &&
PRIVILEGED_METHODS.has(lxm)
) {
throw new InvalidRequestError('Bad token method', 'InvalidToken')
}

I did get a build submitted to Apple for Test Flight, so I am hoping it is approved soon. And actually as I am writing this it was approved 😳. Was a 35 minute turn around on that review. So now all that is left in 1.0.5 is testing, write some new documents for the new actions, and some new examples. It's close!

PDS Migrators

With the events of the day both in the world as well as the atmosphere many users were ready to make a jump to a third party PDS not hosted by Bluesky. Last month I created the PDS migration tool pdsmoover.com to help users do just that. To this day it is probably my proudest atproto application. It is the one that has had the most impact on helping users feel safer and protect their online identity by moving to their own or another hosted PDS. So I spent a good bit of the night helping users with any issues they might of had as well as watching the unique visitor count skyrocket for pdsmoover.com.

Blacksky.community

The PDS blacksky.app supports two endings for handles .blacksky.app or .blackskycomra.de. This caused an issue where some users would accidentally change to one or sign up with one and cannot change to the other.

The official Bluesky client does not support multi domain handle changes in the settings. I'm guessing it just may have been an oversight since they only support .bsky.social. But they do support it on account creation. So I made a PR to blacksky.community to copy that functionality to the change handle screen in settings.

PR can be found here

Thursday, September 11th, 2025

AT Toolbox

I ended up not working a lot on side projects. I did get some feedback back from the Test Flight build. So far so good! No major bugs reported. I am going to spend some time this weekend on documentation and examples for the new actions. I debated about not doing new examples for this release, but it’s really the best way to test the shortcut actions to make sure they work as expected. Hoping to have it submitted to the App Store by Saturday-ish.

Hollow Knight

I played a little bit more of Hollow Knight as well. Still don’t think I’m cut out for it, but it has been pretty fun! I got my second charm, the one that allows collection of more souls.

Friday, September 12th, 2025

PDS Dashboard (a side quest)

Everyone loves a good side quest. What I thought would take me a couple of hours ended up being a couple more on top of that. But selfhosted.social now has a landing page! The witches over at @witchcraft.systems has probably the coolest looking landing page for their PDS(pds.witchcraft.systems) in the atmosphere. While looking at it today I found out that it is open source, so I decided to fork it and change it a bit for the selfhosted.social PDS.

You can find my fork at @baileytownsend.dev/pds-dash-fork.

A few of the changes I made:

Added a simple cache in localStorage for some of the repeat calls like did -> handle, and the user's profile pdsfetch.ts#L432

Changed loading the blobs from com.repo.sync.getBlob to use Bluesky's cdn PostComponent.svelte#L99

A new theme that is somewhat similar to daisyui's dark theme dark/theme.css

Reply to now shows the author's name instead of the did since those are cached and easier to load in

On the UI side I added the ability to load in a user's most recent xyz.statusphere.status and teal.fm play record

I added RichText support as well for the posts so they would render hyperlinks for link facet's and mentions

This was also my first time using Svelte and first time using Deno since 2022-ish(when fresh launched).

Svelte I really liked the template rendering. I've always found the closer it is to HTML the easier it is for me to read. I think I'm going have to add it to my list of things to read up on.


{#each post.richText.segments() as segment}
{#if segment.mention}
<a href="{Config.FRONTEND_URL}/profile/{segment.mention.did}"
>{segment.text}</a
>
{:else if segment.link}
{segment.text}
{:else if segment.text}
{segment.text}
{/if}
{/each}


Deno was also nice! My favorite part about it was besides the commands I had no idea I was using Deno. This may sound like an insult, but it was so nice to just have it plug and play with the tools I am familiar with. This was not the case 3 years ago. I am going to be reaching for Deno a lot more when developing projects going forward I think.

Saturday, September 13th, 2025

MigrationMania

I think a lot of atproto users took the weekend to migrate. Was an increase in mentions in people needing help and thanking me for PDS MOOver. Love to get those, it's really nice to see something I've written help others. Here's a 7 day graph to show just the uptick in interest for users going to pdsmoover.com

The hell is the atmosphere anyway?

I wanted to take a stab at explain what atproto was to a larger audience so I wrote the leaflet What the hell is the atmosphere anyway. I'm pretty happy with it! The goal was to take some of the basic concepts and break them down for a larger audience to digest.

And that's my week! Was kind of expecting to be a bit more laid back, didn't quite happen. But that's okay. Was a fun week and excited to see what next week brings. Thank you for reading if you made it this far! I plan on putting out a similar post to do this next Sunday-ish!