Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

Plugins

I tried to build an ActivityPub plugin for Grav, looking for honest feedback

first-time plugins

Started by Sebastian van de Meer 1 month ago · 1 replies · 47 views
1 month ago

Hi all,

quick context for why I'm posting this. I run my own blog on WordPress and I use the ActivityPub plugin there. It just works in the background, my posts show up in Mastodon timelines without me thinking about it.

My wife runs her counselling practice site on Grav and she wanted the same thing. I looked around and there's no native ActivityPub plugin for Grav that I could find. There is bridgyfed which goes through the brid.gy bridge, but that's a different mechanism and I wanted something that runs in the same box as the blog.

So I tried to build it. Solo, in my spare time, over the last couple of days. No idea if I did it well or if half my design choices are wrong. I'm not a Grav developer by trade, I copied some patterns from grav-plugin-form for the boring bits and worked out the ActivityPub side by reading the spec and a lot of the wordpress-activitypub source.

Repo: https://github.com/Kernel-Error/grav-plugin-fediverse-publisher
Release: v0.1.0 ( https://github.com/Kernel-Error/grav-plugin-fediverse-publisher/releases/tag/v0.1.0 )

Where it runs right now

Exactly one production site, my wife's blog. Grav 1.7.52, Grav-Admin 1.10.51, PHP 8.3 on FreeBSD. Two real followers, one from mastodon.social and one from bonn.social. New posts she publishes via the Admin land in both their Mastodon home timelines within about 15 seconds, with the right title, summary, image and hashtags from her taxonomy.tag frontmatter. Profile page (bio, avatar, header) renders correctly on Mastodon.

I also tested it locally against GoToSocial 0.21 in a podman setup, the follow handshake and broadcast both work there too.

What the plugin does

  • WebFinger + NodeInfo + Actor JSON-LD at the spec-required paths
  • Inbound Follow / Undo Follow with HTTP-signature verification (draft-cavage-12), digest check, date-skew, identity binding, SSRF-hardened keyId fetch
  • Outbound Accept push when somebody follows
  • Auto-broadcast on Grav Admin page-save: onFlexAfterSave event hooks into the save, builds a Create activity wrapping a Note or Article (depending on length), pushes to every active follower
  • summary plus attachment (image from the body or from $page->media() if there's no inline <img>)
  • Hashtag federation from taxonomy.tag, with the #-prefixed name Mastodon needs to index, plus href pointing back at Grav's per-tag landing page
  • Push queue in SQLite with per-row retry / backoff / dead-lettering, drained by the Grav scheduler tick
  • Two operator CLIs: broadcast:post <route> for manual re-broadcast if a save event was missed, push:purge-dead for housekeeping

What it doesn't do yet

  • Update activity on re-saves. Right now a re-save sends a fresh Create. Mastodon dedupes by object.id so the visible result is fine, but I'm pretty sure Pleroma and Misskey will not handle that nicely
  • Delete federation. When a post is deleted in Grav the follower-side keeps the stale copy until that server happens to refetch the URL
  • Showing inbound likes, boosts and replies on the source site (broadcast only for v0.1)
  • Multi-actor. One Grav site equals one Fediverse actor, no per-author handles
  • Authorized-fetch (the AUTHORIZED_FETCH=true Mastodon variant) is only partially supported via a heuristic for the inbox URL. Full signed-GET path is on the list
  • Update and Delete are the next two roadmap items but I haven't started on them

Things I'm genuinely unsure about

  • Whether the architecture (SQLite for state, draft-cavage signatures, scheduler-driven push worker) is anywhere near how Grav-native plugins are usually built. It's what I landed on by reading other plugins and the ADRs I wrote for myself, but I'm probably missing established conventions
  • Whether subscribing to both onFlexAfterSave and onAdminAfterSave is the right idea (Grav-Admin 1.10 routes saves through Flex, but classic save paths fire the other event, so I'm hedging). The push queue dedupes via a UNIQUE constraint so double-firing is safe, but maybe there's a cleaner way
  • Whether anyone other than my wife's setup would actually want this. There's already feed2toot for the "post to Mastodon when RSS updates" case which is a perfectly fine alternative for a lot of people
  • Whether the multi-site config gotcha (Admin saves to per-host yaml but CLI reads only the global) is something the plugin should warn about loudly or just document. Right now it's documented in the README troubleshooting section but it bit me on day one of the deploy

What I'm hoping for from this thread

If you have a Grav blog, even a test one, would you be willing to give it a try and tell me what breaks? README has the install steps. The one config field you absolutely need to set is federation.canonical_host (the public https URL of your site, the plugin refuses to enable without it).

Code review is also welcome. I'm sure there are PHP, Grav and ActivityPub idioms I got wrong.

And the actual question I'm wrestling with: does this make sense as a real plugin that goes into the GPM index, or is it solving a problem too few people have? If the latter, I'll just keep it as my wife's setup and not bother submitting. If the former, I want to make sure it behaves on at least one setup that isn't mine before I formally submit.

Thanks for any look you can spare. Even "tried it, blew up on first save, here's the log" is useful information.

👍 2
1 month ago

I would use it to post changelog posts for the releases of my software 🤔 Not gonna be soon, because I'd have to change the structure a bit on the page, but I see it could be useful 👍

Suggested topics

Topic Participants Replies Views Activity
Plugins · by Rene, 1 week ago
2 43 1 week ago
Plugins · by Xavier, 4 weeks ago
2 53 4 weeks ago
Plugins · by Luka Prinčič, 7 years ago
3 1179 1 month ago
Plugins · by PIERROT Alain, 2 months ago
3 72 2 months ago
Plugins · by Anna, 3 months ago
5 73 3 months ago