Skip to content

MSC4427: Custom banners for user profiles - #4427

Open
cyrneko wants to merge 9 commits into
matrix-org:mainfrom
cyrneko:main
Open

MSC4427: Custom banners for user profiles#4427
cyrneko wants to merge 9 commits into
matrix-org:mainfrom
cyrneko:main

Conversation

@cyrneko

@cyrneko cyrneko commented Feb 25, 2026

Copy link
Copy Markdown

Rendered

Signed-off-by: Alexia cyrus42@disroot.org

@cyrneko cyrneko changed the title MSC0000: Custom banners for user profiles MSC4427: Custom banners for user profiles Feb 25, 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 Feb 25, 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:

  • Client (sending)
  • Client (rendering)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Question, for an implementation to be valid...can it be one that is compatible but uses a different field?

I've just found out that Commet apparently implements this, with the same semantics, however uses chat.commet.profile_banner instead of eu.cyrneko.msc4427.banner / m.banner

I assume not, but I thought I'd ask just in case

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I've pushed a commit that makes the unstable prefix chat.commet.profile_banner

This means there is now two known implementations for this feature:

respective commits:

Both of these can set a banner as well as display it on profiles.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Question, for an implementation to be valid...can it be one that is compatible but uses a different field?

Sure, as long as the spec your describing in this MSC matches an implementation it's valid. The reason for this check is to ensure that the proposal works and the field names do not need to align for that.

And there is precedence for using a existing field name as a unstable key 👍

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Client implementation (Voyage):

VoyageClient/Voyage@15b4729

Comment thread proposals/4427-user-banners.md Outdated
Comment thread proposals/4427-user-banners.md Outdated
from `eu.cyrneko.msc4427.banner_url` to `chat.commet.profile_banner`

Clients can then use this field to load user banners.

## Potential issues

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would we benefit from a recommendation for the banner dimensions or is this something you'd expect to work itself out organically across clients and users?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think this will probably end up being an implementation detail, though I feel guidelines around aspect ratio would make sense probably? Something along the lines of perhaps 1:√21 or another aspect ratio

Footnotes

  1. okay, I admit, that's me being a nerd for DIN standard paper sizes. There isn't really necessarily a reason I suggest this ratio in particular

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe worth comparing with other platforms. From a quick check:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I can see the point on both to be honest. Mandating an aspect ratio is almost certainly going to be impossible, as clients require their own agency about how to display the banner.

