Add Bluesky replies, quotes, and reposts to any web page. Handy for adding a comments section anywhere.
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix CSS custom property overrides, add moderation docs to README

Custom properties were declared on the inner .bsky-conversation div,
which blocked inheritance from the host element. Moved light-mode
defaults into var() fallbacks so overrides on <bsky-conversation>
cascade through correctly. Also added hide-reply usage docs to README.

Jim Ray 283f934a 56957300

+40 -15
+33
README.md
··· 108 108 - API failures degrade gracefully — the rest of the conversation still renders 109 109 - All user content is XSS-hardened through `escapeHtml()` 110 110 111 + ## Moderation 112 + 113 + The `hide-reply` script lets you hide replies or detach quote posts from conversations via the command line. It auto-detects the post type. 114 + 115 + ### Setup 116 + 117 + ```bash 118 + cp .env.example .env 119 + ``` 120 + 121 + Fill in your `ATPROTO_HANDLE` and `ATPROTO_APP_PASSWORD` (create an app password in Bluesky Settings > App Passwords). Then install the dev dependencies: 122 + 123 + ```bash 124 + npm install 125 + ``` 126 + 127 + ### Usage 128 + 129 + ```bash 130 + # Hide a reply (adds to threadgate hiddenReplies) 131 + npm run hide-reply https://bsky.app/profile/did:plc:.../post/... 132 + 133 + # Detach a quote post (adds to postgate detachedEmbeddingUris) 134 + npm run hide-reply https://bsky.app/profile/did:plc:.../post/... 135 + ``` 136 + 137 + The script auto-detects whether the URL is a reply or a quote post: 138 + 139 + - **Replies**: Walks up the thread to find the root post and adds the reply URI to the root post's `app.bsky.feed.threadgate` record. Equivalent to "Hide reply for everyone" on bsky.app. 140 + - **Quote posts**: Detects the embedded post and adds the quote URI to the root post's `app.bsky.feed.postgate` record. Equivalent to "Detach quote" on bsky.app. 141 + 142 + The authenticated user must own the root post being replied to or quoted. 143 + 111 144 ## License 112 145 113 146 MIT
+7 -15
bsky-conversation.js
··· 514 514 515 515 this.innerHTML = ` 516 516 <style> 517 - .bsky-conversation { 518 - --bsky-border-color: #e5e7eb; 519 - --bsky-muted-color: #6b7280; 520 - --bsky-link-color: black; 521 - --bsky-link-underline: rgba(82, 82, 91, 0.5); 522 - --bsky-link-hover: #2563eb; 523 - --bsky-link-underline-hover: rgba(59, 130, 246, 0.3); 524 - } 525 517 .dark .bsky-conversation { 526 518 --bsky-border-color: #374151; 527 519 --bsky-muted-color: #9ca3af; ··· 532 524 } 533 525 534 526 .bsky-conversation a { 535 - color: var(--bsky-link-color); 527 + color: var(--bsky-link-color, black); 536 528 text-decoration: underline; 537 - text-decoration-color: var(--bsky-link-underline); 529 + text-decoration-color: var(--bsky-link-underline, rgba(82, 82, 91, 0.5)); 538 530 font-weight: 400; 539 531 transition: color 150ms, text-decoration-color 150ms; 540 532 } 541 533 .bsky-conversation a:hover { 542 - color: var(--bsky-link-hover); 543 - text-decoration-color: var(--bsky-link-underline-hover); 534 + color: var(--bsky-link-hover, #2563eb); 535 + text-decoration-color: var(--bsky-link-underline-hover, rgba(59, 130, 246, 0.3)); 544 536 } 545 537 546 538 .bsky-conversation header { ··· 601 593 } 602 594 603 595 .bsky-conversation .handle { 604 - color: var(--bsky-muted-color); 596 + color: var(--bsky-muted-color, #6b7280); 605 597 } 606 598 607 599 .bsky-conversation .reply > p, ··· 615 607 gap: 0.75em; 616 608 margin-top: 0.25em; 617 609 font-size: smaller; 618 - color: var(--bsky-muted-color); 610 + color: var(--bsky-muted-color, #6b7280); 619 611 } 620 612 621 613 .bsky-conversation .thread { 622 614 list-style: none; 623 615 padding: 0 0 0 1.5em; 624 616 margin: 0.5em 0 0; 625 - border-left: 2px solid var(--bsky-border-color); 617 + border-left: 2px solid var(--bsky-border-color, #e5e7eb); 626 618 } 627 619 628 620 .bsky-conversation .thread .reply {