I’d like to use this thread to riff on a community practice of mapping web pages to their canonical AT record. This is something that standard.site already does as a way to verify publications and their documents using <link> tags. Unfortunately Rich Harris pointed out that this isn’t technically valid, so there is discussion for a breaking change for standard site to use the <meta> tag. Making this work with any lexicon/record has quite important ramifications for the entire ecosystem (I’m writing a short piece to better contextualize this right now).
Summarizing some of the previous conversation, I proposed this:
<meta property="at:uri" content="at://…" />
Miguel brought up that standard.site needs more than one record per page so it might make sense to append the NSID to the property. This could also make it easier to query:
As a side-note, we (collectively) will need to figure out a path forward for AT URIs not being valid URI syntax as part of the IETF working group process. We are roughly scheduled to work on the repo and sync documents first, so it might even a while before there is a consensus solution.
I think going ahead with a different HTML tag/setup is a reasonable choice in the near term. I think it would probably also be reasonable to just stick with the existing deployed system and syntax for a while longer.
I’d nudge towards “at-uri” instead of “at:uri”, but that is just aesthetics. For better or worst, there is an “at-uri” syntax variant to refer to accounts, like “at://did:plc:abc123” (no path segment). A nice thing about full AT URIs is that the NSID is baked in to the URI itself, so you don’t need to have that be part of the “property” field. I think it is usually fine to have multiple of the same meta or link tag with the same property? So wouldn’t need to have separate property values for repeated tags.
I’m not gonna weigh in on the technical implementation because I know that’s not my wheelhouse.
I do want to emphasize though that having some way on a page by page basis, and even cooler on an element basis, to indicate what AT record is being rendered would be hugely beneficial for interop between web clients of all kinds. Right now, a lot of interop and enhanced rendering of lexicon in contexts outside of the client in which are URLs shared involve a manual list of compatible clients and verified URL schemes. A stop gap for this is to include the full URI in the link, but that’s clunky as hell. If it were trivially easy to detect what record is being rendered by a webpage, then it becomes trivial to resolve that link and then pull down the record to do whatever kind of fancy embedding and rendering you’d like, regardless of what the domain name of the link is. Pair this with perhaps an on-protocol way to declare the URL scheme for a client app and what kinds of records it renders under what you were else schemes. Then you’ve got a really great system for interop between the web and atproto, where you always know what record you’re dealing with regardless of the front end that you’ve been directed to.
Both of those could be equally easy to fetch the actual underlying record just from the link without having to know about myrandom.website ahead of time.
Specific use case is for “claiming” pages. Standard Site does this kind of indirectly, but I should be able to put my DID in a page, and then in a system like Semble, “claim” that URL, and Semble could verify that. Very hand wavy description and I’m not set on this.
As well, at:[something] follows a vendored set of attributes like og:
Aram pushed us previously towards Schema.org, but regardless this conversation may be useful:
I edited/updated my post to talk about multiple properties. I think there is a fair amount of flexibility that can be done with a single property value. But doing colons aligns with opengraph. I don’t have a super strong opinion either way. Might be good to mock up examples with both syntax and try reading with common HTML parsing libraries (eg, beautifulsoup, CSS selectors) and see how they feel.
I would argue the usage of <link> tags for mapping pages to the DID of the controlling user is valid, and should be kept. The AT-URI can’t be used as an href because the syntax doesn’t accommodate for colons in the authority, but the bare DID would be correctly interpreted as a valid URN with the did scheme.
I understand the desire for consistency between the methods for “linking to the record for this page” and “linking to the user for this page”, but I think it’s worth retaining the existing rel=me method for making the latter claim:
Edit: The HTML specification states that href values must be URLs, so this usage is technically invalid. As mentioned in the first post in the thread, this causes issues for certain producers who validate the href as a URL, so I wouldn’t recommend this after all. Full support to property="at:did" for this use case.
I built a demo of this using RDFa lite — I put a demo Browser Extension together & set up two of my atproto sites (StS2 & Passing Reads) to have the necessary tags to explore. Try it out here, or see the Github repo.
The only downside is that RDFa also requires that a resource is an IRI, with the same issue of did:plc:abc123 not being a valid authority.
If we’re interested in being able to tag elements as well as a whole page/document (I think we should be!) then just using <meta> is limiting, but also most mechanisms that feel “right” also expect valid URIs, so we’re in the same boat.
I think the three options are:
Accept that at-uris aren’t valid (yet) and use RDFa lite (or something similar) to allow tagging of pages and elements
Use <meta> tags to link whole pages, and defer being able to tag element level
Swap to something entirely custom (like data-at-uri="at://…")
I’m definitely in favour of (1), despite the authority issue, especially looking at the longer term — I’d be super interested to hear what excites you about this too @tynanpurdy.com; personally I love the idea of being able to right-click an interesting thing on an AT-powered website and explore it (with PDSls, with Aturi, go straight to Mu.social or any number of other things).
(2) I think unblocks the issues standard.site has been having with at-uris not being valid URIs, though I think it misses the opportunity to bring element-level into the mix.
(3) feels… less than ideal. It’s a bit like HTML microdata (but would support nested-but-unrelated at-uris)
If we end up with tags for records and dids then it makes me wonder what having one for a collection (feed?) or a user’s specific collection would mean?
To me, it is about following through on the promise that the data is separate from the app. When you share a link, you are now baking the app and the content together in transport. For all sorts of reasons, the client you were using to find a thing when you decided to share it with me may not be the client I want to use to view it. So to make that journey work from end to end, you need some way to preserve the distinguished relationship between the client and the content it is representing. Now, most of the time just labeling the webpage as a whole will do the trick, but I do foresee you get a ton of cool opportunities, especially at the browser level, when all the contents of a webpage can individually be associated with their source content.
To put it into a concrete example, let’s say I am on somebody’s custom hand rolled blog. The page as a whole is representing the standard site document. But viewable in line are comments from Bluesky. Let’s say this was a particularly spicy blog post and there are a ton of comments. If I want to open up this thread in one of the several different Bluesky tree thread viewers, I might have to click the post link out, which will probably take me back to the Bluesky app, which I may not even want to use and then I have to copy that Bluesky link and then take it to the tree, viewer and paste it it. That’s a lot of work and decisions about which client I interfaced with were made for me. Imagine instead, I could hover over that Bluesky post and the browser recognized what it was and offered me an option to open in a compatible client and I could pick my preferred tree viewer directly.
I think per-element mappings to AT records are orthogonal with mapping web pages, they are both important. But right now if standard.site is going through with a breaking change then we have a small window of time to flesh out a more agnostic way to map web pages to AT records, and per-element mapping can be figured out in parallel. Many web pages will have both per-page and per-element mappings.
The syntax for URIs only allows for colons to appear within the authority component when a numeric port is included as the second “segment” of the authority. It is possible to unambiguously differentiate hostname:port from did:method:identifier, but the presence of more than two “segments” and an non-numeric port “segment” conflicts with the specification, so most (if not all) producers and consumers outside of the ATP ecosystem reject at: URIs entirely when a DID is used as the authority. The mailto: and tel: schemes don’t allow for colons in their authority components, so they can be processed by any URI-handling code.
Allowing for future extensions is wise, but I think the existing semantics of “link this page to a user and/or record” could be collapsed into a single segment-less property, if deemed more ergonomic than at:did/at:uri:
I’m interested in what other types of ATP-related link relations you were envisioning. These two seem like the most “essential” ones to me, and it would make sense to promote them to a segment-less property.
Which syntax should be required for referring to users, a bare DID or an AT-URI with no path? If the bare DID form is chosen, it may be preferable to provide a generic did property for use in both ATP and non-ATP contexts: <meta property="did" content="did:plc:erqwpimsmwnzohwoiojsy22z" />
I think if you want to talk about other use cases than standard site – which wants to solve this NOW but also get some other input, that element tagging is out of scope for this thread.
That is, yes, (2) and using <meta> seems to be the likely desired path, and focusing on page-level meta.
why is there a // in at:// anyway if the thing it refers to isn’t a hostname? (even if it is a DNS name it may not even have an A/AAAA or CNAME record and doesn’t mean “connect to this host” like an ordinary URL—ie locator—means it anyway)
if it’s any consolation tim berners-lee said the // was probably not necessary and he regrets putting it in there.
I’ve been curious about this myself, and would even go as far as questioning the presence of an at scheme at all. The DID specification allows for DID URLs, which could be used with the /{collection}/{rkey} path syntax to refer to records; this form is equivalent to removing the at:// prefix from an existing AT-URI. This form would be fully compliant with URI parsers, unlike AT-URIs. On the other hand, it does make sense to create a dedicated scheme for ATP, since a DID URL doesn’t specify any method for actually locating the resource it refers to, and applications would have to infer the process of resolving the DID document and fetching the record from the PDS.
In the end though, what was chosen for AT-URIs has to remain consistent even if better ergonomics and syntax are possible with different forms; existing records use at:// and every service expects at://.
I thiiiiink @christian.bsky.social explained to me why at: exists at some point or other but it dissipated from my brain.
I mean, it can still be a URL (qua “locator”) and not necessarily rely on DNS; (i mean, again, mailto: and tel: have dereferencing semantics and the latter is emphatically not DNS).