Skip to content

MSC4501: Social Media on Matrix - #4501

Open
q-TheDog wants to merge 17 commits into
matrix-org:mainfrom
Haven-Organization:msc-social-media-pages
Open

MSC4501: Social Media on Matrix#4501
q-TheDog wants to merge 17 commits into
matrix-org:mainfrom
Haven-Organization:msc-social-media-pages

Conversation

@q-TheDog

@q-TheDog q-TheDog commented Jul 6, 2026

Copy link
Copy Markdown

@q-TheDog q-TheDog changed the title MSCXXXX: Rooms as Social Media Pages MSC4501: Rooms as Social Media Pages Jul 6, 2026
@turt2live turt2live added proposal A matrix spec change proposal. Process state. A-Client Server Client-Server API kind:feature MSC for not-core and not-maintenance stuff needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. labels Jul 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation requirements:

  • Chat client (backwards compatibility), or MSC mechanisms to prevent/discourage chat clients from encountering the data
  • Social media client (first party compatibility, multiple)

@q-TheDog q-TheDog Jul 11, 2026

Copy link
Copy Markdown
Author

@turt2live turt2live left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early review for early process requirements.

Comment thread proposals/4501-rooms-as-social-media-pages.md
q-TheDog added 5 commits July 6, 2026 17:23
Spiritual successor to the abandoned MSC3639, defining room types for
social media profiles (m.social.profile) and groups (m.social.group),
a profile-discoverability field built on MSC4133, a post event type
reusing m.room.message's schema, a single mechanism for reposts/boosts/
quote-posts, liking via standard m.reaction, room-membership-as-following,
and a phased migration plan for treating m.room.message as an
interchangeable stand-in for m.social.post during rollout.
Note that a repost's embedded body isn't tied to the referenced
event's actual content at all, so a malicious repost could fabricate
something the original author never said, not just resurface an
edited/retracted statement.
A boost's outer body was empty/absent, which renders as a blank,
confusing message bubble in any client without support for this
proposal. Require a matrix.to/matrix: permalink to the reposted
event instead, so non-compliant clients see an ordinary clickable
link, and specify how a compliant client detects and re-renders that
case.
@q-TheDog
q-TheDog force-pushed the msc-social-media-pages branch from a167973 to 69db24c Compare July 6, 2026 21:23
q-TheDog added 5 commits July 6, 2026 17:53
A repost previously only carried a copy of the original's body. Carry
the whole content object instead (formatted_body, format, media
fields like url/file/info, etc.), so a repost of a rich-formatted or
media post renders the same as the original rather than degrading to
a plain-text stand-in.
m.social.profile_user_id is a new room state event (fixed empty
state_key, guaranteeing a room can only claim one owner at a time)
that lets a profile room assert which Matrix user it belongs to,
independent of its m.room.create creator (which can be a bridge or
appservice bot rather than the real owner). Since it isn't one of
the state events a default power_levels overrides, it inherits
state_default (50, Moderator) rather than Admin-level protection;
documented that gap and recommended an explicit override so
moderators can't reassign a profile out from under its owner.

Also carry the original post's sender and, optionally, displayname
in m.social.repost_of, alongside its content, so a repost can credit
the original author without a fetch to the original room.
m.social.repost_of.content_inline lets a boost point at the outer
event's own content instead of duplicating a copy inside repost_of,
for implementations (e.g. a federation bridge) that already build one
copy of the reposted content as the event's own content.

Also restructured the Reposting/Boosting/Quote Posting section around
a mandatory/optional field list instead of prose, and made content
optional but recommended, since omitting it means a client has to
either fetch the live original (which can fail without permission or
room membership) or fall back to a bare placeholder link.
Replace m.social.repost_of with m.social.relates_to, a generic
cross-room reference block carrying a mandatory kind field
(m.social.repost or m.social.reply) alongside the existing
event_id/room_id/sender/content/content_inline/displayname fields.
Reposts and cross-posted replies need the same shape for the same
reason (rendering a cross-room reference without requiring room
membership), so a shared block with a kind discriminator replaces
what would otherwise be two near-identical mechanisms.

Add a new use of kind: m.social.reply for cross-posting a reply into
the replying user's own profile room, so it surfaces in followers'
feeds the way replies show up on other social platforms' timelines,
without disturbing the real in-thread reply, which still uses
ordinary m.thread relations in the room it was sent in. This is aimed
at implementations like a federation bridge that already need to
mirror a reply both into its thread and into the replier's profile.

Also recommend, but don't require, sending a rotating-arrows reaction
on the referenced event alongside any repost/boost, so clients can
compute repost counts via the same reaction-aggregation mechanism
already used for likes.

Updated Alternatives, Potential issues, Security considerations, and
the Unstable prefix table to match, and trimmed the boost/quote-post
detection prose.
Matches the field name Matrix's own m.relates_to already uses for the
same purpose (naming a relationship type), which is also what an
early independent implementation (matrix-appservice-activitypub)
reached for unprompted, suggesting it is the more expected name.

