0
2
Comments Feature Design
Overview
Add gallery detail page with a comment bottom sheet, matching grain-next's UX adapted to SvelteKit + hatk.
Gallery Detail Page
Route: /profile/[did]/gallery/[rkey]
- Auth required (server-side redirect like
/create) - Reuses existing
GalleryCardcomponent at the top - Comment icon on card opens the bottom sheet
- Server-side load fetches gallery data + comment thread
Comment Sheet (Bottom Sheet)
Slides up from bottom, overlays the page.
Layout
- Header: "Comments" title + close button
- Comment list: Scrollable, oldest-first. Roots first, replies indented below parent (single-level threading)
- Load earlier comments button at top (cursor-based pagination, 20 per page)
- Empty state: "No comments yet. Be the first!"
- Input bar fixed at bottom: user avatar, optional focus photo thumbnail (with clear button), text input, Post button
Each Comment
- Avatar, handle, comment text (with rich text facets), relative time
- Reply button, Delete button (owner only)
- Focus photo thumbnail (40x40) on the right if present
Posting
- User types text, taps Post
callXrpc('dev.hatk.createRecord', { collection: 'social.grain.comment', record: { text, subject, focus?, replyTo?, facets?, createdAt } })- Optimistically add comment to list
- Parse text for facets (reuse
rich-text.ts)
Replies
- Tap Reply → prefill input with
@handle, setreplyToUri, focus input - Reply appears indented below parent
Deletion
- Tap Delete →
callXrpc('dev.hatk.deleteRecord', { collection: 'social.grain.comment', rkey })→ remove from list
Server-Side: social.grain.unspecced.getGalleryThread
New XRPC endpoint in server/xrpc/:
- Params:
galleryUri,limit(default 20),cursor - Query:
social.grain.commentrecords wheresubject = galleryUri, sortedcreatedAt ASC - Hydration: Author profile (displayName, avatar), focus photo thumbnail
- Response:
{ comments: CommentView[], cursor?, totalCount }
New Files
server/xrpc/getGalleryThread.ts— XRPC endpointlexicons/social/grain/unspecced/getGalleryThread.json— Lexicon definitionapp/routes/profile/[did]/gallery/[rkey]/+page.svelte— Gallery detail pageapp/routes/profile/[did]/gallery/[rkey]/+page.server.ts— Auth guard + data loadingapp/lib/components/organisms/CommentSheet.svelte— Bottom sheet with comment list + inputapp/lib/components/molecules/Comment.svelte— Single comment display
Modified Files
app/lib/components/molecules/GalleryCard.svelte— Make comment button accept onclick handlerapp/lib/queries.ts— Add query for getGalleryThread
Constraints
- Comment text max 300 graphemes / 3000 bytes
- Single-level threading only (replies to comments, not replies to replies)
- 20 comments per page
- Auth required to view and post