That said, perhaps some wording that banners should be landscale an approximately 3:1 (clients MAY use techniques such as letterboxing or scaling if a banner doesn't fit)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

that sounds good! I'll add that to the doc

if I don't forget at least...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I did, indeed, forget!

I'll set a reminder with a link to this...

@1vel

1vel commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

(psst, you made the rendered link point to the first revision only)

"displayname": "Alice Margatroid",
"m.example_field": "custom_value",
"m.tz": "Europe/London",
"m.banner_url": "mxc://matrix.org/example123"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps it should be m.banner_uri instead, given this is a new field and it doesn't accept URLs (seemingly). Maybe it should also be noted that this must be an MXC URI.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

that checks out, actually; it wasn't intended that non-mxc-URIs are to be used here and I just wrote url from muscle-memory, I'll fix that in a little bit

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

"url" is currently the standard in other places we have mxc's, e.g. avatar_url

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

hm, that is true...but perhaps this should be changed for new fields...? either way I intend MXC URIs so I'll probably clarify that and push. (finally coming back to this)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

avatar_url does not support arbitrary URLs either, it mandates MXC URIs, yet it is labeled avatar_url

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe url in places that only accept MXC URIs is due to the fields previously accepting URLs, however I haven't verified this. Correction appreciated.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@velikopter no thats not the case

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The sauce gets saucier. The spec doesn't mandate avatar_url being an MXC URI in all places.

For example:


  1. https://spec.matrix.org/v1.19/client-server-api/#mroommember

  2. https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv3roomsroomidjoined_members

@catfromplan9 catfromplan9 Jul 20, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The sauce gets saucier. The spec doesn't mandate avatar_url being an MXC URI in all places.

For example:

1. ![](https://private-user-images.githubusercontent.com/232914828/623842680-cf89bbff-9889-48ca-81a7-b832a45d4d4e.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODQ1NTM4ODIsIm5iZiI6MTc4NDU1MzU4MiwicGF0aCI6Ii8yMzI5MTQ4MjgvNjIzODQyNjgwLWNmODliYmZmLTk4ODktNDhjYS04MWE3LWI4MzJhNDVkNGQ0ZS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNzIwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDcyMFQxMzE5NDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00YmMyYjQ2ZDI5NmZkMWY2MjUwN2JhMmJhYjZlODJkMTBiODc3ZTlhMTQ0MTAzNzcxOGI2ZGJhYTAxYTZhY2FhJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZwbmcifQ.nNwGoQLggT2-uUgCk2oBA4snP3UDTWhycsyHDEAJ3AE)
   https://spec.matrix.org/v1.19/client-server-api/#mroommember

2. ![](https://private-user-images.githubusercontent.com/232914828/623842889-83ba8d15-e8ac-4ec6-80ea-1ebacd13c8e4.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODQ1NTM4ODIsIm5iZiI6MTc4NDU1MzU4MiwicGF0aCI6Ii8yMzI5MTQ4MjgvNjIzODQyODg5LTgzYmE4ZDE1LWU4YWMtNGVjNi04MGVhLTFlYmFjZDEzYzhlNC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNzIwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDcyMFQxMzE5NDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yNjRmMjJhNzU3YTUyOGIyNmMwYWNhMGMxNWFhMjc5ZjcwNTYzYTE2ODk5ZWY0Mzc3MGQ1ZDJiYjM0Y2VjOTRkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZwbmcifQ.79ahy1VZCkh2Fzyt9PC39V2ndEIo3B-ixsKTM5NX8jM)
   https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv3roomsroomidjoined_members

This is a documentation issue, for privacy reasons non-MXC URLs must NOT be fetched by client. You can refer to matrix client implementations for that

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'll leave it as URL and keep the warning for implementers to only load MXC:// URIs in

@cyrneko

cyrneko commented Mar 28, 2026

Copy link
Copy Markdown
Author

(psst, you made the rendered link point to the first revision only)

oops, totally missed that, but it's fixed now, ty!

@catfromplan9

Copy link
Copy Markdown

@cyrneko consider reverting url -> uri, url matches similar syntax elsewhere, namely avatar_url on rooms and memberships. I think that even if uri is pedantically correct it would be better to adhere to pre-established stylistic choices that exist in the spec

I had initially done this to try and be "correct", but perhaps changing
existing norms in the spec is outside the scope of this MSC, and I
should just stick to existing norms.
@cyrneko

cyrneko commented Jul 19, 2026

Copy link
Copy Markdown
Author

@catfromplan9 done.

@cyrneko

cyrneko commented Jul 20, 2026

Copy link
Copy Markdown
Author

smh the spellcheck still thinks commet is wrong

@catfromplan9

Copy link
Copy Markdown

Is this also supported per-room (as in, on join events)?

@cyrneko

cyrneko commented Jul 22, 2026

Copy link
Copy Markdown
Author

Is this also supported per-room (as in, on join events)?

Not through join events, only maybe through things such as MSC4144, but that is out-of-scope for this MSC.

@catfromplan9

catfromplan9 commented Jul 22, 2026

Copy link
Copy Markdown

Is this also supported per-room (as in, on join events)?

Not through join events, only maybe through things such as MSC4144, but that is out-of-scope for this MSC.

Why not m.room.member state events? Its very straightforward to support

@catfromplan9

catfromplan9 commented Jul 22, 2026

Copy link
Copy Markdown

I implemented the m.room.member state event support for banners in my client, would like if it were in this MSC

@catfromplan9

catfromplan9 commented Jul 22, 2026

Copy link
Copy Markdown

Should also be kept in mind that profile lookup over federation may be disabled. If this is the case, then the only way a banner could be visible is to support it on m.room.member state events. Since the membership state event is per-room, this requires this MSC to also support propagating a global banner change server-side into all rooms the user is a member of when it is changed, as is already done for display name and avatar changes.

@cyrneko

cyrneko commented Jul 23, 2026

Copy link
Copy Markdown
Author

hm, I'm not sure if this MSC should be the one to introduce that, I did initially just want to standardize existing behavior based on extended profile data, m.room.member state events are a different mechanism altogether with different considerations1, and I don't know many clients that implement this behavior in m.room.member events as opposed to using extended profile data. I think Extera might still be doing that, but they don't follow this MSC to begin with.

I am also not aware of the specifics of that mechanism so I'd have to read the spec for that part first, but that's the lesser of my worries

Footnotes

  1. My primary concern is that they're another reason state-events are sent to potentially hundreds or thousands of rooms, in addition to name and avatar. I was never really a huge fan of that as it means more waiting time for changes to propagate, as opposed to the basically-instant nature of extended profile data and PMPs, which also discourages changing this data often (which is something I know some like to do).

@catfromplan9

catfromplan9 commented Jul 24, 2026

Copy link
Copy Markdown

hm, I'm not sure if this MSC should be the one to introduce that, I did initially just want to standardize existing behavior based on extended profile data, m.room.member state events are a different mechanism altogether with different considerations1, and I don't know many clients that implement this behavior in m.room.member events as opposed to using extended profile data. I think Extera might still be doing that, but they don't follow this MSC to begin with.

I am also not aware of the specifics of that mechanism so I'd have to read the spec for that part first, but that's the lesser of my worries

Footnotes

1. My primary concern is that they're _another_ reason state-events are sent to potentially hundreds or thousands of rooms, in addition to name and avatar. I was never really a huge fan of that as it means more waiting time for changes to propagate, as opposed to the basically-instant nature of extended profile data and PMPs, which also discourages changing this data often (which is something I know some like to do). [↩](#user-content-fnref-1-63d25e82ccf041064ede23fd5d833ebe)

Well what I mean is, if profile lookups are disabled on the homeserver then you rely on member state events. You could leave propagation of the state event up to the client (meaning no server side change is necessary) so all you'd have to do is add a section about them being defined first by per-room m.room.member state events

This lets you have per-room banners supported, and if you want then you don't need to propagate it into all the rooms when changed on your client (if you assume your userbase is on servers with profile lookup enabled)

Comment thread proposals/4427-user-banners.md Outdated
matrix-org#4427 (comment)

Co-authored-by: Tulir Asokan <tulir@maunium.net>
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.

9 participants