m.social.relates_to remains its own, distinctly named block though,
not the real m.relates_to: added prose clarifying it borrows only the
rel_type naming convention, not m.relates_to's server-side
aggregation, bundling, or thread-rollup behavior.
@q-TheDog
q-TheDog marked this pull request as ready for review July 11, 2026 07:07
Give quote-posting, reposting, and cross-posted replies their own
sections instead of bold-lead subsections under Cross-room post
references, and add an "Also known as" list under each (plus Liking)
naming the equivalent action on other social media platforms.

Standardize on "repost" as the canonical term in prose; "boost" and
"retweet" now only appear inside the Reposts section's own "Also
known as" list, not scattered through the rest of the document.

Move repost counting (the recommended 🔁 reaction) into its own
Repost counts section alongside Liking, rather than living inside the
Reposts section.

Drop the "m.social.like was considered and rejected" paragraph from
Liking, since Alternatives already covers the same reasoning.
@q-TheDog

q-TheDog commented Jul 12, 2026

Copy link
Copy Markdown
Author

Did a little restructuring to the document to give each distinct flavor of event being proposed its own header. Also changed the language around reposts to be consistent throughout instead of interchangeably using other social media platforms' terminology. Other terms for these actions are now isolated in "Also Known As" sections under each type. No changes to any of the JSON schemas

@ErikMichelson ErikMichelson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another question: How can this social media feed approach deal with per-post-visibility?

It is common for social media platforms to allow specifying whether a single post is publicly visible or only for followers. In the same way, replies could be public or only visible to the post author or even just visible to participants of the specific reply thread.

I don't see any mechanism in matrix currently to handle per-message overrides for readability of a message, so I guess this wouldn't work and therefore should probably be noted as a limitation.

Comment thread proposals/4501-rooms-as-social-media-pages.md Outdated
Add m.social.body/m.social.formatted_body: optional content fields
that let a compliant social client render a post differently from how
the same m.room.message renders in an ordinary room timeline. Only
valid alongside their non-m.social counterpart, and forbidden on
m.social.post events, which have no non-compliant timeline to
accommodate.

Move Reposting with inline content here from the Reposts section,
since content_inline exists for the same backwards-compatibility
reason. Add a second example showing content_inline covers the whole
outer content (attachments included, not just body text), and that
m.social.body/formatted_body, when present, are what a compliant
client should treat as the duplicated content's actual text rather
than the raw body/formatted_body.

Note the new section in the intro's summary bullet list.
@q-TheDog

q-TheDog commented Jul 13, 2026

Copy link
Copy Markdown
Author

Made the following changes:

  • Added m.social.body and m.social.formatted_body as a place to store an alternative body for a m.room.message when the body you want to show in the social client is different than the body you want to show in non-MSC4501 clients. This came out of necessity when working on matrix-appservice-activitypub where I was unable to include information like "[user] reposted [other user]'s post: [blockquote]" while also being able to cleanly remove the header and blockquote from the body that was already being displayed via the m.social.relates_to block in the social media client. With a separate body field you can just store each version of them separately. Included a JSON to demonstrate this.

  • Clarified usage of content_inline to make it clear that it applies to file attachments on the outer event too. Provided an example JSON for that.

  • Moved the above two things into their own section: Client Backwards Compatibility, since they both only exist for the purpose of making events render nicely in non-MSC4501 clients.

No changes to any of the already-proposed types.

- Rename proposal from "Rooms as Social Media Pages" to "Social Media on Matrix"
- Reframe the MSC3639 relationship as additive rather than simplifying, and add
  a dedicated Comparison to MSC3639 section
- Fix stale references treating MSC4133 as unmerged; it landed in Matrix 1.16
- Replace the Terminology section with an "Also known as" naming list under Posts
@q-TheDog q-TheDog changed the title MSC4501: Rooms as Social Media Pages MSC4501: Social Media on Matrix Jul 16, 2026
- Rename m.social.profile_room_id to m.social.profile_room, and change its
  value from a bare room ID string to a {room_id, via} block, matching
  m.space.child's own via convention, since room IDs aren't routable on
  their own
- Add via as a RECOMMENDED field on m.social.relates_to for the same reason
- Update repost matrix.to/matrix: permalink examples to include ?via=
@q-TheDog

Copy link
Copy Markdown
Author

Added a place for via entries for all cross-room references. This did mean changing one proposed key. m.social.profile_room_id is now m.social.profile_room, and is now a block containing room_id and via.

- Add a table of contents after the intro
- Nest Quote Posts, Reposts, and Cross-posted reply under Cross-room post
  references
- Fold Client Backwards Compatibility into Handling m.room.message in social
  rooms: its two mechanisms (m.social.body/formatted_body, and reposting with
  inline content) are now subsections there instead of their own section
…mpatibility

Nest the phased-rollout content under its own Handling m.room.message in
social rooms subsection, alongside the other two backwards-compatibility
mechanisms already there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Client Server Client-Server API kind:feature MSC for not-core and not-maintenance stuff needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. proposal A matrix spec change proposal. Process state.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants