Org Social is so simple it looks like it was born before the internet. A single plain text file, an editor and a host are enough to interact with other people.
To "create an account", you just create a plain text file in any editor. Your "database" is your own hierarchy of posts. Your "algorithm" is however you decide to sort other people's posts. There is no "character limit". Your "server" is any hosting or web server. Your "interface" is your favorite editor. And if you want to "delete your account", you just delete the file. And of course, the syntax is richer than Markdown and just as easy to learn: Org Mode. You share and edit wherever you want, and you use it as a microblog, a journal, a forum, a bulletin board or a blog. Your file, your rules.
Behind it there is infrastructure that enriches the interaction and connects it with other systems and formats (the Fediverse, RSS, clients...). Each piece adds one more level of convenience, but none of them is essential: they are 100% optional! And that is what I want to talk about.
I'd like to take it apart piece by piece, explaining what each one does and why it exists.
Layer 0: a plain text file
Everything starts and ends here. A file called social.org, in UTF-8, with LF line endings.
The header is your profile. They are Org Mode keywords:
#+TITLE: My journal
#+NICK: Alice
#+DESCRIPTION: I write about Emacs and coffee
#+AVATAR: https://alice.com/avatar.jpg
#+LINK: https://alice.com
#+FOLLOW: https://bob.com/social.org
#+FOLLOW: friend https://carol.net/social.org
Below it, in a * Posts section, go your posts. Each one is a heading with an RFC 3339 timestamp, which works as a unique identifier:
** 2025-05-01T12:00:00+0100
:PROPERTIES:
:LANG: en
:TAGS: emacs org-social
:END:
Today I discovered Org Social and I can't stop writing.
And you already have a social network.
Anyone can curl your file, read it with their own eyes or with a client or script, and follow you by adding your URL to their #+FOLLOW:.
The interaction itself lives inside the format. There are no magic buttons, there are properties:
- Replying is a post with
:REPLY_TO: <url>#<id> pointing to the original.
- Reacting is a reply with just
:MOOD: ❤ and an empty body.
- Sharing is
:INCLUDE: with a reference to someone else's post.
- Voting in a poll is replying with
:POLL_OPTION:.
- Mentioning someone is a link
[[org-social:https://bob.com/social.org][Bob]].
Since it is plain text, you can edit all of it by hand if you feel like it.
When you are done, you save the file and upload it to your server.
Every decentralized social network has a weak spot, whichever one comes to mind. I covered this in There is no such thing as full decentralization, but in short, you always have to decide which of these five things the network sacrifices:
- Identity
- Connectivity
- Discovery
- Cost
- Moderation
Org Social sacrifices discovery. Nobody can find you unless you give them your URL, just like an email address. And that makes some interactions impossible to reconstruct. For example, what happens if someone you don't follow joins a thread you started? If you don't follow them, you never find out.
That's why we need upper layers that mitigate the problem, although you should only use them if you think you need them. It may be that everyone taking part follows each other and needs nothing else. Otherwise, you will need a Relay: an index.
Layer 1: the client
You can check each feed directly with curl or with your browser. However, just like with your list of RSS/Atom feeds, what we all end up doing for convenience is using a client. It reads every source, sorts them, filters them and merges them into a list that is easier to read and that you can also navigate. The same goes for Org Social.
There is a client for Emacs, another for iOS, another for Android (in alpha as I write this), command line implementations and a public web viewer that needs no account or client. Clients build a timeline by merging all the feeds you follow, and they let you reply, react, share and vote in polls. But every change happens in your own file, not on a central server, and reading is volatile, since it is built on the fly.
:quality(85)/https://andros.dev/media/blog/2026/10/org-social-screenshot.png)
The client also acts as a translator between Org Social and the interface you choose. And it is a good way in for people who are already used to X/Twitter or Mastodon, or who don't want to bother learning the syntax.
Layer 2: the Relay
The Relay is a server that crawls the network of social.org files and builds an index: users, mentions, replies, groups and threads. It does this by reading the #+FOLLOW: lines of every feed it knows and downloading the files it finds. You can also register your feed manually so it reads it.
It doesn't store content, only addresses. It notes who mentions whom, what replies to what and what belongs to each thread.
Now you can write a client or a script that asks the Relay for the information that fills in the parts where you were blind before:
# Who mentioned me?
curl "https://relay.org-social.org/notifications/?feed=..."
# Give me the full thread of this post
curl "https://relay.org-social.org/replies/?post=..."
# Find everything about Emacs
curl "https://relay.org-social.org/search/?q=emacs"
And that's not all: anyone can run their own Relay, locally or on a server. Their instance will connect to other public Relays and they will exchange information, so the whole network knows which feeds exist and how they relate.
It also offers other features, such as real-time notifications, RSS/Atom feeds, post search and bridges to ActivityPub/Mastodon. Yes, you can follow Mastodon accounts from Org Social, or keep up with Org Social from your favorite RSS/Atom reader.
Layer 3: Org Social Host
Needing your own hosting just to start taking part in the network is a tough requirement. That's why there is a free and open hosting service, integrated with the clients, that puts your social.org online with a single click.
You pick a nick and get two addresses:
- public-url: the one you share with everyone, for example
https://host.org-social.org/alice/social.org.
- vfile: a secret, signed URL that works as a password. Whoever has it can overwrite your file, so keep it safe.
If you use a client, all of this is automatic and you never even see the secret URL, since it is stored in your configuration. It all happens behind the scenes.
If you are curious, signing up is a single request:
curl -X POST https://host.org-social.org/signup \
-H "Content-Type: application/json" \
-d '{"nick": "alice"}'
And overwriting your file, another one:
curl -X POST https://host.org-social.org/upload \
-F "vfile=YOUR_VFILE" \
-F "file=@social.org"
It doesn't lock you in either. You can ask it for a permanent redirect (HTTP 301) to your new URL and your followers won't even notice. Their clients follow the redirect on their own, although it's a good idea to let them know so they update their #+FOLLOW:. It is a way in, not a requirement.
You can also run it on your own server, with public sign-up disabled and your own domain.
And it has an advantage that seasoned app developers will have guessed already: it makes syncing between devices easy. You can, for example, write in the mobile client and carry on in the Emacs one with simple HTTP requests. No old protocols, no third-party APIs.
Layer 4: Mirror or CDN
Do you use an RSS/Atom reader? Then you already know that the more feeds you follow, the slower it gets.
It doesn't matter how fast and parallel the downloads are. There will always be dropped connections, timeouts, errors and redirects. And if a feed is very large, the client has to parse all of it to keep what it cares about.
In my case, I follow 250 feeds. Download and parse them every time I scroll? Not viable. Cache them? Then the problem becomes when to invalidate the cache.
This is where the Mirror comes in. It is a server that keeps an up-to-date copy of every feed and saves you the parsing, sorting, thread building and mention consolidation. It exposes a simple REST API that returns JSON ready to use in a client.
You can think of it as a client of clients, or a general-purpose client without an interface. Internally, it works non-stop to keep the most recent copy and to prepare the processed information so it is easy to consume.
For example, if I want to build the timeline with Bob's and Carol's posts from the last 14 days:
curl --get "https://mirror.org-social.org/api/posts/" \
--data-urlencode "following=https://bob.com/social.org" \
--data-urlencode "following=https://carol.net/social.org" \
--data-urlencode "sinceDays=14"
It doesn't replace the Relay. In fact, it needs it to know which feeds exist and which ones have changed. And most importantly: it is read-only. It never edits or deletes anything at the source. To publish, you still write to your own file. Its only way in is a webhook that a client can call to say a feed has changed and the Mirror should update it:
curl -X POST "https://mirror.org-social.org/api/webhook/refresh/" \
-H "Content-Type: application/json" \
-d '{"feed": "https://alice.com/social.org"}'
It is optional. The client calls it right after publishing or uploading a new version of the file to your hosting, so the Mirror updates its copy straight away instead of waiting for the next refresh cycle.
Layer 5: Push
The Relay already sends real-time notifications with Server-Sent Events, which clients can listen to in order to tell you about mentions, replies and reactions. But phones don't let an app keep connections open in the background, so there you need push notifications. It is the most specific layer of all, since each platform, iOS and Android, has its own notification system with its own certificates and tokens.
If this layer goes down, all you lose is the convenience of getting alerts on your phone while the app is closed.
Layer 6: Live Preview
An Org Social post has an address in the format https://<host>/social.org#<timestamp>. For example, my first post: https://host.org-social.org/andros/social.org#2025-08-14T09:11:00+0200. It works fine between Org Social clients, but what happens if you want to share it on another social network? Nothing pretty: the whole social.org file gets shared.
Live Preview turns a post into a web page. You give it the post URL, it downloads the original social.org (straight from the source, not through the Relay), finds the post and generates an HTML card with its Open Graph metadata: nick, avatar, text and date. Ready to share on any social network.
For example, the URL above becomes:
https://preview.org-social.org/?post=https%3A%2F%2Fhost.org-social.org%2Fandros%2Fsocial.org%232025-08-14T09%3A11%3A00%2B0200
:quality(85)/https://andros.dev/media/blog/2026/10/org-social-live-preview.png)
And if I share it on social media, it looks like this:
:quality(85)/https://andros.dev/media/blog/2026/10/org-social-live-preview-whatsapp.png)
Clients also use this link format in their share option.
The same need gave birth to another very interesting feature: generating an HTML blog from your social.org, if it is hosted on host.org-social.org.
For example, my Org Social web version would be preview.org-social.org/blog/andros.
:quality(85)/https://andros.dev/media/blog/2026/10/org-social-live-preview-blog.png)
You write in Org Mode, upload the file to the hosting (with a simple curl if you like) and your HTML blog is generated automatically, ready to share. It isn't perfect, since you don't control the design, but it saves you from running a static site generator.
Summary
In the end, they are not layers, but pieces orbiting around your social.org.
flowchart TB
File["social.org"]
Client["Client"]
Relay["Relay"]
Host["Host"]
Mirror["Mirror"]
Push["Push"]
Preview["Live Preview"]
Client -- "reads and writes" --> File
Client -- "uploads and syncs" --> Host
Host -- "hosts" --> File
Host -- "registers feeds" --> Relay
Relay -- "indexes" --> File
Client -- "mentions, threads and search" --> Relay
Mirror -- "which feeds exist and which change" --> Relay
Mirror -- "copies" --> File
Client -- "JSON timeline and webhook" --> Mirror
Relay -- "real-time notifications" --> Push
Push -- "phone alerts" --> Client
Preview -- "reads" --> File
Client -- "share link" --> Preview
| Piece |
What it gives you |
If you remove it |
social.org |
Your identity and your posts |
There is no network |
| Client |
Reading and writing comfortably |
You read with curl and edit by hand |
| Relay |
Discovery, mentions, threads and bridges |
You only see who you follow |
| Host |
Hosting without a server and syncing between devices |
You use your own hosting |
| Mirror |
Ready-to-use JSON, no Org parsing |
The client downloads and parses every file |
| Push |
Alerts on your phone |
You find out when you open the app |
| Live Preview |
Sharing posts outside the network |
You share the raw file URL |
Whatever you use, the only essential piece is your social.org.
If every Org Social server shut down tomorrow, what would you lose? Convenience. And what would you keep? Your file, intact, on your disk. You upload it anywhere else and keep posting.
Few social networks can say the same.
Help me keep writing Every coffee gives me a push toward the next article. Sure, it's on me!
Send an email to comment+article-6c165f77@andros.dev to leave a comment. The subject will be ignored.