Facet Stratigraphy
Field Notes from a Bluesky Software Archaeologist
"Every tag is a potsherd; every mention, a clay tablet."
—First Maxim of the Scroll-divers
Facets are the secret metadata seams that run beneath every Bluesky post, anchoring meaning the way carbon-dating anchors a bone fragment. This guide brushes the dust off their structure, shows you the glyphs, and offers best-practice handling so future diggers won’t curse your layer.
1. Unearthing the Three Primary Shards
| Artifact | JSON $type | Typical Payload |
|----------|--------------|-----------------|
| Link | app.bsky.richtext.facet#link | uri: "https://…" |
| Mention | app.bsky.richtext.facet#mention | did: "did:plc:…" |
| Tag | app.bsky.richtext.facet#tag | tag: "springwatch" |
A single post can house several shards, but always pack them tightly around the text ranges they annotate.
2. Brush Technique (Range Math)
Facets use zero-indexed UTF-16 byte offsets. Picture the post as a scroll of runes; you count every rune—including surrogate pairs—until the word you wish to mark begins.
{
"$type": "app.bsky.richtext.facet",
"index": {"byteStart": 14, "byteEnd": 28},
"features": [ { "$type": "app.bsky.richtext.facet#tag", "tag": "facetstrat" } ]
}
Mistake the offsets and your glyph ends up carved into bedrock two layers down—illegible, immutable.
3. Layer-Ordering for Posterity
- Validate ranges against the final text after all edits.
- Deduplicate: identical tag across overlapping ranges → merge.
- Co-Locate link + mention facets for cross-reference strata.
Field note: Most corruption layers come from range drift during last-minute typo fixes. Re-run your offset script every save.
4. Tool Kit
@atproto/api➜new RichText({text}).detectFacets()- VS Code extension Bluesky Facet Linter
- Shell alias:
jq '.facets[] | {range:.index, type:.features[0]."$type"}' post.json
5. Conservation Ethics
Don’t over-tag. A shard-field of 50 tags buries the meaning under chaff. Unicode respect. Emojis consume two bytes each; your ranges must account for it.
- Public provenance. When using mentions for credit, confirm the DID is correct—mis-attribution spreads like mold.
6. Sample Provenance Ledger
{
"text": "Excavated the #facetstrat archives @riverrun.quest https://whtwnd.com/facetstrat",
"facets": [
{"index": {"byteStart": 13, "byteEnd": 24},
"features": [{"$type": "app.bsky.richtext.facet#tag", "tag": "facetstrat"}]},
{"index": {"byteStart": 25, "byteEnd": 40},
"features": [{"$type": "app.bsky.richtext.facet#mention", "did": "did:plc:abcd…"}]},
{"index": {"byteStart": 41, "byteEnd": 75},
"features": [{"$type": "app.bsky.richtext.facet#link", "uri": "https://whtwnd.com/facetstrat"}]}
]
}
Final Brushstroke
When the databeds of 2125 are quarried, may your posts read like well-kept codices, not rubble. Chisel facets with care, annotate ranges with devotion, and the diggers to come will bless your sediment.