{
  "path": "/@aka.dad/3mg5ejw7eil23",
  "site": "https://unthread.at",
  "$type": "site.standard.document",
  "title": "Continue reading on Unthread",
  "content": {
    "$type": "at.unthread.content",
    "content": "# Unthread\n\nI built a TwitLonger for Bluesky. Write as much as you want, it saves to your repo as a `site.standard.document` record, then posts a teaser to your feed with a link back.\n\n### Why\n\nThe 300 character limit is fine most of the time. Sometimes it's not. I didn't want to make a thread. Hence the name.\n\n### The nerdy bit\n\nI'm a Laravel dev, so naturally I overthought this. Instead of a normal backend that stores your OAuth tokens and posts on your behalf, I went a different route:\n\n- OAuth starts on the server (AT Protocol requires a confidential client), but after the callback, everything goes to the frontend. The backend stores nothing.\n\n- All XRPC calls go through your PDS using *service proxying*. Your PDS verifies you, signs a JWT, and forwards it to Unthread. The backend just checks that JWT, no tokens, no sessions.\n\n- Records get created client-side directly to your PDS.\n\nBasically the backend is a stateless bridge. Your tokens stay in your browser, your content stays in your repo.\n\n### Standard.site\n\nUnthread uses [Standard.site](https://standard.site)'s `site.standard.document` lexicon: the growing standard for long-form content on AT Protocol. Other apps like [Offprint](https://offprint.app), [pckt.blog](https://pckt.blog), and [Leaflet](https://leaflet.pub) can read your posts too.\n\nOne detail: Unthread creates \"loose documents\" without a publication record. This is valid per the spec, the `site` field accepts a URL, not just an AT-URI. \n\nThis being an MVP, we haven't implemented the validation portion of the Standard.site spec, nor have we created our content lexicon yet.\n\n### Try it\n\nStill early. Minimal markdown editor with @mention autocomplete, multi-account support, drafts. Let me know what's broken or missing.\n\n[@aka.dad](https://aturi.to/did:plc:eob75vcjtmbaef2tn4evc4sl)"
  },
  "createdAt": "2026-03-04T00:45:51.466Z",
  "bskyPostRef": {
    "cid": "bafyreihxjsp2nauokveuhohvlmmq3qiuhstzdf2fve7xx3vhyqpipo2lfu",
    "uri": "at://did:plc:eob75vcjtmbaef2tn4evc4sl/app.bsky.feed.post/3mg72m6voxu2l",
    "$type": "com.atproto.repo.strongRef"
  },
  "publishedAt": "2026-03-04T00:45:51.466Z",
  "textContent": "Unthread\nI built a TwitLonger for Bluesky. Write as much as you want, it saves to your repo as a site.standard.document record, then posts a teaser to your feed with a link back.\nWhy\nThe 300 character limit is fine most of the time. Sometimes it's not. I didn't want to make a thread. Hence the name.\nThe nerdy bit\nI'm a Laravel dev, so naturally I overthought this. Instead of a normal backend that stores your OAuth tokens and posts on your behalf, I went a different route:\nOAuth starts on the server (AT Protocol requires a confidential client), but after the callback, everything goes to the frontend. The backend stores nothing.\nAll XRPC calls go through your PDS using service proxying. Your PDS verifies you, signs a JWT, and forwards it to Unthread. The backend just checks that JWT, no tokens, no sessions.\nRecords get created client-side directly to your PDS.\nBasically the backend is a stateless bridge. Your tokens stay in your browser, your content stays in your repo.\nStandard.site\nUnthread uses Standard.site's site.standard.document lexicon: the growing standard for long-form content on AT Protocol. Other apps like Offprint, pckt.blog, and Leaflet can read your posts too.\nOne detail: Unthread creates \"loose documents\" without a publication record. This is valid per the spec, the site field accepts a URL, not just an AT-URI. \nThis being an MVP, we haven't implemented the validation portion of the Standard.site spec, nor have we created our content lexicon yet.\nTry it\nStill early. Minimal markdown editor with @mention autocomplete, multi-account support, drafts. Let me know what's broken or missing.\n@aka.dad"
}