Static file ActivityPub

I’ve been researching ActivityPub a lot recently and have been trying to figure out ways to make it easier to adopt, safer to operate, and better at scaling and the conclusion I’ve come to is there needs to be a way to adapt the protocol to be static file friendly.

Right now if I want to host any service that uses ActivityPub (eg mastodon) I have to run a server that can accept and respond to POST requests and URL parameters. This a fine for some use cases but will not scale to broad adoption for many potential adopters.

Most people don’t know how to run a server and of the people that do even fewer know how to secure a server. This is a potential liability for any service using AcivityPub. The first major CVE that happens in Mastodon is going to have huge reputation impact as thousands of servers aren’t updated. We’ve seen this over and over with things like Wordpress and others.

The existing servers don’t scale to millions of users or followers. The amount of scaling you need to do to handle that amount of requests costs too much in processing power to make it feasible for any individual or company to want to take on that burden.

Governments and large companies that want to use this for announcements and news would have a hard time maintaining and scaling to the number of subscribers. The complexity of the server components also means it is more likely to have outages and be unavailable. Identity keys being stored with servers is also concerning because of the potential of impersonation if those keys are extracted. Companies and governments will likely have higher standards for how their keys are stored (offline or in hardware).

How can I propose additions to the ActivityPub protocol to make it 100% static file hosting friendly? The most reliable, cheapest, and fastest way to serve content on the internet is with static files and ActivityPub needs to support that hosting option if it is going to reach the scale of public adoption.

This might change some of the applications built on top of ActivityPub, but they can adopt the new protocol options over time.

I recently wrote this blog post as I was discovering what is possible. If I want to continue building it I have to create at minimum an active endpoint for inbox and a way to POST messages to followers’ inboxes.

I would love to help make the protocol more sustainable for the future, but I haven’t found any information on how that can be proposed.


The whole goal of ActivityPub is to support real-time interaction using a pubsub model. That was the fundamental design goal from day 1. There are other protocols that rely on crawling for distribution, like Atom, RSS and indieweb protocols (microformats).

That said, the goal of self-hosted static files with a semi-centralized “aggregator” to handle subscription and publishing was also part of the goal. It’s not something Mastodon has explored, but if you’re interested in static file hosting, that’s the direction i’d start looking in—self-hosted static content, but a trusted service for aggregating likes / follows / replies.

1 Like

Extensions to the protocol are usually proposed as Fediverse Enhancement Proposals (FEPs):

And this forum has a special category for discussing standards: Standards - SocialHub

1 Like

Mastodon could support pointing those dynamic URLs (inbox, outbox, following…) to another server.

That’s what I would want too. I’d host the identity file myself, but someone who cares about running servers would do the dynamic parts.

Going fully static of course is not possible, as point is pub/sub.

Governments and large companies that want to use this for announcements and news would have a hard time maintaining and scaling to the number of subscribers. The complexity of the server components also means it is more likely to have outages and be unavailable. Identity keys being stored with servers is also concerning because of the potential of impersonation if those keys are extracted. Companies and governments will likely have higher standards for how their keys are stored (offline or in hardware).

Sounds like you’d like to be able to follow RSS feeds, there is proposal for that: Allow Following RSS · Issue #15350 · mastodon/mastodon · GitHub

I would like that too, so one could like, boost and reply to RSS feed items.

What makes you think it doesn’t?

Does it work by default? I have an account in e.g. “” could I take this:

Store it on my servers and have but still use as my inbox/outbox/following/UI etc?

I don’t think it supports it by default.

There is another problem too, I don’t think I can get that private key in to myself.

I aim for a static reading experience plus single-user publishing cgi.

Will start Jan 2023, follow at

P.S.: protocol improvements, especially concerning sustainability, are in dire need but I doubt they have a chance.

Thanks for that clarification about the initial goals. Right now (at least with Mastodon) the real-time portion of the network is done through websockets but that is an optional implementation for a server. Do you know if that is required with other apps built on top of ActivityPub or if it will increasingly be a requirement in the future?

My attempts to make it more static file friendly may not be make sense if real time data exchange is a desired goal of the protocol.

Yes, you can point your inbox to any URL and you could still control the outbox (static file) but you would also be responsible for POSTing your outbox items to your followers.

Not being able to extract your user keys would be the biggest problem because you couldn’t sign your posts, but as far as I can tell post signatures aren’t verified anyway so it wouldn’t matter until servers do verification.

1 Like

@jgarr You don’t have to post anything to your followers.

There is even clients that post some messages to some followers and some to others. One instance has made a feature out of this, called circles, e.g. does that.

You could add all your messages to just your outbox only, I think these would be fetched if someone views your profile, but it wouldn’t appear as shoved to other people’s inboxes.

I think for corporation like Apple which doesn’t really interact with its listeners, it would suit them. They could have fake followers, and release public messages just in outbox.

People could still boost, reply and favorite their messages just fine.

Mastodon doesn’t actually work that way. Outboxes aren’t fetched when a user is searched and mastodon doesn’t pull old posts (see my blog post). When you search for my static user you won’t see any posts even though the user has one.

Boosts and replies won’t work either because it requires the /inbox to handle those requests and increment the post mestadata

