Tag: social

29 posts
ATProto in Practice #1: Identity
M
MacKuba blog
mackuba.eu

ATProto in Practice #1: Identity

I’m starting a new blog post series that I’ve named “ATProto in Practice”. I want to go through some practical tasks that you’re likely to need when working with the protocol, using Ruby and my Ruby gems for the examples. These will (hopefully) be a bit shorter than my standard book-length blog posts here 🫠 If you’re new to the AT Protocol and you haven’t read my long Introduction to AT Protocol post that goes through the whole architecture and defines the various pieces of it, I recommend you read that one first, because I won’t be explaining everything from scratch again here. Let’s start with something pretty fundamental: user identity. DIDs & handles Every account has an immutable identifier called a DID (Decentralized Identifier), e.g. did:plc:z72i7hdynmk6r22z27h6tvur. This ID serves a similar role as an UUID might in an SQL database – it’s used everywhere behind the scenes in the protocol for any references between accounts and records, in URIs and so on. But generally every account also has a human-readable handle assigned to it, which can be changed at any time, and this handle is normally what you see in the UI, often in user-facing URLs, what you use to log in with, etc. The handle is a domain name, e.g. @python.org, and any existing domain name you own and use for your website can be used as your handle. As you start building on ATProto, one of the first things you might need to do is convert between these two identifiers. For example, a user logs in to your app using a handle and you need to first “resolve” it to a DID, or a URI or other reference in a record points to a DID, but you want to show the corresponding user’s handle in the UI, and the handle is not included in the data you got. A useful UI tool for quickly looking this up is internect.info. If you look up e.g. “firefox.com” there, you will get a page showing details of Firefox’s ATProto account: the DID (did:plc:m424cqoxwhxgjutbta7jmrur), when it was created, assigned PDS hostname, and so on. Now, how to do the same thing in code? Every DID has a so called DID Document, a JSON file storing some basic info about that identity, and among other things, that document includes the alsoKnownAs field, which lists the assigned handles, in the form of at:// URIs with only the first segment. Almost every account will have exactly one handle assigned, but it might happen that one will have zero or more than one. It might also happen that the array will contain some invalid strings which aren’t proper handles – e.g. don’t include the at:// prefix, or only contain one word and no periods. You need to filter only the valid ones. The assignment is bi-directional – a DID has one (usually) handle assigned in its document, and a handle resolves to a DID. You should ideally check the assignment in both directions, because it could happen that the other sign of the assignment is no longer valid, or worse – has never been real. That is, when you resolve a handle to a DID, check if th…

Jul 19, 2026
Social comments on my blog
M
MacKuba blog
mackuba.eu

Social comments on my blog

I had a comments section on this blog since the beginning. I always felt like a comments section was kind of a requirement for a blog: it’s not just a website where you publish posts, it’s a website where you publish posts and other people can comment on them. I strongly disagreed with bloggers who openly declared that they’re removing comments from their blog because their blog is not a place for others to add their remarks, and that they can always write to the author on Twitter if they want to contact them. But one obvious problem with comments on a blog, which got worse and worse over time, was spam. People tried to solve it e.g. with captchas, though as the bots got smarter, captchas had to get more complicated and annoying. For a very long time, I had a super simple captcha in the comment form that just asked: “Are you a human? (yes/no)”. You just had to write “yes” in the text field. And for a very long time it was enough – obviously it’s trivial to make a bot add an additional query parameter, the point was that nobody would think about it when writing generic spambots, and my blog isn’t famous so the bot authors wouldn’t have come across it. Things got worse around 2018-19. I started getting comments (I had email notifications for them) that were spam that obviously got around the captcha. So I started tweaking the captcha, adding multiple slightly more complex questions, but still such that you could answer them if you’re a developer or an Apple user – “What’s the name of the Mac operating system”, “Who is currently the CEO of Apple”, and so on. But it only worked for some time, and then I started getting spam again, while making the questions progressively harder over time: At some point I figured that this had to be actual people, rather than bots, adding the comments (talking in general, not about Jerry here above), people sitting at a computer, browsing websites and filling the forms by hand, because there was no way a bot would figure out that the question was a captcha and that it had to google for a name of a function (note, this was in pre-AI times). The comments were usually either in Russian or Ukrainian, or linking to some local service companies in some random small town in the US. There was no way I could out-captcha an actual human that can google for an answer. But it wasn’t a huge problem, I didn’t get many of those comments, and it was fairly easy to filter them out still by content, so I didn’t bother changing the system further. But here’s the thing: it’s not 2010 or 2018 anymore, and some other things have changed in the meantime too. I think it’s a bit of a truism that blogs and “blogosphere” aren’t what they used to be 15+ years ago. People post their thoughts on social media, Instagrams, Facebooks, LinkedIns, Substacks, record Tiktoks, YouTube videos or podcasts. Reading and writing blogs and commenting on them is a very niche hobby, let’s face it. After 2020-21, when for a while I was getting a ton of comme…

