Here is an updated proposal based on my Bluesky thread on this topic.
Proposal: Lexicon publishers should be able to publish an optional com.atproto.lexicon.web record that acts as a bridge between the AT Protocol and the HTTP web, defining how records in that lexicon should be displayed or embedded.
It would include:
-
URL Template: A scheme for converting an at:// URI into a browseable HTTP URL (RFC 6570 URI Templates).
-
oEmbed Endpoint: The service URL for fetching JSON embed data.
Workflow: When a client encounters an unknown custom record (e.g., com.example.music.rating):
-
Finds the
com.atproto.lexicon.webrecord (the same way it finds thecom.atproto.lexicon.schemarecord) -
It hydrates the URL template.
-
Path A (Simple): Fetch the HTTP URL to parse standard Open Graph meta tags.
-
Path B (Rich): Pass the HTTP URL to the provided oEmbed endpoint for an interactive widget.
Example Record: A configuration for app.bsky.feed.post might look like this:
JSON
{
“lexiconId”: “app.bsky.feed.post”,
“urlTemplate”: “Bluesky,
“oembedApi”: “https://embed.bsky.app/oembed”
}
Rationale: The lexicon publisher is the ultimate authority on how their data should be presented to the user.
While there are valid concerns about centralization here—this does give the lexicon publisher control over the default web URLs—the reality is that publishers already exercise this control de-facto.
For example, bsky.app URLs are already the standard web representation for posts, and Bluesky already serves the OG tags and oEmbed endpoints. This pattern will likely repeat for every new social app built on a custom schema. This proposal simply formalizes that relationship, making the default presentation discoverable for any client rather than hardcoded.