Allows you to use Mastodon and Bluesky comments on your Lustre blog hexdocs.pm/chilp/
blog gleam lustre indieweb mastodon bluesky comments
1
fork

Configure Feed

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

Make up some notes for what I'll be adding in 1.0.1

+235
+235
NOTES.md
··· 1 + # Notes for 1.0.1: 2 + 3 + To do for this release: 4 + - [ ] [feat] Adding multiple back-ends 5 + - [ ] Bluesky, including a "[Comment via Bluesky]" button, and fetching comments from Bluesky posts in Bluesky-only mode or in a mixed mode with Mastodon. 6 + - [ ] ~~GitHub issues, including a "[Comment via GitHub]" button.~~ For a later release, as this will require a lot of work to implement the GraphQL queries and mutations. 7 + - [ ] Other platforms? Maybe? Depends on how much time I have, and how much demand there is for other platforms. 8 + - [ ] [fix] Adding `flex-wrap: wrap;` to `.widget .form-controls` to prevent the buttons from overflowing on smaller screens. 9 + 10 + ## [feat] Adding multiple back-ends 11 + 12 + ### Fetching a post from Bluesky 13 + This seems a little more complicated than fetching from Mastodon, but seems doable. 14 + 15 + From a uri, extract `handle` and `post_id` (e.g. `at://did:plc:abc123/app.bsky.feed.post/def456` -> `handle=abc123`, `post_id=def456`) 16 + 17 + Then, fetch the post using the Bluesky API: 18 + 19 + Firstly, resolve the handle to get the DID: 20 + https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=abc123 21 + 22 + This will return a DID (e.g. `did:plc:abc123`). 23 + 24 + Then, fetch a list of the user's posts: 25 + https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed?actor=did:plc:abc123&filter=posts_with_replies&limit=100 26 + 27 + This may require a few requests if the user has more than 100 posts, but we can paginate through them using the `cursor` parameter. 28 + 29 + Finally, find the post with the matching `post_id` (e.g. `def456`) in the list of posts and return it. 30 + 31 + Shaped like this: 32 + 33 + ```json 34 + { 35 + "12": { 36 + "post": { 37 + "uri": "at://did:plc:jgtfsmv25thfs4zmydtbccnn/app.bsky.feed.post/3mgrbiiadws2k", 38 + "cid": "bafyreif64xlr7idezspawc36x4dcatl655esh7eenc6mxuudfzymqirkyy", 39 + "author": { 40 + "did": "did:plc:jgtfsmv25thfs4zmydtbccnn", 41 + "handle": "strawmelonjuice.com", 42 + "displayName": "Mar !!", 43 + "pronouns": "she/her", 44 + "avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:jgtfsmv25thfs4zmydtbccnn/bafkreia45evsjv2oae3bceh6jezy7am7uobmjhstvmwgdb5fekvs6q5wry", 45 + "associated": { 46 + "chat": { 47 + "allowIncoming": "following" 48 + }, 49 + "activitySubscription": { 50 + "allowSubscriptions": "followers" 51 + } 52 + }, 53 + "labels": [], 54 + "createdAt": "2023-12-03T09:45:34.997Z" 55 + }, 56 + "record": { 57 + "$type": "app.bsky.feed.post", 58 + "createdAt": "2026-03-11T06:36:58.800Z", 59 + "langs": [ 60 + "en" 61 + ], 62 + "reply": { 63 + "parent": { 64 + "cid": "bafyreiagb7e2ia3lkzi2yqpvtu2qvcp52xz2ifspuhisluy6rcgzga3wwu", 65 + "uri": "at://did:plc:wgmcfsuu2o2hnbyf6eon5tw6/app.bsky.feed.post/3mgqujnkpf22n" 66 + }, 67 + "root": { 68 + "cid": "bafyreiagb7e2ia3lkzi2yqpvtu2qvcp52xz2ifspuhisluy6rcgzga3wwu", 69 + "uri": "at://did:plc:wgmcfsuu2o2hnbyf6eon5tw6/app.bsky.feed.post/3mgqujnkpf22n" 70 + } 71 + }, 72 + "text": "penith" 73 + }, 74 + "bookmarkCount": 0, 75 + "replyCount": 0, 76 + "repostCount": 0, 77 + "likeCount": 1, 78 + "quoteCount": 0, 79 + "indexedAt": "2026-03-11T06:36:58.954Z", 80 + "labels": [] 81 + }, 82 + "reply": { 83 + "root": { 84 + "uri": "at://did:plc:wgmcfsuu2o2hnbyf6eon5tw6/app.bsky.feed.post/3mgqujnkpf22n", 85 + "cid": "bafyreiagb7e2ia3lkzi2yqpvtu2qvcp52xz2ifspuhisluy6rcgzga3wwu", 86 + "author": { 87 + "did": "did:plc:wgmcfsuu2o2hnbyf6eon5tw6", 88 + "handle": "chitin.link", 89 + "displayName": "AUBURN", 90 + "avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreighu5b4perorcoytfdqjnbnlm424htrmmqojp5ayvoobhiw47hpma", 91 + "associated": { 92 + "chat": { 93 + "allowIncoming": "all" 94 + }, 95 + "activitySubscription": { 96 + "allowSubscriptions": "followers" 97 + } 98 + }, 99 + "labels": [], 100 + "createdAt": "2023-07-24T21:41:48.499Z" 101 + }, 102 + "record": { 103 + "$type": "app.bsky.feed.post", 104 + "createdAt": "2026-03-11T02:44:59.275Z", 105 + "embed": { 106 + "$type": "app.bsky.embed.images", 107 + "images": [ 108 + { 109 + "alt": "", 110 + "aspectRatio": { 111 + "height": 1125, 112 + "width": 2000 113 + }, 114 + "image": { 115 + "$type": "blob", 116 + "ref": { 117 + "$link": "bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4" 118 + }, 119 + "mimeType": "image/jpeg", 120 + "size": 942046 121 + } 122 + } 123 + ] 124 + }, 125 + "langs": [ 126 + "en" 127 + ], 128 + "text": "" 129 + }, 130 + "embed": { 131 + "$type": "app.bsky.embed.images#view", 132 + "images": [ 133 + { 134 + "thumb": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4", 135 + "fullsize": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4", 136 + "alt": "", 137 + "aspectRatio": { 138 + "height": 1125, 139 + "width": 2000 140 + } 141 + } 142 + ] 143 + }, 144 + "bookmarkCount": 0, 145 + "replyCount": 1, 146 + "repostCount": 0, 147 + "likeCount": 2, 148 + "quoteCount": 0, 149 + "indexedAt": "2026-03-11T02:45:05.575Z", 150 + "labels": [], 151 + "$type": "app.bsky.feed.defs#postView" 152 + }, 153 + "parent": { 154 + "uri": "at://did:plc:wgmcfsuu2o2hnbyf6eon5tw6/app.bsky.feed.post/3mgqujnkpf22n", 155 + "cid": "bafyreiagb7e2ia3lkzi2yqpvtu2qvcp52xz2ifspuhisluy6rcgzga3wwu", 156 + "author": { 157 + "did": "did:plc:wgmcfsuu2o2hnbyf6eon5tw6", 158 + "handle": "chitin.link", 159 + "displayName": "AUBURN", 160 + "avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreighu5b4perorcoytfdqjnbnlm424htrmmqojp5ayvoobhiw47hpma", 161 + "associated": { 162 + "chat": { 163 + "allowIncoming": "all" 164 + }, 165 + "activitySubscription": { 166 + "allowSubscriptions": "followers" 167 + } 168 + }, 169 + "labels": [], 170 + "createdAt": "2023-07-24T21:41:48.499Z" 171 + }, 172 + "record": { 173 + "$type": "app.bsky.feed.post", 174 + "createdAt": "2026-03-11T02:44:59.275Z", 175 + "embed": { 176 + "$type": "app.bsky.embed.images", 177 + "images": [ 178 + { 179 + "alt": "", 180 + "aspectRatio": { 181 + "height": 1125, 182 + "width": 2000 183 + }, 184 + "image": { 185 + "$type": "blob", 186 + "ref": { 187 + "$link": "bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4" 188 + }, 189 + "mimeType": "image/jpeg", 190 + "size": 942046 191 + } 192 + } 193 + ] 194 + }, 195 + "langs": [ 196 + "en" 197 + ], 198 + "text": "" 199 + }, 200 + "embed": { 201 + "$type": "app.bsky.embed.images#view", 202 + "images": [ 203 + { 204 + "thumb": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4", 205 + "fullsize": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:wgmcfsuu2o2hnbyf6eon5tw6/bafkreif4famkhzes4l6f4t3mald5k5eekmy6vx3rnt76kfar4vxro2iqs4", 206 + "alt": "", 207 + "aspectRatio": { 208 + "height": 1125, 209 + "width": 2000 210 + } 211 + } 212 + ] 213 + }, 214 + "bookmarkCount": 0, 215 + "replyCount": 1, 216 + "repostCount": 0, 217 + "likeCount": 2, 218 + "quoteCount": 0, 219 + "indexedAt": "2026-03-11T02:45:05.575Z", 220 + "labels": [], 221 + "$type": "app.bsky.feed.defs#postView" 222 + } 223 + } 224 + } 225 + } 226 + ``` 227 + 228 + 229 + This is a big chunk of data, but it contains all the information about the post, including the author, the text, the embed (if any), and the counts for bookmarks, replies, reposts, likes, and quotes. It also includes information about the reply (if it's a reply), including the root and parent posts. 230 + 231 + Should be enough to mix it into our Mastodon based comments! 232 + 233 + ### GitHub issues for comments 234 + 235 + GitHub uses GraphQL for this, I do not currently have the capacity to work on that.