Jul 13, 2026

Hello from Leaflet

After all that effort making my static personal site posts standard.site compatible, I decided to start using Leaflet instead.

Jun 27, 2026
1

Standard.site

Exploring the Standard.site lexicon and integrating it into my hugo blog.

Jun 8, 2026
Joining the atmosphere
Rachel Andrew icon
Rachel Andrew
rachelandrew.co.uk

Joining the atmosphere

I don't post to or visit the social network formerly known as Twitter, but as a very early Twitter user, I can't quite bring myself to delete all my old posts. There's so much history there, not just personal history but the stories of a lot of the work I've done. This is the problem...

May 31, 2026

Integrating my website with ATProto

A first pass at integrating my personal site with the ATProto network. Publishing standard.site records on deploy and embedding bluesky comments on my post pages.

Feb 15, 2026
1

The (potential) fall of Discord

More age-verification, more downfalls

Feb 10, 2026
M
MacKuba blog
mackuba.eu

Running Bluesky PDS undockered

A bit over a year ago, in the first week of January 2025, I migrated my main Bluesky account to my own PDS on a Netcup VPS. It’s been quite easy to set up using the official installer, and it’s been running pretty much without any problems or maintenance the whole year. Despite that, I haven’t been 100% happy with this setup for one reason: Docker. So I decided to try to take it out of the box, and I made it run first on the same VPS installed separately, and then moved it to another machine this month with a clean install. This blog post is a guide to how I did this, if you’re interested. There are a few existing posts about this already: https://benharri.org/bluesky-pds-without-docker/ https://char.lt/blog/2024/10/atproto-pds/ https://cprimozic.net/notes/posts/notes-on-self-hosting-bluesky-pds-alongside-other-services/ But I figured it doesn’t hurt to make another one that does things slightly differently again. “There are many like this, but this one is mine”. (I mostly followed the benharri.org version.) Note: I’m describing what I did to migrate an existing PDS from in-Docker to outside-Docker, so I already had existing data and pds.env config; if you wanted to install one from scratch this way, you’d probably need to also set up the config manually. You might be asking: why? And that’s a good question. I mostly wouldn’t recommend this setup over the standard Docker one by default, unless you know what you’re doing. The standard installation is literally running one command and answering some questions, and then it auto-updates and manages everything. My reason is that I’m generally pretty familiar with installing things on Linux servers manually, but I’m completely unfamiliar with Docker. I always wanted to do some modifications on the PDS, but I didn’t know how, because the Docker setup basically takes over the whole server for itself. I don’t know where it pulls code from, I don’t know where it puts it, and I don’t know when it can overwrite any changes I make. I don’t feel in control. (And to be clear, this is likely a me problem.) So here’s what I did (this setup is for Ubuntu 24.04 Noble): Install Nginx The standard PDS distribution uses Caddy, but I use Nginx everywhere and I have configs built for it, so I’ve set up Nginx: # install Nginx sudo apt-get install --no-install-recommends nginx-light # enable HTTP on the firewall sudo ufw allow http/tcp sudo ufw allow https/tcp # if you haven't enabled ufw before: sudo ufw limit log ssh/tcp sudo ufw enable Also here’s a standard thing I do on VPSes to let me install webapps in /var/www from my account: # set up environment for webapps sudo groupadd deploy sudo adduser psionides deploy sudo chown root:deploy /var/www sudo chmod 775 /var/www I also need Certbot for LetsEncrypt: # install Certbot sudo apt-get install --no-install-recommends certbot python3-certbot-nginx sudo certbot plugins --nginx --prepare certbot plugins --nginx --prepare does some initial setup of …

