I’ve finally done it. 😬 Ever since I heard that it was possible to federate WordPress blogs, I’ve been interested in having GPORG join the fediverse. For me, it wasn’t just plug ‘n play, because of my setup (Litespeed Web Server, with a cache plugin + Cloudflare). WordPress’s site health thing kept saying:

Your author URL does not return valid JSON for application/activity+json. Please check if your hosting supports alternate Accept headers.

Apparently, you can test whether or not these accept headers are working by entering in the command line:

curl -I https://giantpaper.org/author/giantpaper/ -H "Accept: application/activity+json"

With the https://giantpaper.org/author/giantpaper/ being the URL to your author page. It’s supposed to bring up a normal HTML page just as you designed it when viewed in the browser, but when entered in the command line with the accept header, it’s supposed to return JSON. For me, it was returning as text/html, which is what the problem was.

Here’s what I did. Hopefully it’ll help someone else.


Every tutorial or fix I saw online was either for Apache or nginx, but I’m using Litespeed. Supposedly, caches aren’t supposed to butt heads with the Activitypub plugin, but there were some exceptions (some people found it started working after they disabled plugins like Jetpack). I figured out I could bypass the cache by adding https://giantpaper.org/author/giantpaper/ to the exclude list. Only problem is that the cache would also be bypassed if the page were accessed in browser which I didn’t want.

There seems to be only other article I saw online about Litespeed + WP Activitypub issues. Fixing OpenLiteSpeed Caching for ActivityPub on WordPress [Archived] (you basically need to add a rewrite rule to your .htaccess file). I THINK this helped.


I’m using my own version of Sage and found that the accept header thing works if I had the default Twentytwentyfour theme activated. I found that the correct JSON code was returning with my own custom theme, but it had the surrounding <html> and <body> tags, as well as everything in the <head> tag everything outside the #app container, which what I have in my index.php file for the theme. I think it had something to do with all of this code being in the index.php file (normally this would be in the header.php and footer.php files). Wasn’t sure how to not make it do that other than:

if($_SERVER['HTTP_ACCEPT'] == 'application/activity+json' || preg_match("#^/(.+)/activitypub/?$#", $_SERVER['REQUEST_URI'])) {
	header("Content-Type: application/activity+json; charset=UTF-8;");
	echo view(app('sage.view'), app('sage.data'))->render();

(The $_SERVER['HTTP_ACCEPT'] == 'application/activity+json' tells the server to only bring up this code if the content-type is set to application/activity+json. Since the content-type of WordPress posts & pages are almost always text/html when viewed in a browser, you won’t be smacked with a big wall of weird-looking code when trying look at your own author page.)

I put this at the very top of my index.php file. If you do:

curl https://giantpaper.org/author/giantpaper/ -H "Accept: application/activity+json"

You should see a big wall of confusing looking code (compressed JSON). This is what you want.

Cloudflare (optional?)

I’m not sure if this was necessary, because supposedly the rewrite rule from the Caches section would’ve taken care of this, but I did the previous two items and it still wasn’t working. So in Cloudflare, under Caching > Cache Rules, I added a new rule:

  • URI Path: Not sure if it really needed to be URI Path or if URI or URI Full would’ve sufficed. Obviously if you use URI Full, you need to include the domain name + protocol (https://…).
  • Request Headers: In the blank field after Request Headers, put content-type. Field #3, put as equals. Field #4 as application/activity+json

Browser Cache TTL

I found I had to leave the Browser TTL as 4 hours (which I think is the default):


Earlier, whenever I clear the site cache, I notice I would get the same message in Site Health:

Your author URL does not return valid JSON for application/activity+json. Please check if your hosting supports alternate Accept headers.

And doing:

curl https://giantpaper.org/author/giantpaper/ -H "Accept: application/activity+json"

Followed by:

curl -I https://giantpaper.org/author/giantpaper/ -H "Accept: application/activity+json"

In this exact order fixes it. Why? I don’t know.

Sidenote: I updated something on the site and cleared the cache. I don’t get this message anymore. Why? I don’t know.

Sometimes you might notice that the error message won’t go away after doing any of the above. I THINK the Site Health checker just needs time to check again (a half an hour? An hour?). I’m not sure if it’s a cache problem.

What it doesn’t do

  • If you have custom fields on your theme, you won’t be able to include them in fedi posts. Hopefully that will change in the future, because my linklog posts make so sense without the external URL.
  • This is completely separate from Lemmy or Mastodon, and there’s no way to connect your existing accounts with your newly federated WordPress site. It creates a completely separate profile on all supported fedinetworks.
  • Looks like it doesn’t support kbin yet. Kbin is still new and doesn’t have an API released at the moment (this is being worked on), so…yeah.
  • Any new posts you create will federate, but it won’t pull over pre-federation posts. It’s most like email than say RSS.


Aaaaaand I think that’s it. I think it still might be indexing everywhere, but you can search for giantpaper@giantpaper.org in your fedi instance (it’s definitely on mastodon.social*). Comments on GPORG are disabled, so I dunno what will happen if someone responds on Mastodon, but it won’t show up here (since comments aren’t even supported on this theme).

*If you’re not signed into mastodon.social, it’ll just redirect to the author page on giantpaper.org.