Overview
Omote lets each app’s profile of an ATProto account build on the account’s other profiles, and shows the account holder where every field comes from.
The problem
Section titled “The problem”An ATProto account is one identity across every app, but its profile is not. Apps keep their own profile records beside Bluesky’s app.bsky.actor.profile, and nothing tells the account holder which app reads which.
The apps already agree on the shape of a profile. Grain’s profile lexicon, for example, is Bluesky’s with three fields removed. What they cannot say is where a value comes from when their own record doesn’t have it. So nobody can tell whether changing a display name on Bluesky changes it anywhere else.
How Omote answers it
Section titled “How Omote answers it”Omote adds one optional field to an app’s own profile record: extends, a list of the profile records it builds on.
{ "$type": "social.grain.actor.profile", "extends": ["app.bsky.actor.profile", "social.omote.actor.profile"], "displayName": "Alice (photos)", "description": null}The record resolves the way a tsconfig.json resolves its extends:
- later bases win over earlier ones;
- the record’s own fields win over all of them;
- a field the record leaves out is inherited;
nullhides what the bases say.
A record takes part by its shape. Fields with Bluesky’s names and types are shared, and everything else stays the app’s own. No app’s lexicon has to reference Omote’s.
What Omote provides
Section titled “What Omote provides”- Lexicons (
@omote-social/lexicon):social.omote.actor.profile, a shared profile that belongs to the account holder rather than to any app. It is also the template an app copies to adopt the pattern. - A library (
@omote-social/profiles):getProfile()resolves how an account appears in an app, reading straight from the account’s own server. It works in browsers, Node and Cloudflare Workers. - An editor (omote.social/editor): shows every profile record in an account and where each field comes from, and edits each one within that app’s own rules.
- A resolve endpoint:
social.omote.getProfile, the library’s answer over XRPC, for prototyping.
Where to go next
Section titled “Where to go next”- Learn how profiles extend, including the rules every implementation follows.
- Adopt Omote in your app.
- Show profiles in your app with the library.
- Read the full specification, including the questions still open for adopting apps.