I can lie about how many boosts and replies my posts have because mastodon doesn’t verify any of the metadata (see my post where I have a million followers)

1 Like

You can boost, reply and view other people’s posts even if you don’t follow them. A lot of clients support that. I know that web client just show the link “Show older posts in the original link”, but you can boost older posts by putting them in to search bar.

I’m not talking about “counts”, I know they can be false, but who cares.

The official client could support viewing older posts as well, it’s an ideological decision that they don’t.

Mastodon does not automatically fetch the outbox, but once a message is searched on the instance, the message is shown under that user’s profile. On the case of your blog, Justin, from what I can see is not returning a proper object, it’s at least missing the @context. I’m trying to make a simple ActivityPub implementation for my bots and I can already see their messages once I search for them. It’s obviously not ideal and not what you are looking for, but in theory, looking for any of the URLs returned on your /toots endpoint (only one atm) should make the post appear, not only on your profile, but also on the federated timeline of the instance where they are searched.

1 Like

I would love to see AP servers drive two changes to make it easier for static files-based sites to integrate in Fediverse:

  • For WebFinger lookup, use /.well-known/webfinger/acct/domain/username.json before /.well-known/webfinger?resource=acct:username@domain
  • If an actor does not provide an inbox URL, interpret it to mean that it cannot receive Follow events and therefore, cannot push posts to its followers. In such case, the follower’s AP server should switch to periodic pulls like RSS feed readers.

With these two changes, software like Hugo or Jekyll can easily build ActivityPub feeds for static blogs. Crucially, I think both these are enhancements and do not require breaking the ActivityPub spec. They can be standardized AFTER these are widely adopted.

1 Like
  • the 1st would be a violation of the webfinger spec; you need to take a query parameter and respond with application/jrd+json and a valid JRD as described in the webfinger rfc.

  • the 2nd would be technically possible but would violate a guarantee on the definition of an “actor” (an object with inbox + outbox).

however, i would also point out that activitypub is not intended to be a “feed reader” or syndication protocol. it is a message passing protocol. if you wish to publish a feed then something like RSS is far more suited to this use-case.

indeed, an activitypub Server does not generally have a concept of “periodic pulls”; it would be the activitypub Client that would have to do this, and if you imagine an activitypub feed-reader client then you naturally have to wonder how that differs from an RSS feed-reader.

also, if you don’t have an inbox, then you will find that activitypub as a whole is entirely useless, as you will not be able to receive any messages. what is the point?

what you could do is to generate ActivityStreams 2.0 documents that live at the same URL (perhaps with a .json appended, if you can’t do content negotiation for Accept: application/ld+json; profile="" as you are required to do for ActivityPub). This would still require you to generate an actor and a webfinger JRD, though. at least the actor can be static (if your consumers don’t check for content-type), and the webfinger can probably be static too if you don’t care to serve multiple actors (again, if your consumers don’t check for content-type).

however, it would be better to just have a dedicated service handle this for you – asking for “static activitypub” is like asking for “static email” or “static webmentions”. you can’t statically respond to what is fundamentally a dynamic request.


I want my static blog to be consumable within Fediverse. That means AP users should be able to read my posts, see my profile/bio, reply/like/boost the posts - even if the replies can’t be sent to me. I agree that all this can be achived by implementing this but that seems like a more complex undertaking than the changes I suggested.

The WebFinger spec excludes all static websites of the whole world wide web. So, I think it’s fair to challenge the spec itself. But I think this specific change can be implemented by WebFinger users like Mastodon in a backward-compatible way.

Asking me to use a dedicated service is not ideal because as a non-technical user, this forces me to trust an intermediary which leads to abuse of power by holding my identity, reputation and audience hostage.

it would be easier for fediverse software to consume RSS than it would be for you to implement even a minimal ActivityPub presence in a purely static environment. as stated before, activitypub is a dynamic protocol like email or webmentions. requests must be handled by process calls.

if you find it unpalatable to trust an intermediary then the fediverse is frankly not a good idea. the entire concept of federation is built on trusting your service provider.

i can only point you to tools like GitHub - dariusk/rss-to-activitypub: An RSS to ActivityPub converter. or guides like Adding ActivityPub to your static site or s3lph made - How much ActivityPub can a Static Site Generator implement?


I intend to use webserver URL rewriting as a workaround.

Edit: actually I do that for

FYI just bumped into:


If your main goal is to make static content available to ActivityPub, then all you have to do is make your data available as an RSS feed, and let people use RSS Readers to read it. Many ActivityPub-compatible clients can import RSS feeds and distribute them via ActivityPub.

One possible way of implementing it is how Hubzilla implements it:

  1. Find an RSS feed.
  2. Create a fediverse channel that consumes an RSS feed. This channel can be made public or can be private to be consumed by a single person.
  3. People who follow that channel see new posts every time the RSS feed has new content. A cron job runs periodically in the background to check for new posts.
  4. People with permission can comment on the post, and other people following that channel or thread can see the comments.

It does not really make sense to try to implement ActivityPub for static files since static files cannot reply. But, existing technology allows people to convert RSS feeds to ActivityPub-enabled conversations, so the information can still get into the fediverse without the originator of the data having to run a fediverse server.