Self-hosted e-commerce platform for atproto bazaar.whereditgo.diamonds

Add Leave a review box to the receipt page #26

Merged whereditgo.diamonds
targeting main
Merged opened by and assigned to whereditgo.diamonds
targeting main

Leave a review on the receipt page #

Buyers can now write a review from the receipt page (/dashboard/purchase/:receiptUri). It posts as an ordinary Bluesky post on their own account, with a link card back to the item.

What the buyer sees #

  • A "Leave a review" box styled as a mock of the post: their avatar, display name and @handle, the text box as the post body, and the item's link card (cover art, title, description, store domain).
  • A 300-character counter and a Post on Bluesky button. After posting it shows "Posted · View on Bluesky ↗".
  • If the buyer's sign-in predates the new permissions, the PDS refuses the post and the box shows a "Sign in again" link.

What gets posted #

An app.bsky.feed.post in the buyer's repo:

  • text: only what the buyer typed. Link, tag and mention facets come from RichText (@atproto/api). Mentions are resolved with our own handle resolution, not an AppView (ADR 0012). Handles that don't resolve stay plain text.
  • embed: an app.bsky.embed.external card linking to /item/:rkey/:slug, with the item's title and the first line of its description. The thumbnail is the item's cover art (the same image /api/catalog/cover/:rkey serves), uploaded as a blob to the buyer's repo. If the art is over 1 MB or the upload fails, the card posts without an image.

No Bazaar review record and nothing stored locally: the post is the review.

Changes #

  • Server
    • POST /api/atproto/review (routes/atproto.ts). Checks the receipt is in the buyer's own repo and the item is from this store, builds the card, uploads the thumbnail, and creates the post.
    • lib/atproto/review.ts builds the post and checks its text; tests in review.test.ts.
    • loadCoverArtBytes in productAssets.ts.
    • getItemOg and slugifyItemTitle are now exported from spaHtmlMeta.ts.
  • OAuth scopes: both sign-in flows now request repo:app.bsky.feed.post?action=create and blob:image/* (reviewPostOAuthScopes). Test added.
  • Client: LeaveReviewSection.tsx and lib/api/reviewApi.ts, wired into PurchaseDetailPage.tsx.
  • Docs: ADR 0027, with a row added to the ADR index.

Notes #

  • Existing sessions have to sign in again before they can post.
  • A buyer can post more than one review for the same purchase.
  • The card's link uses PUBLIC_WEB_ORIGIN (or APP_URL if that isn't set), so in local dev it points to 127.0.0.1.
  • Thumbnails are uploaded as image/webp. I haven't confirmed Bluesky shows them with a real post.

This pull request has no versions submitted yet.