Bluesky: thread support and quote posts #158

Open
opened 2026-06-23 13:35:01 +00:00 by jmiller · 2 comments
Owner

Summary

Bluesky supports thread chains (reply to own posts) and quote posts. For long articles, auto-splitting into a thread is valuable.

Thread Support

Reply chain via root + parent references:

{
  "reply": {
    "root": {"uri": "at://...", "cid": "..."},
    "parent": {"uri": "at://...", "cid": "..."}
  }
}

Auto-Thread Logic

  1. If message exceeds 300 graphemes, split at sentence boundaries
  2. First post is the root
  3. Subsequent posts reply to the previous one
  4. Last post includes the article URL

Quote Posts

Embed type app.bsky.embed.record:

{
  "embed": {
    "$type": "app.bsky.embed.record",
    "record": {"uri": "at://...", "cid": "..."}
  }
}

External Link Cards

Already supported via app.bsky.embed.external but our plugin doesn't use it. Should generate link cards with title/description/thumbnail.

Acceptance Criteria

  • Auto-thread when message exceeds 300 graphemes
  • Smart splitting at sentence boundaries
  • External link card embed for article URLs
  • Quote post support via params
## Summary Bluesky supports thread chains (reply to own posts) and quote posts. For long articles, auto-splitting into a thread is valuable. ## Thread Support Reply chain via `root` + `parent` references: ```json { "reply": { "root": {"uri": "at://...", "cid": "..."}, "parent": {"uri": "at://...", "cid": "..."} } } ``` ### Auto-Thread Logic 1. If message exceeds 300 graphemes, split at sentence boundaries 2. First post is the root 3. Subsequent posts reply to the previous one 4. Last post includes the article URL ## Quote Posts Embed type `app.bsky.embed.record`: ```json { "embed": { "$type": "app.bsky.embed.record", "record": {"uri": "at://...", "cid": "..."} } } ``` ## External Link Cards Already supported via `app.bsky.embed.external` but our plugin doesn't use it. Should generate link cards with title/description/thumbnail. ## Acceptance Criteria - [ ] Auto-thread when message exceeds 300 graphemes - [ ] Smart splitting at sentence boundaries - [ ] External link card embed for article URLs - [ ] Quote post support via params
Author
Owner

Implemented in commit 5fee5d7. Bluesky auto-threads: splitIntoThread() splits at sentence boundaries (. ! ? followed by space) with 30% minimum segment threshold before falling back to word breaks. Thread posts use reply.root + reply.parent references. External link card (app.bsky.embed.external) attached to the last post in thread with article title/description. Single posts under 300 chars use the simpler createPost() path. Dispatcher now passes article_title to all service plugins via params.

Implemented in commit `5fee5d7`. Bluesky auto-threads: `splitIntoThread()` splits at sentence boundaries (. ! ? followed by space) with 30% minimum segment threshold before falling back to word breaks. Thread posts use `reply.root` + `reply.parent` references. External link card (`app.bsky.embed.external`) attached to the last post in thread with article title/description. Single posts under 300 chars use the simpler `createPost()` path. Dispatcher now passes `article_title` to all service plugins via params.
Author
Owner

Testing Checklist

Migrated from #175

Test Steps

Auto-Thread

  • Messages under 300 chars post as single post (no thread)
  • Messages over 300 chars split into thread at sentence boundaries
  • Thread posts linked via reply.root + reply.parent references
  • Sentence splitting prefers ". " / "! " / "? " breaks
  • Falls back to word boundary when no sentence break in first 30%
  • Article URL attached to last post in thread
  • Root post URI stored as platform_post_id
  • Response includes thread_count

Link Card Embeds

  • Single posts include app.bsky.embed.external with article URL
  • Link card has article title and description
  • Thread posts: link card on last post only

Existing Behavior

  • Session caching still works (sha256 cache key)
  • Delete still works (rkey extraction from AT URI)

Namespace Fix

  • bluesky.xml namespace is Joomla\Plugin\MokoSuiteCross\Bluesky (not ${CLASS_NAME})

Related

  • #158 (implementation, closed)
## Testing Checklist _Migrated from #175_ ## Test Steps ### Auto-Thread - [ ] Messages under 300 chars post as single post (no thread) - [ ] Messages over 300 chars split into thread at sentence boundaries - [ ] Thread posts linked via reply.root + reply.parent references - [ ] Sentence splitting prefers ". " / "! " / "? " breaks - [ ] Falls back to word boundary when no sentence break in first 30% - [ ] Article URL attached to last post in thread - [ ] Root post URI stored as platform_post_id - [ ] Response includes thread_count ### Link Card Embeds - [ ] Single posts include app.bsky.embed.external with article URL - [ ] Link card has article title and description - [ ] Thread posts: link card on last post only ### Existing Behavior - [ ] Session caching still works (sha256 cache key) - [ ] Delete still works (rkey extraction from AT URI) ### Namespace Fix - [ ] bluesky.xml namespace is Joomla\Plugin\MokoSuiteCross\Bluesky (not ${CLASS_NAME}) ## Related - #158 (implementation, closed)
jmiller reopened this issue 2026-06-23 17:20:13 +00:00
Sign in to join this conversation.
No labels
Priority Medium
Type Feature
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MokoConsulting/MokoSuiteCross#158