Bridgy Fed: a translation layer between ActivityPub, AT Protocol and webmentions
🌉 A bridge between decentralized social networks
At a glance
- What is it?
- Bridgy Fed is a Python web application that converts profiles and interactions between the fediverse, Bluesky and the IndieWeb, and it is documented closely enough that a new protocol can be added by subclassing two base classes.
- Who is it for?
- Bridgy Fed is the right tool when your problem is moving one identity and its interactions between ActivityPub, Bluesky and IndieWeb rather than running any one of them, and it is open to anyone who wants to add a protocol to that set. It is the wrong tool for a self contained service, because it is an application rather than a packaged library and its dependencies are pinned to GitHub heads, so installing it means deploying it.
- Can I use it commercially?
- Yes. CC0-1.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 15, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One identity translated into profiles, likes, reposts and follows
Bridgy Fed connects decentralized social networks that do not share a protocol. The supported set covers the fediverse, with Mastodon named as an example, reached over ActivityPub; Bluesky, reached over the AT Protocol; and the IndieWeb, reached over webmentions with microformats2. What moves across the bridge is the substance of an account: profiles, likes, reposts, mentions, follows, and more. The application lives at fed.brid.gy, with separate user documentation and separate developer documentation published under a readthedocs address. The design point is worth stating plainly. Bridgy Fed does not try to make one protocol the winner and translate down to it. It maintains its own model of a person and their activity, and translates in both directions between that model and each supported network.
Farcaster and Nostr are still open questions in the source tree
The supported list is short on purpose, and two further protocols are marked as under consideration, Farcaster and Nostr, each with a tracked issue in the repository. That is the public statement. The source tree shows the work in progress: it contains nostr.py, nostr_hub.py, farcaster.py and farcaster_hub.py alongside activitypub.py, atproto.py and the rest of the protocol modules, plus a set of per-protocol ActivityStreams configuration files named after the bot accounts such as ap.brid.gy.as2.json and bsky.brid.gy.as2.json. A protocol being under consideration and having a module in the tree are different things, and the documentation has not yet turned those modules into supported protocols.
Local development needs the Firestore emulator and a project id
The development setup is documented in full and it is not small. You need the Google Cloud SDK, and the Firestore emulator installed as a component. The environment is then set up in the repository root with these commands, which create a virtual environment, install the pinned requirements and link the static files that OAuth Dropins serves.
gcloud config set project bridgy-federated
python3 -m venv local
source local/bin/activate
pip install -r requirements.txt
# needed to serve static files locally
ln -sf local/lib/python3*/site-packages/oauth_dropins/static oauth_dropins_staticThe documentation notes that `uv` can be used instead of `pip`, with the `--no-sources` flag if you do. Tests run against the emulator on port 8089 in datastore mode, and the app itself starts with a Flask command that points at the Bluesky app view, the PLC directory and a bridge PDS host.
gcloud emulators firestore start --host-port=:8089 --database-mode=datastore-mode < /dev/null >& /dev/null &
python3 -m unittest discoverenv FLASK_ENV=development APPVIEW_HOST=api.bsky.app PLC_HOST=plc.directory BGS_HOST=bsky.network PDS_HOST=atproto.brid.gy flask --debug run -p 8080Adding a protocol means subclassing Protocol and User
The contribution guide spells out the recipe for a new protocol and puts the design work before the coding. First you decide how the new protocol maps onto the existing ones in terms of identity, protocol inference, events and operations, and you add that to the tables in the docs template in a pull request. Then you register the protocol in `DEBUG_PROTOCOLS` in models.py, implement the identifier and handle conversions in ids.py, and add any new data format to granary with functions that convert to and from ActivityStreams 1 plus tests. The protocol itself becomes a new .py file subclassing both `Protocol` and `User`, implementing `send`, `fetch`, `serve`, `target_for` and `create_for` on one side and `handle`, `handle_for_id` and `web_url` on the other. Two remaining items are marked as todos: a usage section in the docs and any extra UI or signup behaviour the protocol needs.
This is an application, so its dependencies track GitHub heads
The pyproject file says it directly in a comment: bridgy-fed is an application, not a packaged library, so the file exists only to manage dependencies, and the packaging section lists no packages. The project name is `bridgy-fed`, the version is 1.0, and Python 3.14 or newer is required. Most of the internal dependencies are installed from GitHub URLs at branch heads rather than from a package index, including arroba, authlib, brevity, carbox, dag-json, granary, httpsig, lexrpc, mf2util, mox3, negotiator, oauth-dropins, pymemcache, secp256k1 and webutil, with the pinned compiled list generated separately. Third party packages such as Flask, cryptography, requests and websockets come from the index with version floors. The practical consequence is that there is no `pip install bridgy-fed` that gives you a component, and a deployment inherits whatever those branches contain at build time.
Posting as the bridge accounts happens through a webmention
The protocol bot accounts, such as @ap.brid.gy and @bsky.brid.gy, have no user interface to log into, so posting as them takes a deliberate workaround. They are set up as bridged web accounts. To post, you create a blog post without a title on snarfed.org, keep it under 300 characters for Bluesky, then send a webmention to Bridgy Fed so it bridges the post. The source has the shape of an internal URL built from the post address, and the request is made with curl using the Flask secret key as authorization, with a force flag in the payload.
cd ~/src/bridgy-fed && curl -v -H "Authorization: `cat flask_secret_key`" \
-d source=https://ap.brid.gy/internal/snarfed.org/... \
-d force=true \
https://fed.brid.gy/webmentionDeployment to the production instance follows the same pattern of explicit gating: the docs say to run the App Engine deploy command with the project id only if @snarfed has added you as an owner.
Public domain terms and no tagged releases
The licence is unusually generous for an application of this size. The project states that it is placed in the public domain and that you may also use it under the CC0 licence, and the licence field in the package metadata records CC0-1.0. That removes the copyleft obligations that would normally attach to a federation bridge and to the protocol mapping work, which matters if you intend to reuse the translation tables or the identity model. The repository has no GitHub releases at all, so there is no version history beyond the commit log and a CHANGELOG-style set of files, and it does carry a SECURITY.md, a FEDERATION.md and an admin.py alongside the protocol modules. The last push to the repository was on 2026-10-15, so the code is being worked on even though nothing is tagged.
Editorial conclusion
Bridgy Fed is the right tool when your problem is moving one identity and its interactions between ActivityPub, Bluesky and IndieWeb rather than running any one of them, and it is open to anyone who wants to add a protocol to that set. It is the wrong tool for a self contained service, because it is an application rather than a packaged library and its dependencies are pinned to GitHub heads, so installing it means deploying it. Before you build on it, read the protocol mapping step in the developer docs, because that decision about identity and event semantics is the part a new protocol gets wrong.
Frequently asked questions
Which protocols does Bridgy Fed support?
It supports the fediverse over ActivityPub, Bluesky over the AT Protocol, and the IndieWeb over webmentions with microformats2. Farcaster and Nostr are listed as under consideration.
How do I run Bridgy Fed locally?
Install the Google Cloud SDK and the Firestore emulator, create a virtual environment, install the pinned requirements, start the emulator on port 8089 in datastore mode and run the Flask development server on port 8080 with the documented environment variables.
What does a new protocol plugin have to implement?
A new .py file that subclasses both `Protocol` and `User`, with `send`, `fetch`, `serve`, `target_for` and `create_for` from one and `handle`, `handle_for_id` and `web_url` from the other, plus id conversions in ids.py and a data format in granary when the protocol needs a new one.
Can I install Bridgy Fed as a Python package?
No. The packaging file states that the project is an application rather than a packaged library, lists no packages, and its internal dependencies are installed from GitHub branches at build time.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/snarfed-bridgy-fed)Was this useful?