Integrating WordPress Reader and ActivityPub (Concept Mapping) #2324
Jiwoon-Kim
started this conversation in
Ideas
Replies: 1 comment
-
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Integrating WordPress Reader and ActivityPub (Concept Mapping)
First of all, WordPress Reader has site profiles and user profiles.
Basically, a profile also serves as a feed.
Site Profile
https://wordpress.com/reader/feeds/172271303
User Profile
https://wordpress.com/reader/users/kimjiwoon96
However, comments are separated from user profiles.
Comment
https://wordpress.com/reader/conversations
Subscriptions correspond to follows.
https://wordpress.com/reader/subscriptions
You can subscribe to subreddits, but they are RSS.
https://wordpress.com/discover/reddit
You can perform Like activities, but they are separated from the user profile. (In Misskey, you can configure whether to make your reaction list public.)
https://wordpress.com/activities/likes
https://www.w3.org/TR/activitypub/#liked
https://www.w3.org/TR/activitypub/#like-activity-outbox
Limitations
You cannot follow another user profile.
You cannot join a Fediverse forum (group actor).
In the Jetpack app, you can access the media library per site when writing a post. But is access to the media library even possible with only the basic ActivityPub specification?
An idea that should be looked at carefully is that the WordPress.com user profile acts like a multi-instance actor.
https://wordpress.com/reader/users/kimjiwoon96
If you look at the user profile, you can see posts written on multiple sites displayed in one feed.
It seems similar to how Lemmy’s person actor works.
Then, would it be better to pair the WordPress.com user profile with the main site’s person actor handle and treat WordPress websites as group actors?
Hmm… I think the blog profile, user profile, and forum profile (subreddit) are the most important functions that the WordPress Reader should implement, so wouldn’t it be better to distinguish actor types?
Hmm… for now, it seems better to separate the logic for handling posts and comments. The main instance where the user profile belongs can federate posts, but posting from other sites using the integrated handle seems difficult. However, federating comments under a single handle seems somewhat feasible.
Would it be possible to consider a WordPress website as a group actor?
That could depend on whether WordPress can adopt the mechanism of creating and publishing posts like Lemmy.
https://lemmy.world/create_post?communityId=114236
Example
@[email protected],and subscribes to a community on another instance:
[email protected].lemmy.mlsends aFollowactivity to thediscuss.onlineserver.discuss.onlinesends anAcceptresponse and approves.[email protected],a
Create(Note)activity is pushed tolemmy.ml.lemmy.mlcaches that post in the local DB,and displays it on the user’s timeline.
Good question.
Posting to a remote forum in Lemmy is actually one of the core functions of the ActivityPub protocol —
that is, “subscribing to a community on another instance and posting to that community.”
It looks simple on the surface, but quite a complex federation process happens internally.
Let me explain step by step 👇
🌐 1. Prerequisite: Subscribing to a Remote Community (Follow)
First, to write a post in a remote community (e.g.,
[email protected]),your instance (
lemmy.ml) must follow that community.Process
lemmy.ml) queries the[email protected]community URI via ActivityPub (webfinger→actor)lemmy.ml→ sends aFollowActivity → to thediscuss.onlinecommunity actordiscuss.online→ sends anAcceptActivity → back tolemmy.mllemmy.mlDB has the remote community cached locallyAt this stage, the “remote community is registered in my instance.”
From then on, it can be used like a local community.
📝 2. Writing a Post to a Remote Community (Create Activity)
Now suppose the user inputs this on their instance UI:
Then, the post is temporarily stored in the local DB, and the following ActivityPub message is generated:
And this
CreateActivity is sent via HTTP POST tohttps://discuss.online/inbox(the inbox of the community actor).📨 3. Reception and Processing on the Remote Server
discuss.onlinereceives thisCreateactivity and performs the following:lemmy.mlis from a trusted instance (HTTP Signatures)lemmy.ml)[email protected]’s follower instances viaCreateAs a result,
on your instance (
lemmy.ml) it appears as “my post,”and on
discuss.onlineit appears as “a post written by an external user,” but they stay fully synchronized.💬 4. Comments (Replies) Work the Same Way
Comments (
Comment) are also delivered asCreateactivities.The difference is that the
inReplyTofield points to the original post URL:This allows the “conversation tree” to be reconstructed across ActivityPub,
so both instances display the same comment thread.
🧭 5. Local vs Remote Distinction
DeleteActivity → propagated⚙️ 6. Summary of Actual Operation
So, “posting to another instance’s community”
👉 is ultimately handled perfectly through the ActivityPub Create → Accept → Distribute chain.
“Full Lemmy Remote Post Creation Sequence Diagram (actor → community → followers)”
This is the key point where Lemmy’s permission–follow structure (ActivityPub + local permission system) intersects.
To understand it precisely, you first need to distinguish between “join (membership),” “follow,” and “write permission.”
These three may all look like “follow relationships” in ActivityPub, but Lemmy handles them differently.
🧩 1️⃣ Basic Premise: Every Community is an ActivityPub Actor
Each community (
c/forum1,c/forum2) exists as an ActivityPub Group type actorand manages its own inbox / outbox / followers / moderators / banned list.
⚙️ 2️⃣ Lemmy Internal Permission System
Lemmy manages additional role-based permissions in its DB beyond ActivityPub standards.
memberfollowermoderatorbanned_userSo even if you follow, posting (write) permission may not be granted.
This is determined separately in Lemmy’s DB, depending on whether you’re registered as a “member” after
Accept(Follow).🧭 3️⃣ How to Allow Posting Only in Certain Forums
✅ Method 1: Community Access Level Setting
When creating a community in Lemmy, you can choose one of the following:
→ For example, if
[email protected]isPublic,and
[email protected]isPrivate,then from outside instance A, you can post in forum1 but not forum2.
✅ Method 2: “Join Required” Option
If you enable
Require users to join before postingin the community settings (c/forum2/edit),then you cannot post with a simple follow — you must press the “Join” button.
Internally, this sends:
→ When
a.instancereceives this, it records you asmemberin the DB and returns anAcceptresponse.→ Only then will it allow
Createactivities.So even though it’s still a “Follow” in ActivityPub,
Lemmy extends follow into membership internally and separates permissions.
✅ Method 3: Moderator Whitelist
If
forum2isPrivate,the moderator must add a specific account (
@[email protected]) to the whitelist.In that case, there’s a manual approval step before
Accept(Follow)—just like approving followers in Mastodon.
💡 Example Scenario
a.instanceforum1a.instanceforum2a.instanceforum2can_create = true,and must pass ACL (access control list) validation when processing
Create.cannot be represented purely through ActivityPub standards —
it’s handled by Lemmy’s application-level extended logic.
In summary 🔍
Sequence diagram (Follow → Accept → Join → Create → Reject flow)
🧩 1️⃣ Basic Structure
In ActivityPub, Lemmy is modeled like this:
and the Community announces (relays) them.
So the actual actor of the Create activity is the Person,
and the Group sees it and sends an Announce to its own timeline.
Then
b.instance’sforum1announces like this:🔓 2️⃣ The Problem with This Structure
This structure leads to the “posting without permission” issue.
Because ActivityPub is decentralized,
anyone can send a Create activity from a remote server.
kimfroma.instanceb.instance/c/forum2b.instancejust checks “who is this?”and if the policy doesn’t block it, simply accepts it.
It’s similar to an email system —
“anyone can send mail, and the receiver must filter it.”
## 🧱 3️⃣ How Lemmy Blocks It Internally
So Lemmy doesn’t just operate at the ActivityPub protocol level,
it also has a separate verification logic at the application level.
When a user writes a post to a remote community
→ that instance checks the community’s mod log or membership record
→ verifies, “Is this person a member of this community?”
→ if not, it returns a Reject response.
In other words, Lemmy adds
an “application-level ACL” (access control layer)
on top of ActivityPub’s base freedom.
⚙️ 4️⃣ How to Allow “Posting Only in Specific Forums”?
It’s impossible within ActivityPub itself.
→ Because a Create activity has no structure like “this person is a member of this Group.”
Instead, it can be implemented at the application level like this:
In practice, Lemmy manages this through the LocalUser ↔ CommunityFollower relationship.
Therefore, “only members of a joined forum can post.”
💬 Conclusion
Strictly speaking,
✅ “It can be sent, but it won’t be accepted.”
That is, technically “writing” is possible,
but unless the community “approves,” it won’t appear in the public feed.
The inbox categories in an email system (e.g., Primary, Promotions, Social, Forums, Updates) are more than simple “folder classification.”
They are structures combining large-scale spam filters + ML classification systems + user-defined rules.
Let’s break them down one by one.
📬 1️⃣ Basic Structure: “Mail = Object, Inbox = Index”
The core data structure of an email system is as follows:
The mail body (message) is essentially an independent object (message/rfc822).
Inbox, folder, category are sets of metadata indexes pointing to that message.
That is, in reality, “moving mail” is just changing its position or tag within the index.
🧱 2️⃣ Three Implementation Methods for Categories
(1) Folder-based structure (IMAP-based)
Older Outlook, Yahoo Mail, and most standard mail clients use this structure.
The IMAP protocol manages folders through commands like LIST, SELECT, and MOVE.
Categories such as “Social” or “Promotions” are essentially implemented as IMAP folders:
📎 Downside: A single mail can belong to only one folder.
So Gmail extended this.
(2) Label-based Structure (Gmail Style)
Gmail extended IMAP to implement it using labels instead of folders.
Example:
A single mail can have multiple labels.
→ The same message can appear simultaneously in “Inbox” and “Social.”
This is actually similar to ActivityPub’s “Collection” structure:
Inboxis anOrderedCollection,and
Labelacts like a subview filter of that collection.(3) Virtual Categories (ML + Tag-based Filter)
Modern systems like Gmail, Outlook, and Naver use this.
There are no actual “category folders”;
messages are virtually labeled through ML classification of metadata.
Examples of classification criteria:
fromdomain is SNS (facebookmail.com,twitter.com, etc.)List-Id,Precedence: list, etc.That is, the ML classifier learns patterns from tens of millions of messages,
and performs real-time classification at reception time,
adding a category tag to the mail header.
🧩 3️⃣ Actual Storage Model (e.g., Gmail Internal Structure)
Taking Gmail as an example,
mail storage is based on Bigtable,
and each message has fields like this:
msg_idthread_idfrom,to,subject,datebody_snippetlabels[]categoryspam_scoreimportance_scoreIn the user UI it appears as “folders,” but in reality, it’s a label filter query.
⚙️ 4️⃣ From the ActivityPub Perspective?
The email inbox category structure
has much in common with ActivityPub’s Inbox / Outbox concept.
If you want to implement “Inbox categories” in an ActivityPub-based social app,
you can configure “sub-collections” per label for the OrderedCollection:
That is, in ActivityPub, Inbox categories can also be implemented as “query-based virtual collections.”
🧠 Summary
“Design structure for categorizing ActivityPub inbox like an email (e.g., social / system / mentions / dms)”
Beta Was this translation helpful? Give feedback.
All reactions