- Frontend now reads replyTargets from isOwner API to resolve which
syndicator handles replies for each platform
- Build-time reply buttons get platform from URL heuristics as fallback
- enrichBuildTimeBadges upgrades to NodeInfo-resolved platform at runtime
Build-time reply cards rendered from webmention.io cache lack platform
provenance — they fall through URL heuristics to "webmention" (IndieWeb badge).
After conversations API data arrives with NodeInfo-resolved platform names,
enrichBuildTimeBadges() upgrades matching build-time cards with correct badges.
Also adds wm-provenance-badge class to all badge variants for reliable
DOM selection during enrichment.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
detectPlatform() now checks item.platform first (set by conversations
API via NodeInfo) before falling back to URL heuristics. Mastodon gets
its own badge, Bluesky gets its own, all other fediverse software
shows the Fediverse badge, and webmention.io data uses Bridgy URL
heuristics as fallback.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
- Remove self-mention filter (siteOrigin, isSelfMention) from webmentions.js
- Remove build-time self-mention filter from eleventy.config.js
- processWebmentions() now separates is_owner items and threads them
under parent interaction cards via threadOwnerReplies()
- owner:detected handler reduced to wireReplyButtons() only
- Remove loadOwnerReplies() and Alpine.store replies from comments.js
- Owner replies now come from conversations API with parent_url metadata
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
Owner replies sent via webmention-sender appear as webmentions on
the owner's own posts, showing the reply as a top-level entry instead
of threaded. Filter out any webmention whose source URL starts with
the site URL, in both build-time (eleventy.config.js) and client-side
(webmentions.js) rendering paths.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
Sending mp-syndicate-to: [] caused a server-side crash in jf2.js
where syndicateTo?.includes() received a non-iterable after
normalization. Only include the property when a target exists.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
Reply buttons on webmention interactions (Bluesky, Mastodon, IndieWeb)
now show an inline reply form directly under the card instead of
delegating to the hidden Comments section. The form posts via Micropub
with optional syndication targeting.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
- Add .wm-reply-btn button and .wm-owner-reply-slot to dynamically
created reply elements (parity with build-time Nunjucks template)
- Extract wireReplyButtons() so buttons are wired both on owner:detected
and after dynamic replies are appended (fixes timing gap)
- Use data-wired attribute to prevent double-wiring
- Show comment form for site owner (isOwner) not just IndieAuth users
- Fix "Signed in as" display to use ownerProfile when user is null
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
Two bugs fixed:
1. Reply buttons stayed hidden despite owner being detected. The
alpine:initialized event fires before the async checkOwner() fetch
resolves, so isOwner was always false when the handler ran. Fix:
dispatch custom owner:detected event from init() after both owner
check and owner replies are loaded.
2. Client-side webmentions not rendering on pages with zero build-time
webmentions. createWebmentionsSection() looked for .webmention-form
but the <details> element lacked that class, so the insertion point
was never found. Fix: add webmention-form class to the details element.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
The previous approach filtered client-side webmentions by timestamp
(only show items received after buildTime). This missed webmentions
that existed in the API but weren't included in the build-time cache
(e.g., Bluesky interactions via Bridgy that webmention.io stored but
the Eleventy cache plugin didn't fetch).
Now scans the DOM for actually-rendered items: author URLs in facepiles
for likes/reposts/bookmarks, and wm-url on reply cards. Only appends
webmentions not already visible, regardless of when they were received.
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
- Owner detection via Alpine.js global store (shared across components)
- Inline reply form for native comments with threaded display
- Micropub reply support for social/webmention interactions
- Provenance badges (Mastodon/Bluesky/ActivityPub/IndieWeb) on webmentions
- detectPlatform() for both build-time and client-side webmentions
- Reply buttons on webmention cards (owner only)
- Threaded owner reply display under matching webmentions
- Auto-expand comments section when comments exist
- Hide IndieAuth sign-in when admin session detected
- Author badge on owner comments and replies
Confab-Link: http://localhost:8080/sessions/184584f4-67e1-485a-aba8-02ac34a600fe
- Add skip-to-main-content link and main content ID target
- Add prefers-reduced-motion media queries for all animations
- Enhance visible focus indicators (2px offset, high-contrast ring)
- Replace ~160 text-surface-500 instances with text-surface-600/dark:text-surface-400
for 4.5:1+ contrast ratio compliance
- Add aria-hidden="true" to ~30+ decorative SVG icons across sidebars/widgets
- Convert facepile containers from div to semantic ul/li with role="list"
- Add aria-label to icon-only buttons (share, sort controls)
- Add sr-only labels to form inputs (webmention, search)
- Add aria-live="polite" to dynamically loaded webmentions
- Add aria-label with relative+absolute date to time-difference component
- Add keyboard handlers (Enter/Space) to custom interactive elements
- Add aria-label to nav landmarks (table of contents)
- Fix modal focus trap and dialog accessibility
- Fix lightbox keyboard navigation and screen reader announcements
Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88
- Change .avatar-row selector to .facepile to match build-time template
- Use facepile-avatar class for dynamically created avatar links
- Fix pluralization in updateCount (was only replacing the number,
now rebuilds the full "N Like/Likes" text correctly)
- Align ring color classes with build-time template
Conversations items are now included in build-time rendering via
conversationMentions data, so they no longer need a special exception
to bypass the timestamp filter. All items (webmention.io and
conversations) are now filtered equally by build timestamp.
The client-side webmentions.js was deduplicating by wm-id and source
URL, but conversations API and webmention.io use different ID formats
(string vs numeric). Add author URL + action type dedup to catch
cross-source duplicates (e.g., same Bluesky like reported by both).
Conversations items (from Mastodon/Bluesky/ActivityPub) were filtered
out by the client-side timestamp check that prevents duplicating
build-time webmentions. Since conversations data is never in the
build-time cache, bypass the filter for items with a platform field.
Fetch from both /webmentions/api/mentions and /conversations/api/mentions,
merge results with conversations items taking priority (richer metadata),
and display platform badges (Mastodon/Bluesky icons) on interaction cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change all webmention fetch URLs from /webmentions-api/api/mentions
to /webmentions/api/mentions to match the new @rmdes/indiekit-endpoint-webmention-io
plugin which replaces both the upstream viewer and the proxy plugin.
Build-time feed now fetches from local Indiekit API instead of
webmention.io directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old sessionStorage rate limiter prevented re-fetching on page refresh,
causing webmentions to disappear since they weren't in the build-time HTML.
Now caches the actual API response data with a 5-minute TTL so webmentions
render instantly from cache on refresh, while still fetching fresh data in
the background.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bridgy sends webmentions with inconsistent target URLs — articles
get trailing slashes but likes/bookmarks/reposts don't. The
client-side JS now queries both variants and deduplicates, matching
the build-time filter's behavior.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When no build-time webmentions exist, the first type to be processed
was silently dropped because createWebmentionsSection() only creates
the wrapper, not the type-specific section. After calling it, the code
tried to find the selector which still didn't exist.
Fixed by: create wrapper if needed, then always append the section
to the wrapper and get the row/list from the newly created section.
When build-time webmentions section doesn't exist, show ALL webmentions
from the API instead of filtering to only new ones.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add js/webmentions.js to fetch new webmentions from webmention.io API
- Supplements build-time cached webmentions with real-time data
- Shows new webmentions with 'NEW' badge and visual ring highlight
- Uses safe DOM methods to prevent XSS vulnerabilities
- Data attributes on webmentions container provide target URL and build time
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>