Feb 4, 2026

Nostr - First Impressions

Some initial thoughts after connecting to the Nostr network using the Amethyst Android client

Jan 22, 2026
M
MacKuba blog
mackuba.eu

ATProto blog posts collection

(Last update: 3 Jun 2026.) I come across a lot of blog posts about the AT Protocol and Bluesky technicals – both on Bluesky official blogs and those of the team members, and by independent developers from the community. So many people are blogging now (especially now that Leaflet got popular in these circles) that I started using an RSS reader again just to keep up with everything. These posts are usually shared widely for a day or two, and then kind of forgotten – but a lot of them contain some valuable knowledge that is still relevant much later. Even if someone remembers that something like this has been written, it’s not always easy to dig it out from the archive. I thought it would be nice to have one place collecting those old and newer blog posts to make them easier to find. So I went through those RSS feeds, my like archives and other places, and collected everything I could find here in an organized list. I also included the documents from the “Proposals” GitHub repo, and various posts from the “Discussions” section in the ATProto repo. This is a subjective selection – from many blogs I skipped some less relevant posts or only included a couple out of many – so if you’re interested, click through to the home page from any post and look for the other posts there. Search posts by title: Bluesky official sources atproto.com articles Atproto for distributed systems engineers (Sep 2024) Atproto Ethos (Apr 2025) bsky.social/about/blog (non-technical blog) Composable Moderation (Apr 2023) How to verify your Bluesky account (Apr 2023) Federation Architecture Overview (May 2023) Bluesky: An Open Social Web (Feb 2024) Bluesky’s Stackable Approach to Moderation (Mar 2024) Tips and Tricks for Bluesky Search (May 2024) Bluesky Welcomes Mike Masnick to Board of Directors (Aug 2024) Bluesky Announces Series A to Grow Network of 13M+ Users (Oct 2024) 2024 In Review (Dec 2024) Bluesky’s Patent Non-Aggression Pledge (Oct 2025) What’s Next at Bluesky (Jan 2026) A New Chapter for Bluesky (Mar 2026) Bluesky’s 2025 $100M Series B Lays Foundation for Open Social Web (Mar 2026) docs.bsky.app/blog (old dev blog) Click to expand 2023 Why are blocks on Bluesky public? (Jun 2023) Featured Community Project: Skyfeed (Aug 2023) Posting via the Bluesky API (Aug 2023) Updates to Repository Sync Semantics (Aug 2023) Rate Limits, PDS Distribution v3, and More (Sep 2023) Bluesky BGS and DID Document Formatting Changes (Oct 2023) 2023 Protocol Roadmap (Oct 2023) Download and Parse Repository Exports (Nov 2023) Featured Community Project: Bridgy Fed (Dec 2023) 2024 Early Access Federation for Self-Hosters (Feb 2024) Announcing AT Protocol Grants (Mar 2024) Bluesky’s Moderation Architecture (Mar 2024) Meet the second batch of AT Protocol Grant Recipients (Apr 2024) 2024 Protocol Roadmap (May 2024) Labeling Services Microgrants (May 2024) Typescript API Package Auth Refactor (Aug 2024) OAuth for AT Protocol (Sep 2024) Lexicons, Pinned Posts, and Interopera…

Nov 18, 2025
M
MacKuba blog
mackuba.eu

How I ran one Ruby app on three SQL databases for six months

