{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreiauf2dehhmz2gij535dwtv2xz4nazasv5up3b7jhs6y5biqan22d4",
"commit": {
"cid": "bafyreigc4juodjqyent5d73o4574bfbtcif7x6vnezi5nzkid4csup22iu",
"rev": "3mmltnylrs52k"
},
"uri": "at://did:plc:ephkzpinhaqcabtkugtbzrwu/app.bsky.feed.post/3mmltnygkjc27",
"validationStatus": "valid"
},
"content": {
"$type": "pub.leaflet.content",
"pages": [
{
"$type": "pub.leaflet.pages.linearDocument",
"blocks": [
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://bsky.app/hashtag/atprotodev"
}
],
"index": {
"byteEnd": 38,
"byteStart": 26
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
],
"index": {
"byteEnd": 64,
"byteStart": 59
}
}
],
"plaintext": "Today it's likely just us #atprotodevs who want to see the at:// uris behind the interesting or useful parts of the atproto-powered sites we visit, but I think we need an agreed way to markup HTML so browser extensions can hook in."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "I want your feedback in determining if this suits, and if it does, implementing it on your sites, so the convention spreads!"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Using RDFa"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://www.w3.org/TR/rdfa-primer/#multiple-items"
}
],
"index": {
"byteEnd": 51,
"byteStart": 42
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://github.com/jphastings/where-its-AT"
}
],
"index": {
"byteEnd": 82,
"byteStart": 65
}
}
],
"plaintext": "A short while back I prototyped this with RDFa tags, and built a browser extension to show off that data. It was as simple as adding two attributes to an HTML element representing atproto data:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "html",
"plaintext": "<div typeof=\"schema:Thing\" resource=\"at://uri\">\n Some element showing data derived from atproto data\n</div>",
"syntaxHighlightingTheme": "solarized-light"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://sts2.byjp.me"
}
],
"index": {
"byteEnd": 49,
"byteStart": 20
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://github.com/jphastings/where-its-AT"
}
],
"index": {
"byteEnd": 78,
"byteStart": 65
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://addons.mozilla.org/en-GB/firefox/addon/where-it-s-at/"
}
],
"index": {
"byteEnd": 105,
"byteStart": 98
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://chromewebstore.google.com/detail/where-its-at/oemnpmaojhkhbdokgndacapnpmmlmfni?authuser=0&hl=en-GB"
}
],
"index": {
"byteEnd": 113,
"byteStart": 107
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://github.com/jphastings/where-its-AT/releases"
}
],
"index": {
"byteEnd": 121,
"byteStart": 115
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
],
"index": {
"byteEnd": 154,
"byteStart": 149
}
}
],
"plaintext": "I added these to my Slay the Spire 2 atproto site, and built the Where it's AT browser extension (Firefox, Chrome, Safari) to highlight & expose the at:// uris, as something of a demo."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.image",
"alt": "A screen recording showing the functionality of Where it's AT — highlighting at:// uris on the Slay the Spire 2 site, clicking through to PDSls, then altering the settings to use aturi instead, and demoing clicking through to there as well.",
"aspectRatio": {
"height": 497,
"width": 800
},
"fullBleed": true,
"image": {
"$type": "blob",
"ref": {
"$link": "bafkreig5cyyziyjskfpxyb3vfw72j4slpci47nmp4ea6lmre5mw36nxe2a"
},
"mimeType": "image/gif",
"size": 1108805
}
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Rationale"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "I think there are a number of ways you could use metadata like this:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.unorderedList",
"children": [
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://discourse.atprotocol.community/t/a-micro-review-lexicon-is-not/858"
}
],
"index": {
"byteEnd": 91,
"byteStart": 67
}
}
],
"plaintext": "Enabling \"review anything atproto\" type functionality (I'm already thinking about this here)"
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#link",
"uri": "https://discourse.atprotocol.community/t/an-at-uri-deeplink-lexicon/861"
}
],
"index": {
"byteEnd": 40,
"byteStart": 15
}
}
],
"plaintext": "Letting people deep-link to the original of that record, via the canonical or platform of their choice"
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#italic"
}
],
"index": {
"byteEnd": 174,
"byteStart": 172
}
}
],
"plaintext": "Letting devs see how atproto apps are put together (I was looking for how Popfeed & Bookhive store reviews recently, it took me a moment to realise Bookhive stores reviews on the book record — this would have shown me immediately!)"
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Annotating the HTML so Agents can see where the data has come from too"
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "…and I'm sure much more"
}
}
]
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Going further"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#italic"
}
],
"index": {
"byteEnd": 12,
"byteStart": 6
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#didMention",
"did": "did:plc:ewvi7nxzyoun6zhxrhs64oiz"
}
],
"index": {
"byteEnd": 71,
"byteStart": 59
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
],
"index": {
"byteEnd": 262,
"byteStart": 250
}
}
],
"plaintext": "If we really like this, I'd propose that the fine folks at @atproto.com ship an RDFa schema specifically for atproto (which could extend later to include permissioned spaces 😉) so that the syntax could provide clearer indications than the default schema:Thing I've used above."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "An illustrative (but not well thought through) example:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "html",
"plaintext": "<html prefix=\"at: https://atproto.com/ns#\">\n<body>\n <article\n typeof=\"at:Record\"\n resource=\"at://did:plc:abc123/app.bsky.feed.post/3kxy...\"\n >\n <!-- Something derived from that post -->\n </article>\n <cite>\n by\n <span typeof=\"at:Identity\" resource=\"did:plc:abc123\">Abc123</span>\n </cite>\n</html>\n",
"syntaxHighlightingTheme": "solarized-light"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
],
"index": {
"byteEnd": 84,
"byteStart": 22
}
},
{
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
],
"index": {
"byteEnd": 98,
"byteStart": 92
}
}
],
"plaintext": "It could also support <link typeof=\"at:Renders\" resource=\"at://did/collection/rkey\"> in the <head> to indicate that the whole page is a rendering of the provided at:// uri."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "This needs you!"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "If you like this & build atproto apps then please write here with feedback of what you'd use it for, what's missing, or what you'd change (and why!) — and you can just implement it on your site."
}
}
],
"id": "019e591d-1a83-700d-b4e6-6ef6d5676f55"
}
]
},
"description": "A call to use trivial RDFa markup in our HTML to indicate which records produced the elements on our pages.",
"path": "/3mmltnsb45s2n",
"publishedAt": "2026-05-24T11:17:09.931Z",
"site": "at://did:plc:ephkzpinhaqcabtkugtbzrwu/site.standard.publication/3lxehdht2rs24",
"tags": [
"atproto",
"html",
"rdfa"
],
"title": "Atproto markup for HTML"
}