···11-# Nuxt Minimal Starter
11+# finxol blog
22+33+This is the repo for finxol's blog.
44+55+All posts are in `content/`.
66+Configuration is in `blog.config.ts`.
77+88+## Technology stack
99+1010+- Nuxt v4
1111+- Nuxt Content
1212+- TailwindCSS
1313+- Deno (Deploy EA)
1414+1515+## Bluesky integration
1616+1717+Tracking PR: [#1](https://tangled.org/finxol.io/blog/pulls/1/)
1818+1919+Comments on this blog are directly integrated with Bluesky, the atproto-based micro-blogging social network.
2020+2121+This integration relies on the `@atcute/` library collection for interaction with Bluesky/atproto.
2222+2323+The idea was originally inspired from [natalie's blog](https://natalie.sh/posts/bluesky-comments/).
2424+Although I ended up using mostly the same tools and strategies, I didn't follow her post to build it here.
2525+2626+### How it works in practice
2727+2828+The author of the blog writes a post and publishes it.
2929+They can then post about it on Bluesky, find the post id, and add it to the `bskyCid` field in the post frontmatter.
3030+Any Bluesky post below the one identified will now be displayed at the bottom of the blog post, allowing for integrated conversation about the post.
3131+3232+### How it works technically
3333+3434+The [AT Protocol](https://atproto.com/) is an open internet protocol for social applications.
3535+All the data is decentralised and public ([for now](https://pfrazee.leaflet.pub/3lzhui2zbxk2b)).
3636+This openness allows us to reuse and build things based on that data very easily, in a built-in way, without hacky workarounds.
3737+3838+This integration works in several parts:
3939+4040+#### `app/util/atproto.ts`
4141+4242+Contains the utility functions for retrieving all replies to a post, and extracting a post id from an atproto uri.
4343+4444+Uses `@atcute/client` to fetch using the `app.bsky.feed.getPostThread` RPC on the Bluesky public API.
4545+Everything is strongly typed, although fetch errors are handled as `post not found` to make handling simpler in the Vue component.
4646+4747+#### `blog.config.ts`
4848+4949+The author DID is set blog-wide in the config file through `authorDid`, as it is primarily intended as a personal blog.
5050+If need be, I can always move the DID parameter to the post frontmatter, allowing for guest authors or secondary accounts too.
5151+5252+#### `content.config.ts`
5353+5454+Since the Bluesky post CID needs to be set for each blog post independently,
5555+I added a `bskyCid` field in the post frontmatter.
5656+5757+#### `app/components/BskyComments.vue`
5858+5959+This is the core component to display the replies.
6060+6161+The component simply fetches the replies by calling `getBskyReplies`, passing in the post CID passed as prop,
6262+and displays the content using the `BskyPost` component.
6363+6464+The reply, like, repost, and bookmark counts of the original Bluesky post are also displayed.
6565+26633-Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
6767+#### `app/components/BskyPost.vue`
46855-## Setup
6969+This component displays the post author, their avatar, the post content, and its stats beautifully.
67077-Make sure to install dependencies:
7171+Replies to replies are indented accordingly to visually thread replies together, using `BskyPost` recursively,
7272+with a `MAX_DEPTH` to set a limit to the number of replies to show.
87399-```bash
1010-# pnpm
1111-pnpm install
1212-```
13741414-## Development Server
7575+#### `app/pages/posts/[...slug].vue`
15761616-Start the development server on `http://localhost:3000`:
7777+The actual post page only had some minor adjustments to integrate the `BskyComments` component,
7878+using a `Suspense` boundary with a fallback to avoid blocking the rendering of the actual content.
17791818-```bash
1919-# pnpm
2020-pnpm dev
2121-```
8080+#### Others
22812323-## Production
8282+Some other files saw modifications, to adapt to this integration addition, allowing for visual consistency.
24832525-Build the application for production:
8484+### Advantages of the approach
26852727-```bash
2828-# pnpm
2929-pnpm build
3030-```
8686+Since this blog is built with Nuxt, everything is SSRed.
8787+This makes the Bluesky integration a wonderful progressive enhancement.
8888+The comments will still display and show up as intended if the client has Javascript disabled,
8989+without blocking rendering of the actual content through the use of a `Suspense` boundary.
31903232-Locally preview production build:
9191+Using Bluesky as a comment platform allows me to integrate conversations about my posts directly alongside them,
9292+without bearing the load of moderation and user accounts.
33933434-```bash
3535-# pnpm
3636-pnpm preview
3737-```
9494+### Limitations
38953939-Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
9696+As briefly mentioned, fetch errors are normalised to `#notFoundPost`,
9797+this could be refined for better reporting in the UI.
9898+9999+This integration also only handles plain text content.
100100+All embedded and rich media is effectively ignored for now.
101101+102102+## Install locally
103103+104104+```sh
105105+# Install dependencies
106106+pnpm i
107107+108108+# Run the development server
109109+deno task dev
110110+111111+# Build for production
112112+deno task build
113113+114114+# Deploy to Deno Deploy EA. Add `--prod` to deploy to production
115115+deno deploy
116116+```