Since June 2023, I’ve been running a service written in Ruby (Sinatra) that provides several Bluesky custom feeds (initially built with a feed for the iOS/Mac developers community in mind, later expanded to many other feeds). If you don’t know much about Bluesky feeds, you make them by basically running a server which somehow collects and picks existing posts from Bluesky using some kind of algorithm (chronological or by popularity, based on keyword matching, personal likes, whatever you want), and then exposes a specific API endpoint. The Bluesky AppView (API server) then calls your service passing some request parameters, and your service responds with a list of URIs of posts (which the API server then turns into full post JSON and returns to the client app). This lets you share such feed with anyone on the platform, so they can add it to their app and use it like any built-in feed. (If you’re interested, check out my example feed service project.) In order to provide such service, in practice you need to connect to the Bluesky “firehose” streaming API which sends you all posts made by anyone on the network, and then save either those which are needed for your algorithm, or save all of them and filter later. I chose the latter, since that lets me retry the matching at any time after I modify the keyword lists and see what would be added after that change (and also some of the feeds I now run require having all posts). I also use the same database/service to generate e.g. the total daily/weekly stats here. All posts made on Bluesky is much less than all posts on Twitter, of course, but it’s still a lot of posts. At the moment (October 2025), there are around 3.5M posts made on average every day; at the last “all time high” in November 2024, it was around 7.5M per day. A post is up to 300 characters of (Unicode) text, but since I also store the other metadata that’s in the record JSON, like timestamp, reply/quote references, embeds like images and link cards, language tags etc., it adds up to a bit less than 1 KB of storage per post on average. In addition to that, the firehose stream (if you use the original CBOR stream from a relay, not Jetstream, which is a JSON-serving proxy) includes a lot of overhead data that you don’t need in a service like that, plus all the other types of events like handle changes, likes, follows, blocks, reposts, and so on. The total input traffic is around 15 Mbit/s average right now in October 2025 (or around 5 TB per month), and it used to be around twice that for a moment last year. (Jetstream sends around an order of magnitude less, especially if you ask it to send filtered data, e.g. only the posts.) On disk, the millions of posts per day add up to a few gigabytes per day. Since I was running this on a VPS with a 256 GB disk (Netcup, RS 1000 – reflink), I have a cron job set up to regularly prune all older posts and keep only e.g. last 40 days worth of them (since I don’t really need to keep the older posts …

Oct 15, 2025
C
Charles Harries
charlesharri.es

Dan Abramov: Open Social

Dan's recent post about open social platforms is the first time that I've been interested in social media in like... 5 years?

Sep 28, 2025
Introduction to AT Protocol
M
MacKuba blog
mackuba.eu

Introduction to AT Protocol

Walkthrough of the various parts and concepts in Bluesky's AT Protocol (ATProto), the types of servers involved and how it all fits together

Aug 20, 2025
Social media update 2025
M
MacKuba blog
mackuba.eu

Social media update 2025

So here we are, halfway through 2025, a bit over 2.5 years after the Eloncalypse… For better or worse, the Twitter as we knew it in the 2010s and the communities we had there are mostly gone. But it doesn’t feel like we’ve all settled on anything comparable. If you’re a software developer who was active on Twitter before, by now you’ve almost certainly tried at least one of the alternatives – Mastodon, Bluesky, and Threads, and you’re probably posting actively on at least one of these, but probably not on all of them. The problem is that nobody has enough mental space to be active on 3-4 similar social networks, so we’ve split into different camps which only partially overlap. You’re probably still missing some friends from Twitter and some interesting content. It’s all a bit in flux and a bit of a mess. Myself, I’ve basically left Twitter; I haven’t spent much time on Threads (among other reasons, it was unavailable in Europe for a long time); and I’m mostly hanging out on Bluesky and somewhat on Mastodon. So where do we go from here? Obviously everyone has their own take on that, this is just mine. But I really think we should all try to make an effort to focus on the widely understood “open social”, or what Laurens Hof from Fediverse Report now calls “Connected places”. That means Bluesky and Mastodon/Fediverse (with emphasis on “and”), and to some degree maybe also Threads, although that depends on how their integration with ActivityPub progresses (and it’s looking more and more like they aren’t very serious about it). My advice: → If you’re currently cross-posting or bridging between Mastodon and Bluesky: awesome! ❤️ → If you’re active on Mastodon, but currently ignoring or forgot about Bluesky: please reconsider it. I know that these two communities have a lot of differences between them, and we love to hate each other (I fully admit I’m guilty of that myself). It’s likely you prefer one or the other of these for various reasons, and you might not be a fan of the other one. But I think it’s clear at this point that none of them will disappear in the near-term at least or replace the other for everyone. It would be great if we all made some effort to connect to the other side, for those who like it more there. What are the options? Depending on what’s more convenient to you: there are some native apps which let you post to two or more services in parallel, e.g. Croissant, Openvibe or SoraSNS most social media management services like Buffer now support both Fediverse and Bluesky, so you can use that to post to both, including scheduling etc. There are several others like this, and they usually have some free plans. e.g. Fedica was one of the ones that had support for Bluesky from very early on also my friend from my first job, Peter Solnica (known from some Ruby libraries like DataMapper/ROM, dry-rb, Hanami, and now some Elixir libs too) is building his own called JustCrossPost I use a little tool in Ruby I wrote for myself named …

Jun 30, 2025
B
Business Goose Blog
goose.business

Tea Meetup Notes

hosted a small tea tasting meetup today!

Jun 8, 2025
M
MacKuba blog
mackuba.eu

Micro.blog journal

Update 17.11.2025: I’ve migrated this journal blog now from Micro.blog to Leaflet, a new blogging service built on top of Bluesky’s ATProto. I wrote about this here, the new URL is https://lab.mackuba.eu (I’ll add a redirect from ‘journal’ later). Just a quick update, if you’re following this blog via RSS: I’ve started a separate “journal” blog on micro.blog: journal.mackuba.eu. Micro.blog is an interesting service: it’s a one-man indie business that’s sort of a hybrid between a blogging platform and a microblogging social network. You can write anything between full-size blog posts and tweet-sized single messages, and you can cross-post them to Bluesky, Mastodon etc. You can also follow people from the community that’s formed there and reply to them, all in the form of those mini-blogposts (there are no likes or retweets though). The idea, as I understand, is to use a network of blogs to build a social network that uses the web itself as the foundation. I’m not really planning to use it in this social network mode, since I’m pretty happy now posting on Bluesky and to limited degree on Mastodon (I’ve completely stopped posting on Twitter at this point, since last autumn, when Elon started openly supporting Trump). I’m also not completely sold on this “web as a social network” idea. And I don’t intend it to replace this blog here either – I will still be (very) occasionally posting those super long articles here like the one about NSButtons or the guide to Bluesky. But I’ve felt the need for a while to have a place to post something in between those – not full blog, and not a micro blog, but a “mediumblog” so to say (not to be confused with a Medium blog) – like this post, for example. Something where I can sometimes post my thoughts more easily, when I want to write something that doesn’t really fit in a few skeets/toots, with less effort required to start and finish it. This seems like it could work for that. It’s also nice that it’s supposed to sync replies from Bluesky/Mastodon under the posted link back to the blog page as comments below (I’ll try to implement the same thing here). I also have it configured with my own domain, so I can possibly migrate it to something self-hosted like Jekyll or Hugo at some point, keeping all the links and content. For now, I’ve posted two updates about what I’ve been working on recently: about tuning a Postgres database to which I’m trying to migrate my Bluesky feeds service and a review of all I’ve done in 2024 I don’t know how often I will end up posting there, I don’t want to pressure myself, just to have a place to post when I have a need. So if you’re curious, follow me there via RSS (or on Bluesky or Mastodon).

Feb 4, 2025
N
Numergent
numergent.com

RedNote migration

Jan 15, 2025
N
Numergent
numergent.com

The Looming Stupidity Bubble

Jan 5, 2025
Devtools FM icon
Devtools FM
devtools.fm

Rudy Fraser - BlackSky - Next Generation of Social Media

Rudy Fraser built BlackSky, a safe community space carved from BlueSky using custom feeds and ATProto tools for Black creators.

Dec 14, 2024
Whispers in the Dark: Gleam Edition

Whispers in the Dark: Gleam Edition

I used Bluesky's Jetstream and gleam to resurrect and old project I made for twitter.

Nov 20, 2024
On Bluesky

On Bluesky

Some random thoughts on Bluesky (and Mastodon)

Nov 16, 2024
T
Todd Libby
toddl.dev

Bluesky

There are some decisions in life I would like to change, some I would not change for anything. Leaving Bluesky might be one of those I wish I could take back.

Nov 10, 2024
N
Numergent
numergent.com

Data ownership and layer fungibility

Sep 19, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024

Religious Faith In Pursuit of Environmental Justice (Chris Durante)

In recent years, the world’s religions, including the Abrahamic faiths as well as Hinduism, Buddhism, Taoism and various indigenous forms of spirituality, have

Jul 25, 2024