Summary
When publishing to Bluesky via crier publish ... --to bluesky (or the equivalent MCP tool), the resulting post lacks facets in the AT Protocol record. As a result:
- URL text appears in the post but is not clickable
- #hashtags are not indexed by tag feeds (they render as plain text)
The link-card embed at the bottom still works, but the in-text URL and hashtag annotations don't.
Reproduction
Running v2.0.2 on Windows + Python 3.13:
crier publish my-post.md --to bluesky
--rewrite "Why .NET for a database? Read more at
https://example.com #dotnet #database"
--rewrite-author "user"
Then inspect the resulting record (via AT Proto getRecord or the atproto SDK): the facets field is absent. Same behavior reproduces via the MCP server (crier mcp → crier_publish tool).
Root cause
crier/platforms/bluesky.py (function Bluesky.publish) builds the record with text + embed but no facets. The embed produces the link-card preview only; it does not affect inline text rendering or tag indexing. Per the AT Protocol Rich Text spec (https://atproto.com/specs/atp#facets), app.bsky.feed.post records need a facets: [] array with UTF-8 byte-offset annotations for URLs (app.bsky.richtext.facet#link) and tags (app.bsky.richtext.facet#tag).
Suggested fix
Small helper that parses text for URLs and #tag spans, computes UTF-8 byte offsets, and appends them to record["facets"]. Byte offsets are non-negotiable because rewrites often contain µ, →, em-dashes — char/byte counts diverge.
Suggested fix
Small helper that parses text for URLs and #tag spans, computes UTF-8 byte offsets, and appends them to record["facets"]. Byte offsets are non-negotiable because rewrites often contain µ, →, em-dashes — char/byte counts diverge.
Summary
When publishing to Bluesky via crier publish ... --to bluesky (or the equivalent MCP tool), the resulting post lacks facets in the AT Protocol record. As a result:
The link-card embed at the bottom still works, but the in-text URL and hashtag annotations don't.
Reproduction
Running v2.0.2 on Windows + Python 3.13:
crier publish my-post.md --to bluesky
--rewrite "Why .NET for a database? Read more at
https://example.com #dotnet #database"
--rewrite-author "user"
Then inspect the resulting record (via AT Proto getRecord or the atproto SDK): the facets field is absent. Same behavior reproduces via the MCP server (crier mcp → crier_publish tool).
Root cause
crier/platforms/bluesky.py (function Bluesky.publish) builds the record with text + embed but no facets. The embed produces the link-card preview only; it does not affect inline text rendering or tag indexing. Per the AT Protocol Rich Text spec (https://atproto.com/specs/atp#facets), app.bsky.feed.post records need a facets: [] array with UTF-8 byte-offset annotations for URLs (app.bsky.richtext.facet#link) and tags (app.bsky.richtext.facet#tag).
Suggested fix
Small helper that parses text for URLs and #tag spans, computes UTF-8 byte offsets, and appends them to record["facets"]. Byte offsets are non-negotiable because rewrites often contain µ, →, em-dashes — char/byte counts diverge.
Suggested fix
Small helper that parses text for URLs and #tag spans, computes UTF-8 byte offsets, and appends them to record["facets"]. Byte offsets are non-negotiable because rewrites often contain µ, →, em-dashes — char/byte counts diverge.