bridgy-fed/templates/docs.html

1145 wiersze
64 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div id="docs">
<div class="right third">
<a href="/static/snarfed_web_site.png">
<img class="shadow" src="/static/snarfed_web_site.png" />
</a>
<p><em>Personal web site</em></p>
<a href="/static/snarfed_mastodon.png">
<img class="shadow" src="/static/snarfed_mastodon.png" />
</a>
<p><em>Fediverse profile via Bridgy Fed</em></p>
</div>
<p>
Bridgy Fed turns your web site into its own <a href="https://en.wikipedia.org/wiki/Fediverse">fediverse</a> account, visible in <a href="https://joinmastodon.org/">Mastodon</a> and beyond. You can post, reply, like, repost, and follow fediverse accounts by posting on your site with <a href="https://microformats.org/wiki/microformats2">microformats2</a> and sending <a href="https://webmention.net/">webmentions</a>. Bridgy Fed translates those posts into <a href="https://activitypub.rocks/">ActivityPub</a>, and when people inside the fediverse respond, it sends those responses back to your site as webmentions.
</p>
<p>
This isn't <a href="https://indieweb.org/syndication">syndication</a> or <a href="https://indieweb.org/POSSE">POSSE</a>! You don't need an account on Mastodon or anywhere else. Bridgy Fed makes your site a first class member of the fediverse. People there will see your posts directly from your site, and vice versa.
</p>
<p>
Bridgy Fed takes some technical know-how to set up, and there are simpler (but less powerful) alternatives. If you just want your site's posts to show up in the fediverse, without any other interactions, <a href="https://www.google.com/search?q=rss+atom+mastodon+bot">consider an RSS or Atom feed bot instead</a>. Or, if you want to cross-post to an existing Mastodon account, <a href="https://brid.gy/">try Bridgy</a>.
</p>
<br>
<ul class="docs">
<p><em>Setup</em></p>
<li><a href="#setup">How do I set it up?</a></li>
<li><a href="#profile">How do I set up my profile?</a></li>
<li><a href="#update-profile">How do I update my profile?</a></li>
<li><a href="#user-page">Where's my user page and dashboard?</a></li>
<li><a href="#mastodon-link-verification">How do I verify my profile links (ie get green checks) in Mastodon?</a></li>
<li><a href="#opt-out">I hate this! How do I opt out?</a></li>
<br>
<p><em>Usage</em></p>
<li><a href="#how-post">How do I post to the fediverse?</a></li>
<li><a href="#which-posts">Which of my posts will show up in the fediverse?</a></li>
<li><a href="#apps">Which fediverse apps are supported?</a></li>
<li><a href="#which-parts">How does it decide which parts of my posts to include?</a></li>
<li><a href="#visible-links">What's up with the visible fed.brid.gy links in my fediverse posts?</a></li>
<li><a href="#reply">How do I reply to a fediverse post?</a></li>
<li><a href="#like">How do I favorite (aka like) or boost (aka repost) a fediverse post?</a></li>
<li><a href="#follow">How do I follow someone?</a></li>
<li><a href="#unfollow">How do I unfollow someone?</a></li>
<li><a href="#image">How do I include an image in a post?</a></li>
<li><a href="#hashtags">How do I use hashtags?</a></li>
<li><a href="#mention">How do I @-mention someone?</a></li>
<li><a href="#update">How do I edit an existing post?</a></li>
<li><a href="#delete">How do I delete a post?</a></li>
<li><a href="#fragment">Can I publish just one part of a page?</a></li>
<li><a href="#backfeed">How do fediverse replies, likes, and other interactions show up on my site?</a></li>
<li><a href="#read">How do I read my fediverse timeline/feed?</a></li>
<li><a href="#notifications">Are there notifications?</a></li>
<li><a href="#discovery">How can people on the fediverse find and follow me?</a></li>
<li><a href="#see-posts">How can I see what my posts look like inside the fediverse?</a></li>
<li><a href="#searchable">Can I make my posts show up when people search for them in the fediverse?</a></li>
<li><a href="#troubleshooting">I tried it, and it didn't work!</a></li>
<br>
<p><em>About</em></p>
<li><a href="#who">Who are you? Why did you make this?</a></li>
<li><a href="#cost">How much does it cost?</a></li>
<li><a href="#privacy">What do you do with my data?</a></li>
<li><a href="#history">How long has this been around?</a></li>
<li><a href="#terms">What are the terms of service?</a></li>
<li><a href="#bug">I found a bug! I have a feature request!</a></li>
<li><a href="#vulnerability">I found a security vulnerability!</a></li>
<br>
<p><em>Development</em></p>
<li><a href="#compare">How do the different protocols compare?</a></li>
<li><a href="#translate">How are the different protocols translated?</a></li>
<li><a href="#router">How are activities routed?</a></li>
<li><a href="#error-handling">How are errors handled?</a></li>
</ul>
<ul class="docs">
<br>
<h3 id="setup">Setup</h3>
<li id="setup" class="question">How do I set it up?</li>
<li class="answer">
<p>
<ol>
<li>Your site needs to support SSL. Bridgy Fed uses your domain as your identity, so it depends on SSL to prove that you own it.</li>
<li>Configure your site to redirect these URL paths to the same paths on <code>https://fed.brid.gy/</code>, including query parameters:</li>
<pre>
/.well-known/host-meta
/.well-known/webfinger
</pre>
<p>Here are instructions for a few common web servers:</p>
<ul>
<li>
<p><em><a href="http://wordpress.org/">WordPress</a> (self-hosted)</em>: install the <a href="https://wordpress.org/plugins/safe-redirect-manager/">Safe Redirect Manager</a> plugin, then add these entries:</p>
<code>
/.well-known/host-meta* => https://fed.brid.gy/.well-known/host-meta*<br/>
/.well-known/webfinger* => https://fed.brid.gy/.well-known/webfinger*
</code>
</li>
<li><em><a href="http://withknown.com/">Known</a></em> or <em><a href="https://drupal.org/project/indieweb">Drupal</a></em>: follow the <a href="#apache">Apache</a> or <a href="#nginx">nginx</a> instructions below.
</li>
<li id="apache"><em><a href="http://httpd.apache.org/">Apache</a></em>: add this to your <code>.htaccess</code> file:<br />
<pre>RewriteEngine on
RewriteBase /
RewriteRule ^.well-known/(host-meta|webfinger).* https://fed.brid.gy/$0 [redirect=302,last]</pre>
(<code>RewriteEngine on</code> is optional if you already have it earlier in your <code>.htaccess</code>. <code>RewriteBase /</code> is optional if you don't have any other <code>RewriteBase</code> directives, or if you put this <code>RewriteRule</code> inside an existing <code>RewriteBase /</code> section.)
</li>
<li id="nginx"><em><a href="https://nginx.org/">nginx</a></em>: add this to your <code>nginx.conf</code> file, in the <code>server</code> section:<br />
<pre>rewrite ^/\.well-known/(host-meta|webfinger).* https://fed.brid.gy$request_uri? redirect;</pre>
</li>
<li id="netlify"><em><a href="https://docs.netlify.com/routing/redirects/">Netlify</a></em>: add this to your <code>netlify.toml</code> file.
<pre>
[[redirects]]
from = "/.well-known/host-meta*"
to = "https://fed.brid.gy/.well-known/host-meta:splat"
status = 302
[[redirects]]
from = "/.well-known/webfinger*"
to = "https://fed.brid.gy/.well-known/webfinger"
status = 302
</pre>
</li>
</ul>
<li>Add <a href="https://webmention.net/">webmention</a> support to your site. This is strongly recommended, but technically optional. You don't have to automate the webmentions to Bridgy Fed to federate your posts, and you don't have to accept the inbound webmentions that Bridgy Fed sends, but you'll have a much better experience if you do. <a href="https://indieweb.org/webmention#Publishing_Software">Check out the IndieWeb wiki</a> for instructions for your web server.</li>
</ol>
</li>
<li id="profile" class="question">How do I set up my profile?</li>
<li class="answer">
<p>
Your site's fediverse profile comes from the <a href="https://microformats.org/wiki/microformats2">microformats2</a> <a href="https://microformats.org/wiki/representative-h-card-authoring">representative h-card</a> on your site's home page. Here's a minimal example to set your name and a profile picture:
<pre>
&lt;span class="<span class='keyword'>h-card</span>"&gt;
&lt;a class="<span class='keyword'>u-url</span>" rel="<span class='keyword'>me</span>" href="<span class='value'>/</span>"&gt;<span class='value'>Alice Foo</span>&lt;/a&gt;
&lt;img class="<span class='keyword'>u-photo</span>" src="<span class='value'>/me.jpg</span>" /&gt;
&lt;/span&gt;
</pre>
</p>
<p>You can use <a href="https://indiewebify.me/">indiewebify.me</a> to check your site's h-card interactively, but note that that doesn't check that it's <em>representative</em>. In the common case, this just means that your h-card needs a link to your home page with the <code>u-url</code> class. See the <a href="https://microformats.org/wiki/representative-h-card-authoring">representative h-card spec</a> for more details.</p>
<p>If you want to set a <a href="https://docs.joinmastodon.org/user/profile/#header">header image</a>, add a <code><a href="https://indieweb.org/featured">u-featured</a></code> image to your h-card, eg:
<pre>
&lt;img class="<span class='keyword'>u-featured</span>" src="<span class='value'>/my-header.png</span>" /&gt;
</pre>
</p>
<p>By default, your fediverse address will be <code>@yourdomain.com@yourdomain.com</code>. Many services (eg Mastodon) default to only showing the username, so this generally shows up as just <code>@yourdomain.com</code> in posts, and the full address appears on hover.</p>
<p>We recommend this for simplicity and predictability, for everyone else as well as you, but if you want a different username, you can set it by adding an <code>acct:</code> <a href="https://microformats.org/wiki/rel-me">u-url</a> link inside your h-card with <code>username@yourdomain.com</code>, eg:
<pre>
&lt;a class="<span class='keyword'>u-url</span>" href="<span class='value'>acct:alice@yourdomain.com</span>"&gt;<span class='value'></span>&lt;/a&gt;
</pre>
</li>
<li id="update-profile" class="question">How do I update my profile?</li>
<li class="answer">
<p> If you've changed the <a href="https://indieweb.org/representative_h-card">representative h-card</a> on your site's home page, and you want to update your profile in Mastodon to match, click the <button class="btn btn-default glyphicon glyphicon-refresh"></button> button next to your domain <a href="/web-site">on your user page</a>. Alternatively, you can send a webmention from your home page to <code>https://fed.brid.gy/</code>.
</li>
<li id="user-page" class="question">Where's my user page and dashboard?</li>
<li class="answer">
<p>
<a href="/web-site">Enter your domain here</a> to see your user page. It shows your site's current status, recent interactions, remote follow UI, and links to your timeline feeds in various formats.
</p>
</li>
<li id="mastodon-link-verification" class="question">How do I verify my profile links (ie get green checks) in Mastodon?</li>
<li class="answer">
<p>Mastodon's verified profile links with ✅ green checks are fun! <a href="https://docs.joinmastodon.org/user/profile/#verification"></a> Follow these steps to get one on your Bridgy Fed profile:</p>
<ul>
<li>Add a <a href="https://indieweb.org/rel-me"><code>rel=me</code> link</a> on your site that points to <code>https://fed.brid.gy/r/https://[DOMAIN]/</code> for your domain, eg <code>https://fed.brid.gy/r/https://snarfed.org/</code></li>
<li>Click the 🔄 button on your Bridgy Fed <a href="#user-page">user page</a> to update your profile on all of your followers' instances.</li>
<li>Log into any Mastodon instance where you have an account.</li>
<li>Search for your fediverse handle, eg <code>@snarfed.org@snarfed.org</code>.</li>
<li>Click on your fediverse user in the search results.</li>
<li>Wait a minute or two (or ten 😐), then refresh the page. You should see a green check on the profile link for your web site.</li>
</ul>
<p>When you're logged into a Mastodon instance, searching for your Bridgy Fed user triggers that instance to check and verify its profile link(s) in the background. This only works when you're logged in with a native Mastodon account. Also, each instance does this independently; verified links are not synched across instances.</p>
</li>
<li id="opt-out" class="question">I hate this! How do I opt out?</li>
<li class="answer">
<p>Sorry to hear it! Just put the text <code>#nobridge</code> or <code>#nobot</code> in your profile bio, refresh your profile on your Bridgy Fed user page, and it will stop bridging your account.</p>
</li>
<br>
<h3 id="usage">Usage</h3>
<li id="how-post" class="question">How do I post to the fediverse?</li>
<li class="answer">
<p>
Create a <a href="https://indieweb.org/post">post</a> with the <a href="https://microformats.org/wiki/h-entry"><code>h-entry</code> microformat</a> on your web site. Many web servers include this or compatible microformats automatically. The post can be a <a href="https://indieweb.org/note#How_to">note</a>, <a href="https://indieweb.org/article">article</a>, <a href="https://indieweb.org/like">like</a>, <a href="https://indieweb.org/repost">repost</a>, <a href="https://indieweb.org/reply">reply</a>, or <a href="https://indieweb.org/follow">follow</a>. For example:
<pre>&lt;div class="<span class='keyword'>h-entry</span>"&gt;
&lt;p class="<span class='keyword'>e-content</span>"&gt;<span class='value'>Two naked tags walk into a bar. The bartender exclaims, "Hey, you can't come in here without microformats, this is a classy joint!"</span>&lt;/p&gt;
&lt;a class="<span class='keyword'>u-bridgy-fed</span>" href="<a href='https://fed.brid.gy/'>https://fed.brid.gy/</a>" hidden="from-humans"&gt;&lt;/a&gt;
&lt;/div&gt;
</pre>
</p>
<p><a href="https://docs.joinmastodon.org/spec/activitypub/#sanitization">Mastodon preserves HTML links and line breaks, but removes all other formatting and tags.</a> Other fediverse sites vary in their HTML handling.
</p>
<p>Then, include a link (optionally blank, and if so with a <code>hidden</code> attribute to be kind to screen readers and keyboard navigation users)
to <code><a href="https://fed.brid.gy/">https://fed.brid.gy/</a></code> in that post and <a href="#setup">send Bridgy Fed a webmention</a>. That webmention will trigger Bridgy Fed to forward your post into the fediverse. Your web server may send the webmention automatically if it supports them, or <a href="https://indieweb.org/Webmention#Manual_Webmentions">you can send it manually.</a>
</p>
<p>(The <code>u-bridgy-fed</code> class isn't strictly necessary, but it's useful in some cases to prevent microformats2 parsers from <a href="https://microformats.org/wiki/microformats2-implied-properties#hyperlink_and_url_property">interpreting the link as an implied <code>u-url</code></a>.)
</p>
</li>
<li id="which-posts" class="question">Which of my posts will show up in the fediverse?</li>
<li class="answer">
<p>Only the ones you <a href="#send+Bridgy+Fed+a+webmention">explicitly trigger with a webmention</a>. Bridgy Fed doesn't automatically create posts in the fediverse based on your site's Atom feed, HTML, or anything else. It only create posts in the fediverse on an opt in basis, per post, via webmention.
</p>
</li>
<li id="apps" class="question">Which fediverse apps are supported?</li>
<li class="answer">
<p>Lots! <a href="https://joinmastodon.org/">Mastodon</a>, <a href="https://friendi.ca/">Friendica</a>, <a href="https://misskey.page/">Misskey</a>, <a href="https://joinpeertube.org/">PeerTube</a>, <a href="https://hubzilla.org/">Hubzilla</a>, and more. We're working on interoperation with others; <a href="https://github.com/snarfed/bridgy-fed/issues/12">see GitHub issues with the <code>app</code> label for details.</a></p>
</li>
<li id="which-parts" class="question">How does it decide which parts of my posts to include?</li>
<li class="answer">
<p>Magic! Most major blog engines and CMSes are supported out of the box, no setup necessary. Bridgy Fed looks for <a href="http://microformats.org/">microformats</a> in your HTML, first the <a href="http://microformats.org/wiki/microformats2">microformats2</a> <code><a href="https://microformats.org/wiki/h-entry#Core_Properties">e-content</a></code> class and then the legacy <code><a href="https://microformats.org/wiki/hatom#Entry_Content">entry-content</a></code> class. It also understands more advanced microformats2 classes like <code><a href="#reply">in-reply-to</a></code>, <code><a href="#like">u-like-of</a></code>, <code><a href="#like">u-repost-of</a></code>, and <code><a href="#image">u-photo</a></code>.
</p>
<p>Bridgy Fed sends the full contents of all posts, specifically everything inside <code><a href="https://microformats.org/wiki/h-entry#Core_Properties">e-content</a></code>, to the fediverse. However, not all fediverse apps currently <em>show</em> the full contents of all posts.
</p>
<p>For example, text-based posts fall into two broad buckets: short <a href="https://indieweb.org/note">notes</a>, eg tweets and toots, and longer <a href="https://indieweb.org/article">articles</a>, eg blog posts. In the IndieWeb, <a href="https://indieweb.org/post-type-discovery#Algorithm">we differentiate based on whether the post has a title</a>: articles generally have titles, notes don't.
</p>
<p>Mastodon currently shows the full text of notes, but for articles, it only shows their titles and a link to the full article. This is because Mastodon and most other fediverse apps are designed primarily for smaller notes, not longer articles.
</li>
<li id="visible-links" class="question">What's up with the visible fed.brid.gy links in my fediverse posts?</li>
<li class="answer">
<p>These can happen for a couple reasons. For articles, this is expected behavior, <a href="#which-parts">as described above</a>. The link is a Bridgy Fed URL that redirects to the original post on your web site. This is <a href="https://github.com/mastodon/mastodon/pull/6219#issuecomment-429142747">because</a> Mastodon <a href="https://github.com/snarfed/bridgy-fed/issues/16#issuecomment-424799599">requires</a> ActivityPub (ie fediverse) object URLs to use the same domain that serves them, which in this case is fed.brid.gy. We know it's awkward; sorry for the ugliness!
</p>
<p>Otherwise, this may be the <a href="#how-post">invisible fed.brid.gy link that's required to trigger Bridgy Fed</a>. Mastodon will show a preview of links even if their text is blank, so if your link is inside your <code><a href="https://microformats.org/wiki/h-entry#Core_Properties">e-content</a></code> microformats2 element, that's probably what's happening. You can prevent that by moving it outside of <code>e-content</code>. It can go anywhere in your HTML!
</p>
</li>
<li id="reply" class="question">How do I reply to a fediverse post?</li>
<li class="answer">
<p>
Put the reply in a new post on your web site, and include a link to the fediverse post you're replying to with class <code><a href="http://microformats.org/wiki/rel-in-reply-to">u-in-reply-to</a></code>, as if you were publishing a normal <a href="https://indieweb.org/comment">IndieWeb reply</a>. For example:
<pre>&lt;div class="<span class='keyword'>h-entry</span>"&gt;
&lt;p class="<span class='keyword'>e-content</span>"&gt;<span class='value'>Highly entertaining. Please subscribe me to your newsletter.</span>&lt;/p&gt;
&lt;a class="<span class='keyword'>u-in-reply-to</span>" href="<a href='https://indieweb.social/@tchambers/109243684867780200'>https://indieweb.social/@tchambers/109243684867780200</a>"&gt;&lt;/a&gt;
&lt;a class="<span class='keyword'>u-bridgy-fed</span>" href="<a href='https://fed.brid.gy/'>https://fed.brid.gy/</a>" hidden="from-humans"&gt;&lt;/a&gt;
&lt;/div&gt;
</pre>
</p>
</li>
<li id="like" class="question">How do I favorite (aka like) or boost (aka repost) a fediverse post?</li>
<li class="answer">
<p>Favoriting and boosting are almost exactly the <a href="#reply">same as replying</a>. The only difference is that you use <code><a href="https://indieweb.org/like">u-like-of</a></code> for a favorite/like or <code><a href="https://indieweb.org/repost">u-repost-of</a></code> for a boost/repost.
<pre>
&lt;a class="<span class='keyword'>u-like-of</span>" href="<a href='https://indieweb.social/@tchambers/109374703563569354'>https://indieweb.social/@tchambers/109374703563569354</a>"&gt;&lt;/a&gt;
</pre>
<pre>
&lt;a class="<span class='keyword'>u-repost-of</span>" href="<a href='https://cosocial.ca/@evan/110290575042195305'>https://cosocial.ca/@evan/110290575042195305</a>"&gt;&lt;/a&gt;
</pre>
</p>
</li>
<li id="follow" class="question">How do I follow someone?</li>
<li class="answer">
<p>If your web site supports <a href="https://indieauth.net/" style="white-space: nowrap"><img src="/oauth_dropins_static/indieauth_logo.png" style="height: 1em; margin-top: -.2em; white-space: nowrap" /> IndieAuth</a>, <a href="/web-site">go to your user page</a>, click the <em>Following</em> link, then enter the address of the account you want to follow.
</p>
<p>You can also follow someone by posting an <a href="https://indieweb.org/follow#How_to_markup">IndieWeb follow</a> on your site, including the <code>u-follow-of</code> microformats2 class, and sending a webmention to Bridgy Fed. Your site may do that automatically if it supports webmentions. For example:
</p>
<pre>&lt;div class="<span class='keyword'>h-entry</span>"&gt;
I'm now following &lt;a class="<span class='keyword'>u-follow-of</span>" href="<a href='https://mastodon.social/@adactio'>https://mastodon.social/@adactio</a>"&gt;@adactio@mastodon.social&lt;/a&gt;!
&lt;a class="<span class='keyword'>u-bridgy-fed</span>" href="<a href='https://fed.brid.gy/'>https://fed.brid.gy/</a>" hidden="from-humans"&gt;&lt;/a&gt;
&lt;/div&gt;
</pre>
This method doesn't require IndieAuth, and it can be automated.</p>
</li>
<li id="unfollow" class="question">How do I unfollow someone?</li>
<li class="answer">
<p><a href="/web-site">Go to your user page</a>, click the <em>Following</em> link, find the account you want to unfollow, and click the X next to their address. Like <a href="#follow">following</a>, this requires your web site to support <a href="https://indieauth.net/" style="white-space: nowrap"><img src="/oauth_dropins_static/indieauth_logo.png" style="height: 1em; margin-top: -.2em; white-space: nowrap" /> IndieAuth</a>.
</p>
</li>
<li id="image" class="question">How do I include an image in a post?</li>
<li class="answer">
<p>
Use <code>&lt;img class="<span class='keyword'>u-photo</span>"&gt;</code> for the image in your post. For example:
<pre>
&lt;img class="<span class='keyword'>u-photo</span>" src="<span class='value'>/full_glass.jpg</span>" /&gt;
I love scotch. Scotchy scotchy scotch.
</pre>
</p>
</li>
<li id="hashtags" class="question">How do I use hashtags?</li>
<li class="answer">
<p>Use <code><span class='keyword'>p-category</span></code> and link the hashtag to a fully qualified URL. (Any URL you want!) Fediverse sites like Mastodon will generally rewrite the link to point to a search for that hashtag on the local instance. For example:
<pre>&lt;div class="<span class='keyword'>h-entry</span>"&gt;
&lt;p class="<span class='keyword'>e-content</span>"&gt;
chasing the fun laser
&lt;a href="<span class='value'>https://indieweb.social/tags/caturday</span>" class="<span class='keyword'>p-category</span>"&gt;<span class='value'>#caturday</span>&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
</pre>
</p>
<p>The leading <code>#</code> character on the hashtag text is optional. If you don't include the hashtag in <code>e-content</code>, or include it but not inside an <code>&lt;a&gt;</code> link, fediverse sites won't add the hashtag text or link themselves, but your post will still be indexed in searches for that hashtag.
</p>
</li>
<li id="mention" class="question">How do I @-mention someone?</li>
<li class="answer">
<p>Include a link to their fediverse profile in your post's content with their full handle as the text, eg <code>@adactio@mastodon.social</code>. For example:
</p>
<pre>
Hi &lt;a href="<a href='https://mastodon.social/@adactio'>https://mastodon.social/@adactio</a>"&gt;<span class='value'>@adactio@mastodon.social</span>&lt;/a&gt;!
</pre>
<p>The link and text are both necessary!</p>
</li>
<li id="update" class="question">How do I edit an existing post?</li>
<li class="answer">
<p>Edit the post on your web site, then send another webmention to Bridgy Fed for it. Bridgy Fed will refetch the post and send an <a href="https://www.w3.org/TR/activitypub/#update-activity-outbox"><code>Update</code> activity</a> for it to the fediverse.
</p>
</li>
<li id="delete" class="question">How do I delete a post?</li>
<li class="answer">
<p>First, delete the post on your web site, so that HTTP requests for it return 410 Gone or 404 Not Found. Then, send another webmention to Bridgy Fed for it. Bridgy Fed will refetch the post, see that it's gone, and send an <a href="https://www.w3.org/TR/activitypub/#delete-activity-outbox"><code>Delete</code> activity</a> for it to the fediverse.
</p>
</li>
<li id="fragment" class="question">Can I publish just one part of a page?</li>
<li class="answer">
<p>If that HTML element has its own id, then sure! Just put the id in the fragment of the URL that you publish. For example, to publish the <code>bar</code> post here:</p>
<pre>&lt;div id="<span class='value'>a</span>" class="<span class='keyword'>h-entry</span>"&gt;<span class='value'>foo</span>&lt;/div&gt;
&lt;div id="<span class='value'>b</span>" class="<span class='keyword'>h-entry</span>"&gt;<span class='value'>bar</span>&lt;/div&gt;
&lt;div id="<span class='value'>c</span>" class="<span class='keyword'>h-entry</span>"&gt;<span class='value'>baz</span>&lt;/div&gt;
</pre>
<p>...just add the id to your page's URL in a fragment, e.g. <code>http://site/post#b</code> here.</p>
</li>
<li id="backfeed" class="question">How do fediverse replies, likes, and other interactions show up on my site?</li>
<li class="answer">
<p>
To receive likes, reposts, replies, @-mentions, and follows from the fediverse, just make sure your site accepts <a href="https://webmention.net/">webmentions</a>! Bridgy Fed translates those interactions and sends them to your site as webmentions. The source URL will usually be a proxy page on <code>fed.brid.gy</code>. For best results, <a href="https://brid.gy/about#appspot">make sure your webmention handler detects and handles <code>u-url</code> links</a>.
</p>
</li>
<li id="read" class="question">How do I read my fediverse timeline/feed?</li>
<li class="answer">
<p><a href="#user-page">Your user page</a> has links to your fediverse timeline/feed, ie posts from people you follow, in HTML, Atom, and RSS formats. Add them to your feed <a href="https://indieweb.org/social_reader">reader</a> or read them in your browser!
</p>
</li>
<li id="notifications" class="question">Are there notifications?</li>
<li class="answer">
<p>Yes! <a href="#user-page">Your user page</a> has a feed of your notifications - mentions, replies, likes, reposts, follows, etc - in HTML, RSS, and Atom formats, which you can subscribe to in any <a href="https://indieweb.org/social_reader">reader</a>.
</p>
</li>
<li id="discovery" class="question">How can people on the fediverse find and follow me?</li>
<li class="answer">
<p>They can search for your web site in any Mastodon instance! Often you can just enter your domain, eg <code>yourdomain.com</code>, in any Mastodon search box. If that doesn't work, try your full fediverse address, eg <code>@yourdomain.com@yourdomain.com</code>. This can be finicky now and then, but it usually works.
</p>
<p><a href="#user-page">Your user page</a> has a "Following" link that shows you everyone on the fediverse who's currently following you. It also has a "remote follow" form that lets people enter their fediverse address and follow you directly.
</p>
</li>
<li id="see-posts" class="question">How can I see what my posts look like inside the fediverse?</li>
<li class="answer">
<p>This <a href="apps">varies by fediverse app</a>. For Mastodon, <a href="#currently+following_you">open your list of followers in Bridgy Fed</a> and click on one to open their profile. Then, inside that Mastodon instance, <a href="discovery">search for your site's address</a>, click on it in the search results, and you'll see your fediverse profile and all of your posts that were delivered to that instance. This may not be all of them, depending on how long and when people on that instance have been following you.</p>
<p>This general process should often work in other fediverse apps too.</p>
<p>Note: in Mastodon, each of your posts on a given instance will have a permalink inside that instance, eg <a href="https://mastodon.social/@snarfed.org@snarfed.org/109729052169033033">mastodon.social/@snarfed.org@snarfed.org/109729052169033033</a>, but those permalinks <em>only go to Mastodon if you're logged into that instance.</em> If you're not, they redirect to the original post on your site.
</p>
</li>
<li id="searchable" class="question">Can I make my posts show up when people search for them in the fediverse?</li>
<li class="answer">
<p>Yes! Add this line of HTML to each post that you publish with Bridgy Fed and want to be searchable, replacing <code>[URL]</code> with that post's URL:</p>
<pre>&lt;link rel="<span class='keyword'>alternate</span>" type="<span class='keyword'>application/activity+json</span>" href="<span class='value'>https://fed.brid.gy/r/[URL]</span>"&gt;
</pre>
<p><a href="https://docs.joinmastodon.org/user/network/#search">Search is intentionally limited in Mastodon and much of the overall fediverse</a>, so this won't index the full text of your posts, but it will make them show up in search results when you search for your post's full URL, which people commonly do in the fediverse to find and interact with posts.</p>
</li>
<li id="troubleshooting" class="question">I tried it, and it didn't work!</li>
<li class="answer">
<p><a href="#user-page">Check out your user page!</a> It detects and describes common problems with <a href="#setup">your setup</a>, and it shows your recent interactions and detailed logs.
</li>
<br>
<h3 id="about">About</h3>
<li id="who" class="question">Who are you? Why did you make this?</li>
<li class="answer">
<p>
I'm <a href="https://snarfed.org/">Ryan Barrett</a>. I'm just a guy who likes <a href="https://snarfed.org/2012-07-25_why_i_have_my_own_web_site">the web</a> and <a href="https://indieweb.org/why">owning my data</a>.
</p>
</li>
<li id="cost" class="question">How much does it cost?</li>
<li class="answer">
<p>Nothing! Bridgy Fed is small, and it doesn't cost much to run. We don't need donations, promise.
</p>
<p>If you <em>really</em> want to contribute, <a href="https://github.com/snarfed/bridgy-fed/issues">file an issue</a> or <a href="https://github.com/snarfed/bridgy-fed">send a pull request</a>, or <a href="https://opencollective.com/indieweb">donate to the IndieWeb</a>!
</p></li>
<li id="privacy" class="question">What do you do with my data?</li>
<li class="answer">
<p>Nothing! Bridgy Fed isn't a business, and never will be, so we don't have the same motivations to abuse your data that other services might. More concretely, Bridgy Fed won't ever send you email, it stores as little of your <a href="http://en.wikipedia.org/wiki/Personally_identifiable_information">PII</a> (personally identifiable information) as possible, and it <em>never</em> has access to any of your passwords.
</p>
</li>
<li id="history" class="question">How long has this been around?</li>
<li class="answer">
<p>I started thinking about bridging federated social networks and peer to peer networks when I discovered them in the early 2000s. I started talking about bridging them to the IndieWeb in 2016, <a href="http://indieweb.org/2017/ostatusbridge">led a session on it at IndieWeb Summit</a> in July 2017, wrote up <a href="https://snarfed.org/indieweb-activitypub-bridge">concrete</a> <a href="https://snarfed.org/indieweb-ostatus-bridge"> designs</a> soon after, started working on Bridgy Fed in August 2017, and <a href="https://snarfed.org/2017-10-22_bridgy-fed">launched it on October 22, 2017</a>.
</li>
<li id="terms" class="question">What are the terms of service?</li>
<li class="answer">
<p>Bridgy Fed's terms of service are very simple. You agree not to deliberately attack, breach, or otherwise harm the service. If you manage to access private keys or other private data, you agree to <a href="#vulnerability">report the vulnerability</a> and not use or disclose that data.
</p>
<p>Otherwise, you may use the service for any purpose you see fit. However, we may terminate or block your access for any reason, or no reason at all. (We've never done this, and we expect we never will. Just playing it safe.)
</p>
<p>Do you an administer an instance or other service that Bridgy Fed interacts with? If you have any concerns or questions, feel free to <a href="https://github.com/snarfed/bridgy-fed/issues">file an issue</a>!
</p>
</li>
<li id="bug" class="question">I found a bug! I have a feature request!</li>
<li class="answer">
<p>Great! Please <a href="https://github.com/snarfed/bridgy-fed/issues">file it in GitHub</a>. Thank you!
</p>
</li>
<li id="vulnerability" class="question">I found a security vulnerability!</li>
<li class="answer">
<p>Oof. Thank you for reporting it! Please send details to <a href="mailto:security@brid.gy">security@brid.gy</a>. We may provide monetary awards for reports of significant vulnerabilities, eg reading or modifying stored access tokens, <em>if</em> you follow these rules:</p>
<ul>
<li>Vulnerabilities must be in the application itself, not unrelated services like email (eg SPF/DKIM/DMARC).</li>
<li>Out of scope: rate limiting, XSS/CSRF attacks (Bridgy Fed has no authenticated sessions or private data accessible to users), <code>/admin/*</code> pages.
<li>Public user data is intentionally public. That's not a vulnerability.</li>
<li>No automated fuzzing, DoSes, or other high volume traffic. We block this traffic, and it will disqualify you from any possible award.</li>
</ul>
<p>Otherwise, <a href="https://github.com/snarfed/bridgy-fed/">the code is open source</a>, feel free to try to break in, let us know if you succeed!</p>
</li>
<br>
<h3 id="development">Development</h3>
<li id="compare" class="question">How do the different protocols compare?</li>
<li class="answer">
<p>Here's a table showing how they stack up on a number of factors. It's obviously oversimplified, but hopefully still right in spirit, focusing on how they're deployed and used in the real world. For example, <a href="https://www.w3.org/TR/activitypub/#obj-id">identity in ActivityPub is technically URL-based</a>, but in practice the fediverse uses <a href="https://webfinger.net/">WebFinger</a> <a href="https://datatracker.ietf.org/doc/html/rfc7565#section-4"><code>user@domain</code> identifiers</a> more or less universally, so the table reflects that.</p>
<p><a href="https://github.com/snarfed/bridgy-fed/issues">Feedback is welcome!</a></p>
<table>
<thead>
<tr>
<th></th>
<th>IndieWeb</th>
<th>ActivityPub + WebFinger</th>
<th>AT Protocol</th>
<th>Nostr</th>
</tr>
</thead>
<tbody>
<tr>
<th>user identity</th>
<td><a href="https://indieweb.org/personal-domain">DNS</a></td>
<td>username + DNS</td>
<td><a href="https://atproto.com/specs/did-plc"><code>did:plc</code></a>/<a href="https://w3c-ccg.github.io/did-method-web/"><code>did:web</code></a>,<br>
<a href="https://atproto.com/specs/handle">DNS handles</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">public key</a>,
<a href="https://github.com/nostr-protocol/nips/blob/master/05.md">DNS handles</a></td>
</tr>
<tr>
<th>object ids</th>
<td><a href="https://indieweb.org/permalink">URLs</a></td>
<td><a href="https://www.w3.org/TR/activitypub/#obj-id">URLs</a></td>
<td><a href="https://atproto.com/specs/at-uri-scheme"><code>at://</code> URIs</a>,<br><a href="https://atproto.com/specs/repository">data hashes</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">data hashes</a></td>
</tr>
<tr>
<th>data format</th>
<td><a href="https://microformats.org/wiki/microformats2">microformats2</a></td>
<td><a href="https://www.w3.org/TR/activitystreams-core/">ActivityStreams 2</a></td>
<td><a href="https://github.com/bluesky-social/atproto/tree/main/lexicons/app/bsky"><code>app.bsky</code> lexicons</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">Nostr events</a></td>
</tr>
<tr>
<th>serialization</th>
<td>HTML</td>
<td>JSON</td>
<td>JSON (<a href="https://atproto.com/specs/lexicon">Lexicon</a>)</td>
<td>JSON</td>
</tr>
<tr>
<th>delivery</th>
<td><a href="https://websub.net/">push</a>/<a href="https://indieweb.org/Microsub">pull</a> posts</a>,<br>
<a href="https://webmention.net/">push responses</a></td>
<td><a href="https://www.w3.org/TR/activitypub/#delivery">push</a></td>
<td><a href="https://blueskyweb.xyz/blog/5-5-2023-federation-architecture">pull</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#from-client-to-relay-sending-events-and-creating-subscriptions">pull</a></td>
</tr>
<tr>
<th>transport</th>
<td>HTTP</td>
<td><a href="https://www.w3.org/TR/activitypub/#retrieving-objects">HTTP</a></td>
<td>HTTP + <a href="https://atproto.com/specs/event-stream">WebSocket</a> (<a href="https://atproto.com/specs/xrpc">XRPC</a>)</td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#communication-between-clients-and-relays">WebSocket</a></td>
</tr>
<tr>
<th>topology</th>
<td>peer to peer</td>
<td><a href="">federated servers, two tier</a></td>
<td><a href="https://blueskyweb.xyz/blog/5-5-2023-federation-architecture">federated servers</a>,<br>
<a href="https://blueskyweb.xyz/blog/4-13-2023-moderation">decoupled</a> <a href="https://blueskyweb.xyz/blog/3-30-2023-algorithmic-choice">services</a>, multi-tier</td>
<td><a href="https://github.com/nostr-protocol/nostr#how-does-nostr-work">interchangeable relays,<br>two tier</a></td>
</tr>
<tr>
<th>security model</th>
<td>SSL, one user per domain</td>
<td><a href="https://www.w3.org/wiki/SocialCG/ActivityPub/Authentication_Authorization#Signing_requests_using_HTTP_Signatures">transport signatures,<br>
custodial keys</a></td>
<td><a href="https://atproto.com/specs/repository">data signatures</a>,<br>
<a href="https://atproto.com/guides/overview#account-portability">custodial + user-owned keys</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">data signatures,<br>
user-owned keys</a></td>
</tr>
<tr>
<th>app semantics live in...</th>
<td>servers, clients</td>
<td>servers, clients</td>
<td><a href="https://blueskyweb.xyz/blog/5-5-2023-federation-architecture">dedicated service</a>, clients</td>
<td>clients</td>
</tr>
<tr>
<th>blockchain</th>
<td>no</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<th>monetization</th>
<td><a href="https://indieweb.org/business-models">hosting</a></td>
<td>donations</td>
<td><a href="https://blueskyweb.xyz/blog/7-05-2023-business-plan">services</a></td>
<td><a href="https://nostr.how/en/zaps">microtransactions</a></td>
</tr>
<tr>
<th>active user estimates<br>
(as of 2023-09-04)</th>
<td>
<!-- <a href="https://indiemap.org/">2k</a>, <a href="https://w3techs.com/technologies/overview/content_management">43M</a><br> -->
<a href="https://indiemap.org/docs.html#sites">not well defined</a></td>
<td><a href="https://fedidb.org/">1.6M</a>, <a href="https://fediverse.observer/stats#user_growth_active">2M</a>, <a href="https://the-federation.info/">2.7M</a></td>
<td><a href="https://discord.com/channels/1097580399187738645/1097580399187738648/1143696514825326685">360k</a> (still invite-only)</td>
<td><a href="https://stats.nostr.band/#weekly_active_users">25k</a>, <a href="https://stats.nostr.band/">100k</a></a></td>
</tr>
<tr>
<th>server estimates<br>
(as of 2023-09-04)</th>
<td><a href="https://indiemap.org/docs.html#sites">not well defined</a></td>
<td><a href="https://fediverse.observer/stats#pod_growth">23k</a>, <a href="https://fedidb.org/">25k</a>, <a href="https://the-federation.info/">26k</a></td>
<td>1</td>
<td><a href="https://nostr.watch/relays/statistics">170</a>, <a href="https://stats.nostr.band/">1800</a></td>
</tr>
<tr>
<th>governance</th>
<td><a href="https://indieweb.org/">IndieWeb</a> <a href="https://www.oscollective.org/">non-profit</a>,<br>
<a href="https://www.w3.org/community/socialcg/">some W3C</a></td>
<td><a href="https://socialhub.activitypub.rocks/t/about-the-fediverse-enhancement-proposals/1168">FEPs</a>, <a href="https://www.w3.org/community/socialcg/">some W3C</a></td>
<td><a href="https://blueskyweb.xyz/blog/7-05-2023-business-plan">Bluesky C-corp now</a>,<br>
<a href="https://blue.amazingca.dev/user/did:plc:44ybard66vv44zksje25o7dz/post/3k3p6upex4x2l">IETF eventually?</a></td>
<td><a href="https://fiatjaf.com/">mildly BDFL(s) now</a>,<br>
<a href="https://github.com/nostr-protocol/nips/issues/162">decentralized eventually?</a></td>
</tr>
</tbody>
</table>
</li>
<li id="translate" class="question">How are the different protocols translated?</li>
<li class="answer">
<p>Here are internal details on how Bridgy Fed translates user identity and events between protocols, including some like <a href="https://github.com/nostr-protocol/nostr">Nostr</a> and <a href="https://blueskyweb.xyz/">Bluesky</a>/<a href="https://atproto.com/">AT Protocol</a> that aren't launched here, or even fully implemented or thought through yet. Caveat hacker!</p>
<p>In the tables below, BF is Bridgy Fed. <span class="done">Green parts</span> have been implemented and running here for years, the rest are still in the early design phase.</p>
<p>Here's how we (hope to) translate <em>user identity</em> between protocols. Specifically, each cell shows how a user in a given column is identified to the protocol in a given row. These identities uniquely identify users, and are intended primarily to be machine readable and usable. (Scroll down for the equivalent table for translating human-meaningful user handles.)</p>
<p>Note that Bridgy Fed generates some of these ids itself behind the scenes, notably <a href="https://atproto.com/specs/did-plc"><code>did:plc</code>s</a> for Bluesky/AT Protocol and <a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a></code> public keys</a> for Nostr.</p>
<table>
<thead>
<tr>
<th></th>
<th>Web</th>
<th>ActivityPub</th>
<th>AT Protocol</th>
<th>Nostr</th>
</tr>
</thead>
<tbody>
<tr>
<th>Web URL</th>
<td class="na">-</td>
<td class="done">Fediverse profile URL</td>
<td><code>https://bsky.app/profile/[<a href="https://atproto.com/specs/did">did</a>]</code><br>
(<a href="https://github.com/bluesky-social/atproto/discussions/1652">can we avoid hard-coding bsky.app?</a>)</td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> domain or BF user page</td>
</tr>
<tr>
<th>WebFinger <a href="https://docs.joinmastodon.org/user/signup/#address">address</a></th>
<td><code>@[domain]@web.brid.gy</code></td>
<td class="na">-</td>
<td><code>@[<a href="https://atproto.com/specs/handle">handle</a>]@bsky.brid.gy</code></td>
<td><code>@[<a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> or <a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a>]@nostr.brid.gy</code></td>
</tr>
<tr>
<th>ActivityPub <a href="https://www.w3.org/TR/activitypub/#actors">actor</a></th>
<td><code>https://web.brid.gy/ap/[domain]</code></td>
<td class="na">-</td>
<td><code>https://bsky.brid.gy/ap/[<a href="https://atproto.com/specs/did">did</a>]</code></td>
<td><code>https://nostr.brid.gy/ap/[<a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a>]</code></td>
</tr>
<tr>
<th>AT Protocol</th>
<td><a href="https://atproto.com/specs/did-plc"><code>did:plc</code></a></td>
<td><a href="https://atproto.com/specs/did-plc"><code>did:plc</code></a></td>
<td class="na">-</td>
<td><a href="https://atproto.com/specs/did-plc"><code>did:plc</code></a></td>
</tr>
<tr>
<th>Nostr</th>
<td><code><a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a></code></td>
<td><code><a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a></code></td>
<td><code><a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a></code></td>
<td class="na">-</td>
</tr>
</tbody>
</table>
<p>Here's how we (hope to) translate <em>user handles</em> (aka usernames) between protocols. Each cell shows how a user's handle in a given column is translated to the protocol in a given row. These handles are human-chosen, human-meaningful, generally unique, but may not be the primary machine-usable ids in each protocol. Scroll down to the next table for examples, up to the previous table for machine-usable ids.</p>
<p><em>Basic</em> is the default, <em>enhanced</em> requires extra setup on the user's part (or their fediverse instance's) to forward some of their <code>/.well-known</code> HTTP requests to Bridgy Fed.</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th>Web</th>
<th>ActivityPub</th>
<th>AT Protocol</th>
<th>Nostr</th>
</tr>
</thead>
<tbody>
<tr>
<th>Web</th>
<th></th>
<td class="na">-</td>
<td class="done">Fediverse profile URL</td>
<td>bare <a href="https://atproto.com/specs/handle">handle</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> domain or BF user page</td>
</tr>
<tr>
<th rowspan="2">AP <a href="https://docs.joinmastodon.org/user/signup/#address">address</a></th>
<th class="subhead">basic</th>
<td><code>@[domain]@web.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
<td><code>@[<a href="https://atproto.com/specs/handle">handle</a>]@bsky.brid.gy</code></td>
<td><code>@[<a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> or <a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a>]@nostr.brid.gy</code></td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td class="done"><code>@[domain]@[domain]</code></td>
<td><code>@[<a href="https://atproto.com/specs/handle">handle</a>]@[<a href="https://atproto.com/specs/handle">handle</a>]</code></td>
<td><code>@[<a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a>]</code></td>
</tr>
<tr>
<th rowspan="2">ATP <a href="https://atproto.com/specs/handle">handle</a></th>
<th class="subhead">basic</th>
<td><code>[domain].web.brid.gy</code></td>
<td><code>[username].[instance].ap.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
<td><code>[<a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> or <a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids">npub</a>].nostr.brid.gy</code><br>
(convert <code>@</code> to <code>.</code>)</td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td>bare domain</td>
<td><code>[username].[instance]</code> domain</td>
<td>bare <a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> domain<br>
(<code>_</code> username)</td>
</tr>
<tr>
<th rowspan="2">Nostr <a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> domain</th>
<th class="subhead">basic</th>
<td><code>[domain]@web.brid.gy</code></td>
<td><code>[username].[instance]@ap.brid.gy</code></td>
<td><code>[<a href="https://atproto.com/specs/handle">handle</a>]@bsky.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td>bare domain</td>
<td><code>[username]@[instance]</code></td>
<td>bare <a href="https://atproto.com/specs/handle0">handle</a></td>
</tr>
</tbody>
</table>
<p>Here are concrete examples:</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th>Web<br><code>me.com</code></th>
<th>ActivityPub<br><code>@me@instance.com</code></th>
<th>AT Protocol<br><code>me.com</code></th>
<th>Nostr<br><code>me@domain.com</code><br><code>[_@]me.com</code></th>
</tr>
</thead>
<tbody>
<tr>
<th>Web</th>
<th></th>
<td class="na">-</td>
<td class="done"><code>https://instance.com/@me</code><br>
(varies by instance)</td>
<td><code>me.com</code></td>
<td>?<br><code>me.com</code></td>
</tr>
<tr>
<th rowspan="2">ActivityPub</th>
<th class="subhead">basic</th>
<td><code>@me.com@web.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
<td><code>@me.com@bsky.brid.gy</code></td>
<td><code>@me[domain.]com@nostr.brid.gy</code></td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td class="done"><code>@me.com@me.com</code></td>
<td><code>@me.com@me.com</code></td>
<td><code>@me@domain.com</code><br>
<code>@me.com@me.com</code></td>
</tr>
<tr>
<th rowspan="2">AT Protocol</th>
<th class="subhead">basic</th>
<td><code>me.com.web.brid.gy</code></td>
<td><code>me.instance.com.ap.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
<td><code>me.[domain.]com.nostr.brid.gy</code></td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td><code>me.com</code></td>
<td><code>me.instance.com</code></td>
<td><code>me.[domain.]com</code></td>
</tr>
<tr>
<th rowspan="2">Nostr</th>
<th class="subhead">basic</th>
<td><code>me.com@web.brid.gy</code></td>
<td><code>me.instance.com@ap.brid.gy</code></td>
<td><code>me.com@bsky.brid.gy</code></td>
<td rowspan="2" class="na">-</td>
</tr>
<tr>
<th class="subhead">enhanced</th>
<td><code>[_@]me.com</code></td>
<td><code>[_@]me.instance.com</code></td>
<td><code>[_@]me.com</code></td>
</tr>
</tbody>
</table>
<p>Here's how we (hope to) infer the protocol for any string id. In the Format column, <span class="yes">green parts</span> are deterministic, ie they conclusively determine that a matching id belongs to the protocol, and <span class="maybe">yellow parts</span> are ambiguous, ie a matching id may or may not belong to the protocol:
</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th>Example(s)</th>
<th>Format</th>
<th>Network discovery</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="2">Web</th>
<th class="subhead">user</th>
<td><a href="https://snarfed.org/">https://snarfed.org/</a></td>
<td class="maybe">http(s) URL with empty path</td>
<td rowspan="2"><code>HTTP GET</code> succeeds and returns HTML</td>
</tr>
<tr>
<th class="subhead">object</th>
<td><a href="https://snarfed.org/2023-05-26_50328">https://snarfed.org/2023-05-26_50328</a></td>
<td class="maybe">http(s) URL with non-empty path</td>
</tr>
<tr>
<th rowspan="2">ActivityPub</th>
<th class="subhead">user</th>
<td><a href="https://indieweb.social/users/snarfed">https://indieweb.social/users/snarfed</a></td>
<td rowspan="2" class="maybe">http(s) URL</td>
<td><code>HTTP GET</code> <a href="https://www.w3.org/TR/activitypub/#retrieving-objects">with AS2 conneg</a> returns valid AS2 with <a href="https://www.w3.org/TR/activitystreams-core/#actors"><code>Actor type</code></a></td>
</tr>
<tr>
<th class="subhead">object</th>
<td><a href="https://mitra.social/post/01885fad-85ee-c6c3-191e-0a4f132c8113">https://mitra.social/post/01885fad</a></td>
<td><code>HTTP GET</code> <a href="https://www.w3.org/TR/activitypub/#retrieving-objects">with AS2 conneg</a> returns valid AS2 with <a href="https://www.w3.org/TR/activitystreams-core/#actors"><code>non-Actor type</code></a></td>
</tr>
<tr>
<th rowspan="2">AT Protocol</th>
<th class="subhead">user</th>
<td>
<code>did:plc:abc123</code><br>
<code>did:web:snarfed.org</code>
</td>
<td class="yes"><a href="https://atproto.com/specs/did-plc"><code>did:plc</code></a> or <a href="https://w3c-ccg.github.io/did-method-web/"><code>did:web:</code></a> prefix<br>
<nobr>(TODO: <a href="https://atproto.com/specs/handle">domain handles</a>)</nobr>
</td>
<td>
<a href="">resolve <code>did:plc</code></a>,<br>
<a href="https://w3c-ccg.github.io/did-method-web/#read-resolve">resolve <code>did:web</code></a>
</td>
</tr>
<tr>
<th class="subhead">object</th>
<td><code>at://did:plc:asdf/post/abc-123</code></td>
<td class="yes"><a href="https://atproto.com/specs/at-uri-scheme"><code>at://</code> URI</a></td>
<td><a href="https://github.com/snarfed/atproto/blob/main/lexicons/com/atproto/repo/getRecord.json"><code>com.atproto.repo.getRecord</code></a> XRPC</td>
</tr>
<tr>
<th rowspan="2">Nostr</th>
<th class="subhead">user</th>
<td>
<code>abc123...</code> (<a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">32 chars</a>)<br>
<code>npub10hx886...</code> (<a href="https://github.com/nostr-protocol/nips/blob/master/19.md">bech32</a>)
</td>
<td>
<span class="maybe">32 char hex</span> or
<a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids" class="yes"><code>npub</code> prefix</a>
<nobr>(TODO: <a href="https://github.com/nostr-protocol/nips/blob/master/05.md">NIP-05</a> domains)</nobr>
</td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/65.md">NIP-65</a> or <a href="https://github.com/nostr-protocol/nips/blob/master/39.md">NIP-39</a> lookup</td>
</tr>
<tr>
<th class="subhead">object</th>
<td>
<code>def456...</code> (<a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">32 chars</a>)<br>
<code>nevent10hx886...</code> (<a href="https://github.com/nostr-protocol/nips/blob/master/19.md">bech32</a>)<br>
<code>note10hx886...</code> (<a href="https://github.com/nostr-protocol/nips/blob/master/19.md">bech32</a>)
</td>
<td>
<span class="maybe">32 char hex</span> or
<a href="https://github.com/nostr-protocol/nips/blob/master/19.md#bare-keys-and-ids" class="yes"><code>nevent</code>, <code>note</code>, etc</a> prefix</a>
</td>
<td><code><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#from-client-to-relay-sending-events-and-creating-subscriptions">REQ</a></code> request</td>
</tr>
</tbody>
</table>
<p>Here's how we (hope to) translate <em>events and operations</em> between protocols, both inbound to and outbound from Bridgy Fed:
</p>
<table>
<thead>
<tr>
<th></th>
<th>Web</th>
<th>ActivityPub</th>
<th>AT Protocol</th>
<th>Nostr</th>
</tr>
</thead>
<tbody>
<tr>
<th>User discovery inbound</th>
<td>serve <code><a href="https://microformats.org/wiki/h-card">h-card</a></code> on BF user page</td>
<td class="done"><em>basic</em>: serve <a href="https://webfinger.net/">WebFinger</a> and <a href="https://www.w3.org/TR/activitypub/#actors">AP actor</a> on fed.brid.gy<br>
<em>enhanced</em>: user's site serves and redirects <a href="https://webfinger.net/">WebFinger</a> to fed.brid.gy
</td>
<td>resolve <a href="https://www.w3.org/TR/did-core/">DID</a>, serve DID document with fed.brid.gy <a href="https://atproto.com/guides/data-repos">PDS</a></td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/39.md">NIP-39</a> (kind 0) query to BF (or other?) relay</td>
</tr>
<tr>
<th>User discovery outbound</th>
<td class="done">Fetch home page, parse <code><a href="https://microformats.org/wiki/h-card">h-card</a></code></td>
<td class="done">look up <a href="https://webfinger.net/">WebFinger</a>, fetch <a href="https://www.w3.org/TR/activitypub/#actors">AP actor</a></td>
<td>resolve <a href="https://www.w3.org/TR/did-core/">DID</a>, subscribe to <a href="https://atproto.com/guides/data-repos">PDS</a> repo, extract profile object?</td>
<td>discover user's relays with <a href="https://github.com/nostr-protocol/nips/blob/master/65.md">NIP-65</a>, query <a href="https://github.com/nostr-protocol/nips/blob/master/39.md">NIP-39</a> to get profile</td>
</tr>
<tr>
<th>Publish inbound</th>
<td class="done"><a href="https://webmention.net/">webmention</a> to fed.brid.gy</td>
<td class="done">deliver to fed.brid.gy <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a>, user or shared</td>
<td>subscribe to user's <a href="https://atproto.com/guides/data-repos">PDS</a> repo on fed.brid.gy</td>
<td>publish <a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">event</a> to BF relay</td>
</tr>
<tr>
<th>Publish outbound</th>
<td class="done">serve on BF user page followings <code><a href="https://microformats.org/wiki/h-feed">h-feed</a></code></td>
<td class="done">deliver to recipient's <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a></td>
<td>serve repo diff via <a href="https://atproto.com/lexicons/com-atproto-sync"><code>sync</code> XRPCs</a> to subscribing <a href="https://blueskyweb.xyz/blog/5-5-2023-federation-architecture">BGSes</a></td>
<td>serve to subscribers</td>
</tr>
<tr>
<th>Follow inbound</th>
<td class="done"><em>users</em>: UI on BF user page<br>
<em>code</em>: <a href="https://webmention.net/">webmention</a> with <code><a href="https://indieweb.org/follow#How_to_publish">u-follow-of</a></code></td>
<td class="done"><code><a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow">Follow</a></code> activity delivered to BF user <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a></td>
<td>receive <code><a href="https://atproto.com/lexicons/com-atproto-sync#comatprotosyncsubscriberepos">sync.subscribeRepos</a></code>?</td>
<td>user's client sends <code><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#from-client-to-relay-sending-events-and-creating-subscriptions">REQ</a></code> to BF relay</td>
</tr>
<tr>
<th>Follow outbound</th>
<td class="done"><a href="https://webmention.net/">webmention</a> with BF proxy HTML page as source</td>
<td class="done">deliver <code><a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow">Follow</a></code> to followee's <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a></td>
<td>call <code><a href="https://atproto.com/lexicons/com-atproto-sync#comatprotosyncsubscriberepos">sync.subscribeRepos</a></code> on followee's <a href="https://atproto.com/guides/data-repos">PDS</a>?</td>
<td>discover followee's relay(s) with <a href="https://github.com/nostr-protocol/nips/blob/master/65.md">NIP-65</a>, send them a <code><a href="https://github.com/nostr-protocol/nips/blob/master/01.md#from-client-to-relay-sending-events-and-creating-subscriptions">REQ</a></code></td>
</tr>
<tr>
<th>Response inbound</th>
<td class="done"><a href="https://webmention.net/">webmention</a> to a BF proxy page</td>
<td class="done"><code><a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create">Create</a></code>, <code><a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like">Like</a></code>, <code><a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce">Announce</a></code> delivered to BF user <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a></td>
<td>response object received from a subscribed repo?<br>
(what if it's from a user we don't subscribe to?)</td>
<td><a href="https://github.com/nostr-protocol/nips/blob/master/10.md">NIP-10</a> response <a href="https://github.com/nostr-protocol/nips/blob/master/01.md#events-and-signatures">event</a> received at BF relay or other relay</td>
</tr>
<tr>
<th>Response outbound</th>
<td colspan="4">same as follow outbound, with the corresponding response data type</td>
</tr>
</tbody>
</table>
</li>
<li id="router" class="question">How are activities routed?</li>
<li class="answer">
<p>A bridge does more than just translate protocols and formats. It processes activities (events) based on domain-specific logic and semantics. The domain Bridgy Fed currently handles is public social microblogging, the kind popularized by Twitter. There are many other related social domains, with fuzzy boundaries and lots of overlap, eg forums (Reddit), questions and answers (StackOverflow), project trackers (GitHub), and many more, but here we're currently focused on microblogging.</p>
<p>Even within that domain, behavior logic varies. Twitter follows are one way, but Facebook friends are bidirectional. Your Bluesky timeline (skyline) includes your followings' replies, but your fediverse timeline generally doesn't. LinkedIn...honestly I have no clue how LinkedIn works, but I'm sure it has its own logic, workfluencers and all.</p>
<p>Here's what Bridgy Fed's activity router does. I've tried to make it follow "least common denominator" logic, ie do the most common and least surprising thing, and I've explicitly tried not to innovate or invent anything new here. It's a bridge, not a product, after all.</p>
<table class="list">
<thead>
<tr>
<th>When Bridgy Fed receives a...</th>
<th>The router will...</th>
</tr>
</thead>
<tbody>
<tr>
<th>follow</th>
<td><ul>
<li>deliver the follow activity to the followee</li>
<li>automatically send an accept activity to the follower<br>
(we may eventually add UX for this)</li>
<li>store the follower locally</li>
<li>generate a local notification to the follower</li>
</ul></td>
</tr>
<tr>
<th>unfollow</th>
<td><ul>
<li>deliver the unfollow activity to the followee</li>
<li>deactivate the locally stored follower</li>
</ul></td>
</tr>
<tr>
<th>new post</th>
<td><ul>
<li>deliver to all active stored followers</li>
<li>store the post locally</li>
</ul></td>
</tr>
<tr>
<th>update post</th>
<td><ul>
<li>deliver to all active stored followers</li>
<li>update the locally stored post</li>
</ul></td>
</tr>
<tr>
<th>delete post</th>
<td><ul>
<li>deliver to all active stored followers</li>
<li>mark the locally stored post deleted</li>
</ul></td>
</tr>
<tr>
<th>delete actor</th>
<td><ul>
<li>deactivate their locally stored follows, to and from</li>
</ul></td>
</tr>
<tr>
<th>reply</th>
<td><ul>
<li>deliver to the original post</li>
<li>store locally</li>
<li>generate a local notification to the original post's author</li>
</ul></td>
</tr>
<tr>
<th>repost</th>
<td><ul>
<li>deliver to all active stored followers</li>
<li>store locally</li>
<li>generate a local notification to the original post's author</li>
</ul></td>
</tr>
<tr>
<th>like</th>
<td><ul>
<li>deliver to the original post</li>
<li>generate a local notification to the original post's author</li>
</ul></td>
</tr>
</tbody>
</table>
</li>
<li id="error-handling" class="question">How are errors handled?</li>
<li class="answer">
<p>"It's complicated." ...well, at least a bit. There are different philosophies on how to architect request handling and error propagation in these kinds of server-to-server protocols.
</p>
<p>One common bit of received wisdom is to handle all requests asynchronously, in the background. Do minimal request validation synchronously, if necessary, then return HTTP 202 (or 201) and enqueue the request in a background task queue to be processed offline. This is widespread in ActivityPub implementations, for example. Webmention even <a href="https://webmention.net/draft/#receiving-webmentions">recommends it as a SHOULD</a>!
</p>
<blockquote>
Upon receipt of a POST request containing the source and target parameters, the receiver SHOULD verify the parameters (see Request Verification below) and then SHOULD queue and process the request asynchronously, to prevent DoS attacks.
</blockquote>
<p>It's a good idea, but it has drawbacks. Most importantly, it hides errors. Sending side implementations always receive HTTP 202 responses, even when their requests fail in the background, and there's no standard or widely implemented way to get more information or debug. Webmention nods to this and says <a href="https://webmention.net/draft/#receiving-webmentions">receivers can return a per-request status URL in the <code>Location</code> response header</a>, but that's not widely implemented, and ActivityPub has no corresponding mechanism. This makes development and interop materially harder, especially in these protocols' loosely connected ecosystems. <a href="https://github.com/mastodon/mastodon/issues">Mastodon's issue tracker</a>, for example, is full of issues complaining "Mastodon isn't working with my code, but I can't tell why!"
</p>
<p>Bridgy Fed currently takes a compromise position. It handles most requests synchronously, blocks on delivering them to the destination protocol, and propagates any errors back to the sender with the appropriate HTTP response status code and body (often JSON). Delivering posts to ActivityPub followers is one exception; it currently delivers to inboxes serially, so it often takes many minutes, which is uncomfortably long for many HTTP clients.
</p>
<p>Converting to webmention is another exception. Bridgy Fed uses webmentions and microformats2 to provide social interactions for web sites, but unlike with other protocols, it doesn't require web sites to support them. So, Bridgy Fed doesn't currently convert webmention failures (or lack of support) to errors in other protocols. It records those failures, and shows them in the UI on your user page, but returns success to the sending side in its own protocol.
</p>
</li>
</ul>
</div>
{% endblock %}