From ddf272dac9f7f1c7a615259d4a916f2e55126627 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Sun, 15 Mar 2026 14:07:31 +0100 Subject: [PATCH] docs: document reply-to-interactions feature Add Reply-to-Interactions section to README with architecture diagram, threading mechanism, reply routing table, and plugin dependencies. Update CLAUDE.md with interaction API sources and reply architecture. Add conversations and comments plugins to the plugin integration table. Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe --- CLAUDE.md | 21 +++++++++++++---- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e8de46c..95ea1db 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -158,7 +158,7 @@ Most plugin-dependent data files: | `blog-sidebar.njk` | Sidebar for blog/post pages (recent posts, categories) | | `h-card.njk` | Microformat2 h-card for author identity | | `reply-context.njk` | Displays reply-to/like-of/repost-of/bookmark-of context with h-cite | -| `webmentions.njk` | Renders likes, reposts, replies from webmention.io + send form | +| `webmentions.njk` | Renders likes, reposts, replies from webmention.io + conversations API, with threaded owner replies | | `empty-collection.njk` | Fallback message when a post type collection is empty | #### Sections (_includes/components/sections/) @@ -315,14 +315,27 @@ Generates OpenGraph images for posts without photos using Satori (Yoga WASM → - **h-feed** (feed markup): Machine-readable post lists - **h-cite** (reply context): Cites external content in replies/likes/reposts -#### Webmentions +#### Webmentions & Interactions - Build-time caching via `@chrisburnell/eleventy-cache-webmentions` -- Client-side real-time fetching via `/js/webmentions.js` -- Displays likes, reposts, replies with avatars +- Client-side real-time fetching via `/js/webmentions.js` from three APIs: + - `/webmentions/api/mentions` — IndieWeb webmentions (webmention.io) + - `/conversations/api/mentions` — Mastodon/Bluesky/AP interactions (conversations plugin) + - `/comments/api/comments` — Native authenticated comments (comments plugin) +- Displays likes, reposts, replies with avatars and platform badges +- **Owner reply threading** — owner replies appear nested under parent interactions with amber Author badge - Send webmention form on every post - Legacy URL support via `urlAliases` (for micro.blog and old blog URLs) +#### Reply-to-Interactions Architecture + +The conversations API enriches its response with owner replies (`is_owner: true`, `parent_url`). The frontend's `threadOwnerReplies()` function matches `parent_url` to reply `
  • ` elements via `data-wm-url` attributes and inserts threaded reply cards into `wm-owner-reply-slot` divs. + +Reply routing is provenance-aware: +- **Mastodon/Bluesky replies** — `POST /micropub` with `mp-syndicate-to` for platform threading +- **IndieWeb webmention replies** — `POST /micropub` without syndication (webmention sent automatically) +- **Native comment replies** — `POST /comments/api/reply` (stored in comments collection) + #### IndieAuth - `rel="me"` links in `` for identity verification diff --git a/README.md b/README.md index b20af20..b68cce7 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Integrates with custom Indiekit endpoint plugins: | `@rmdes/indiekit-endpoint-podroll` | Podcast episode aggregator | | `@rmdes/indiekit-endpoint-rss` | RSS feed reader with MongoDB caching | | `@rmdes/indiekit-endpoint-microsub` | Social reader with channels and timeline | +| `@rmdes/indiekit-endpoint-conversations` | Multi-platform interaction aggregation + owner reply threading | +| `@rmdes/indiekit-endpoint-comments` | IndieAuth visitor comments with owner replies | ### Modern Tech Stack @@ -428,6 +430,72 @@ See `indiekit-deploy` repository for Docker Compose deployment with this theme a - [IndieAuth](https://indieauth.com/) — Authentication protocol - [Bridgy](https://brid.gy/) — Backfeed social interactions +## Reply-to-Interactions + +The theme supports threaded owner replies on all interaction types: IndieWeb webmentions, Mastodon/Bluesky backfills, and native authenticated comments. + +### How It Works + +``` +Visitor interaction (Mastodon reply, Bluesky like, webmention, native comment) + │ + v +Conversations API (/conversations/api/mentions) + │ Enriches response with owner replies from posts collection + │ Adds is_owner: true + parent_url for threading + v +webmentions.js (client-side) + │ processWebmentions() separates owner replies from regular interactions + │ Renders regular interactions (likes, reposts, replies) + │ threadOwnerReplies() inserts owner reply cards under parent interactions + v +Threaded display: + ┌─────────────────────────────────┐ + │ Jane Doe [Mastodon] Mar 11 │ + │ Great post! │ + │ [Reply] │ + │ ┌─────────────────────────────┐ │ + │ │ Ricardo Mendes [Author] │ │ + │ │ Thanks! │ │ + │ └─────────────────────────────┘ │ + └─────────────────────────────────┘ +``` + +### Key Files + +| File | Role | +|------|------| +| `js/webmentions.js` | Fetches interactions from 3 APIs (webmentions, conversations, comments), deduplicates, renders, and threads owner replies | +| `js/comments.js` | Alpine.js component for native comment form, IndieAuth flow, and inline reply UI | +| `_includes/components/webmentions.njk` | Server-side template with `data-wm-url` attributes and `wm-owner-reply-slot` divs for threading | + +### Threading Mechanism + +1. **`processWebmentions(allChildren)`** separates items with `is_owner: true` and `parent_url` from regular interactions +2. Regular interactions render normally (likes, reposts, reply cards) +3. Each reply `
  • ` gets a `data-wm-url` attribute matching the interaction's source URL +4. Each reply `
  • ` includes an empty `
    ` for threading +5. **`threadOwnerReplies(ownerReplies)`** matches each owner reply's `parent_url` to a reply `
  • `'s `data-wm-url`, then inserts an amber-bordered reply card into the slot + +### Reply Routing + +When the site owner clicks "Reply" on an interaction, the routing depends on the interaction's source: + +| Source | Route | Syndication | +|--------|-------|-------------| +| Mastodon reply | `POST /micropub` with `in-reply-to` | `mp-syndicate-to: mastodon` | +| Bluesky reply | `POST /micropub` with `in-reply-to` | `mp-syndicate-to: bluesky` | +| IndieWeb webmention | `POST /micropub` with `in-reply-to` | No syndication (webmention sent) | +| Native comment | `POST /comments/api/reply` | Stored in comments collection | + +### Plugin Dependencies + +| Plugin | Role | +|--------|------| +| [`@rmdes/indiekit-endpoint-conversations`](https://github.com/rmdes/indiekit-endpoint-conversations) | Serves interactions with owner reply enrichment (`is_owner`, `parent_url`) | +| [`@rmdes/indiekit-endpoint-comments`](https://github.com/rmdes/indiekit-endpoint-comments) | Handles native comment replies and owner detection (`/api/is-owner`) | +| `@rmdes/indiekit-endpoint-webmention-io` | Serves webmention.io data (likes, reposts, replies from IndieWeb) | + ## Troubleshooting ### Webmentions not appearing