AT microdata format

During some of the discussion on the proposal head tags for mapping web pages to AT URIs, the idea of microdata format for tagging DOM element with corresponding AT URIs came up. Now that that proposal is stabilizing, I’d like to look at extending it with per-element tagging.

cc @byjp.me @jauntywk.bsky.social @tynanpurdy.com @doriantaylor.com

3 Likes

Yes please! I think this would be very handy.

Unfortunately we can’t use an identical shape on an element basis (as <meta name> is <head> only) but I think we could reuse the same semantics with itemprop!

If <meta itemprop=“at:alternate” content=“at://…”> is a child of an element, that could indicate the immediate parent represents data from the specified AT record.

This would also allow multiple entries (if the element is an aggregation of multiple records).

We’d also need the itemscope & itemtype=“https://atproto.com/somewhere” attributes on the/a parent for it to be valid microdata, we could point that at wherever we think the final spec will be :blush:

<body>
  <div class=“profile” itemscope itemtype=“https://atproto.com/docs/meta-references”>
    <meta itemprop=“at:alternate” content=“at://byjp.me/app.bsky.actor.profile/self”>
    <h3>JP</h3>
  </div>
</body>
1 Like

I think this is great.

A while ago I had spun up https://github.com/astrenoxcoop/weathervane and was checking for link[rel~="did"] or link[rel~="me"] where the the value was the identity’s DID. This would be a great improvement.

1 Like

As someone [whose requested this feature already (Representing multiple resources, ala microdata · Issue #1 · chrisshank.com/at-tags · Tangled), YES! and huzzah!

To me, i quite want to lean into microdata’s itemid= hard hard hard, to represent the multiple resources we see on the page. Microdata is essentially the thing for semantic web today, is used by lots of people (with schema.org schemas usually), and it’s a pretty good mark up imo!

Let’s take the itemid= example from mdn:

<dl
  itemscope
  itemtype="https://schema.org/Book"
  itemid="urn:isbn:0-374-22848-5">
  <dt>Title</dt>
  <dd itemprop="title">Owls of the Eastern Ice</dd>
  <dt>Author</dt>
  <dd itemprop="author">Jonathan C Slaght</dd>
  <dt>Publication date</dt>
  <dd>
    <time itemprop="datePublished" datetime="2020-08-04">August 4 2020</time>
  </dd>
</dl>

And adapt it as a https://bookhive.buzz example, from a sample bookhive record:

<dl
  itemscope
  itemtype="https://bookhive.buzz/book"
  itemid="at://did:plc:zjbq26wybii5ojoypkso2mso/buzz.bookhive.book/3maotqnx5z22q">
  <dt>Title</dt>
  <dd itemprop="title">A Hole In The Sky</dd>
  <dt>Author</dt>
  <dd itemprop="author">Peter Hamilton</dd>
  <dt>Publication date</dt>
  <dd>
    <time itemprop="datePublished" datetime="2026-01-20">January 20 2026</time>
  </dd>
</dl>

This seems like: we can just do this? We can just do this! (Perhaps/is it wise/etc?)

The most hand wavy thing here, to me, is the itemtype, which maps a lexicon nsid to a url. I hope somewhere atproto has schema validation rules written down that help this make sense, that has some terminology / explanation for how an nsid and domain relate, as once subdomains get involved it becomes non-trivial to figure out the mapping here.

There’s some temptation to invent an itemat= attribute that can be an explicit at:// uri, so that we can put some kind of web based url in the itemid= as usual. This feels like an optional thing we could add on, but would not be my primary recommendation!


Nothing is ever over”! semantic web rides again!! i’m making jokes at my own expense here, looks like a fools quest, tilting at windmills, etc. And I do take this as at least 40% joke but also at least 40% serious! This is such a massive conceptual win for the web i want in this thread!

We can just have different resources on the page! The resources we have in our PDS! The ultimate leverage for user agency, to decompose the page beyond one big thing! Divide the software, and it shall mall(eableize)!

1 Like

Is there any possibility of, or interest in, using the lex: scheme as a way to trivially refer to schema definitions for use in the itemtype attribute, as such:

<dl
  itemscope
  itemtype="lex:community.lexicon.calendar.event"
  itemid="at:did:web:bad-example.com/community.lexicon.calendar.event/3mrgmw4cdvb2b">
  <!-- ... -->
</dl>

If this gains adoption, I would suggest the lex: schema be governed and standardized by whichever entity ultimately controls the overall Lexicon schema specification, whether that ends up being the IETF, Bluesky PBC, or some alternative entity.

1 Like

OK this is just a brain dump because I am in the middle of something:

So first, linked data is still very much alive. There are two mechanisms (in HTML) for doing linked data: microdata (I’m sure we’re aware) and RDFa. JSON-LD also counts as linked data (it’s what the LD stands for; heck there is also a YAML-LD and a CBOR-LD).

The way to think about linked data is that there is a labeled directed graph structure embedded in the document tree. The nodes of the graph are URIs; the edges are also URIs. The root element is associated with the <base href="…"> or document URI in lieu of one, and the graph can be assembled by traversing the DOM tree. In microdata, edges are represented via itemprop=, in RDFa it’s rel= for resources and property= for literals. Whichever of these two rendering mechanisms you choose, however, you should be able to recover the same data structure from either one.

So under that rubric, <link> and <meta> tags in the <head> are just ways of expressing leaf nodes in the graph.

It is worth recognizing though that (in RDFa at least) there is a fundamental bifurcation in data type, resource (aka node) vs literal. So when you lift the graph data off the page (ie via microdata or RDFa processor) it is unambiguous as to whether this or that string represented in the markup is one or the other, and therefore how it ought to be handled. (Literals can’t be subjects in RDF and the construct probably can’t even be expressed in microdata anyway.)

(I should further note that this is not theoretical; I use this technique heavily on Sense Atlas and have been using it extensively in my work across the board for something like 15 years at this point.)

Now: with respect to the matter the at: URI scheme complying with RFC3986. I sincerely hope the resolution conforms, because having a thing that looks like a URI but isn’t would break far more than whatever extant systems would have to be broken in order to make it conform. One essential design element of a URI scheme is the ability to register URI scheme handlers in browsers and operating systems. These are extremely well-defined software development targets implement the the resolution and/or dereferencing mechanism. Think of all the things we could do with an at: scheme handler. It would be a terrible thing, to preserve two consecutive slashes, to throw away access to such fundamental infrastructure.

This brings me back to the use of <meta> versus the use of <link>. A <link> is a link—which can point to any URI scheme, and how the link is to be handled is defined by the URI scheme. A <meta> always points to a literal; it is categorically not a link.

So what I’m basically saying is using <meta> would mean having to hand-roll a bunch of infrastructure that you can currently pull off the shelf if you used <link>. More so if there is no conforming resolution to the matter of the at: URI scheme.

Now, regarding the at: prefix for predicate terms (which has no relationship to the URI scheme). Note that in RDF (just as in XML; the lore is that Tim Berners-Lee asked Tim Bray to add namespaces to XML precisely so he could do RDF), prefixes map to URIs. In XML they use the xmlns:pfx="https://some/uri#" attribute; in RDFa it’s prefix="pfx: https://some/uri#", in JSON-LD it’s { "@context": { "pfx": "https://some/uri#" } }, and so on. You resolve the namespace URI by splitting the term on the first : looking it up in the mapping, and doing a simple string concatenation (importantly NOT relative URI resolution, so pfx:term would resolve in this example to https://some/uri#term), so namespace prefixes are usually terminated by a delimiter character (typically / or #, which itself is A Whole Thing™), but they don’t have to. Likewise the prefix itself is arbitrary; there are terms for associating ontologies with preferred namespace prefixes but there is no enforcement mechanism or central registry.

It isn’t strictly necessary and frowned upon if you don’t, but that URI doesn’t have to be a Web URL, and it doesn’t have to point to the vocabulary’s specification, but it’s awfully convenient if it does. All my OWL ontologies use this convention, and they likewise use RDFa to embed the machine-readable spec in the prose documentation. In other words, you can:

  • point your RDF framework straight at the spec and it JFW
  • if you want to look up the documentation for a particular term, you can just click on it and it will take you straight there.

However, if you don’t define a namespace URI for the term prefix, for one, an RDF processor can’t do anything with it, and you need additional special-case code to drag the non-conforming construct into something you can use. This is the case for OGP as it is often deployed (the namespace URI used to resolve but it doesn’t anymore, but not like any implementers actually put it on), as well as Twitter’s meta tag implementation. The only thing that kinda works is schema.org (though it is broken in other ways).

There are further benefits to defining an ontology (eg the OGP one still exists if you dig for it) for at:-prefixed terms, like being able to hook into a rich inferencing infrastructure, and being able to define the terms (like at:canonical) as subproperties or equivalent properties to other terms. This enables existing systems to make use of the terms even without explicit code to handle them.

@chrisshank.com I can show you how I’d sketch out a vocabulary if you’re interested.