0
2
Gallery Creation Feature Design
Overview
Add gallery creation to hatk-template-grain, matching the UX flow from grain-next adapted to SvelteKit 5 + hatk.
Create Flow
Single /create route with 3 steps managed by Svelte 5 $state:
Step 1: Photo Selection
- "+" button in sidebar nav (desktop) and mobile bottom nav, visible only when authenticated
- Opens native file picker (images only, multiple selection, max 10)
- Client-side processing: resize to max 2000x2000px, compress to <900KB JPEG via binary search on quality
- Horizontal thumbnail strip with remove buttons
Step 2: Gallery Metadata
- Title input (required, max 100 chars) — enables "Next" button
- Description textarea (optional, max 1000 chars)
- Description parsed for rich text facets (@mentions, URLs, hashtags)
Step 3: Alt Text
- Each photo displayed with alt text input (max 1000 chars)
- Alt text is optional
- "Post" button publishes the gallery
Back navigation between steps preserves all state. Only a full page leave discards the draft.
Publish Sequence
- Upload each photo blob via hatk client (
agent.uploadBlob) - Create
social.grain.photorecords (blob ref, dimensions, alt text, createdAt) - Create
social.grain.galleryrecord (title, description, facets, createdAt) - Create
social.grain.gallery.itemrecords (gallery URI, photo URI, position index, createdAt) - On success: invalidate TanStack Query feed caches, navigate to home feed
Error Handling
- Blob upload failure: stop, show error on that photo, allow retry
- Gallery record failure: stop, orphaned blobs acceptable (AT Protocol handles this)
- Gallery item link failure: partial gallery visible, allow retry
- Disable "Post" button during publish, show progress indicator
New Files
app/routes/create/+page.svelte— 3-step create flowapp/lib/utils/image-resize.ts—processPhotos(),resizeImage(),readFileAsDataURL()app/lib/utils/rich-text.ts—parseTextToFacets()for mentions, URLs, hashtags
Modified Files
- Sidebar/nav components — add "+" create button (auth-gated)
app/lib/queries.ts— add mutation helpers for blob upload, photo/gallery/item creation
Constraints
- Max 10 photos per gallery
- Max 2000x2000px resolution
- Max 900KB per compressed image
- Title max 100 chars
- Description max 1000 chars
- Alt text max 1000 chars per photo
Draft State
No sessionStorage or external service needed. All draft state lives in +page.svelte via Svelte 5 $state runes since it's a single route.