Skip to content

feat: Implement Bluesky card previews without additional dependencies#164

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/implement-bluesky-card-previews
Draft

feat: Implement Bluesky card previews without additional dependencies#164
Copilot wants to merge 3 commits intomainfrom
copilot/implement-bluesky-card-previews

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 25, 2026

When a post contains URLs but no images, the Bluesky strategy now automatically fetches Open Graph metadata from the first URL and creates an embed card (app.bsky.embed.external). Thumbnail images are fetched and uploaded when available. Failures are silently ignored so posts still succeed without card previews.

Implements the same feature as #162 but without adding any new dependencies — uses a regex-based HTML parser instead of metascraper.

Changes

  • src/strategies/bluesky.js:

    • Import BLUESKY_URL_FACET constant (already exported from bluesky-facets.js)
    • Add parseOpenGraphData(html) — extracts og:title, og:description, og:image from HTML via regex; falls back to the <title> element when og:title is absent
    • Add fetchOpenGraphData(url, signal) — fetches a URL and returns parsed OG metadata
    • Add createCardEmbed(options, session, facets, signal) — builds an app.bsky.embed.external object from the first URL facet, uploading thumbnail when present
    • In postMessage: add else branch to auto-generate card embed when no images are provided
  • tests/strategies/bluesky.test.js:

    • Add externalServer MockServer for https://example.com and register with FetchMocker
    • Add describe("post with auto card preview", ...) with 5 tests:
      • Basic card preview from URL with title and description
      • Card preview with thumbnail image upload
      • Graceful handling when OG fetch returns an error (no embed)
      • No card when post has no URLs
      • Card preview using <title> as fallback when og:title is not present

Relates to #161


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copy link
Copy Markdown
Contributor

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Let's use <title> as a fallback if og:title is not present.

Also, double-check if an image is required for a card preview or not. If it's required, then we should not create a card preview if there is no image.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 25, 2026

@copilot Let's use <title> as a fallback if og:title is not present.

Also, double-check if an image is required for a card preview or not. If it's required, then we should not create a card previ...

Done in bc80408. <title> is now used as a fallback when og:title is absent.

Regarding images: per the AT Protocol lexicon for app.bsky.embed.external, the thumb field is optional — a card preview can be created without an image. The current implementation already handles this correctly: if og:image is missing or the image fetch fails, the card is still created without a thumbnail.

Copilot AI requested a review from nzakas March 25, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants