Problem: Users spend time carefully choosing their preferred glosses for each word. These selections must be saved so they're not lost when the popup closes or the page refreshes.
Solution: Two-layer persistence — localStorage for instant offline access, plus server-side storage for authenticated users so selections sync across devices.
Not included: Cloud sync between multiple accounts, or sharing selections with other users. Selections are personal and per-user.
When a user selects a gloss in the interlinear popup, the selection is immediately saved. The next time they open the popup for the same verse, their previous selections are restored.
User flow:
Merge behavior: When both localStorage and server have selections for the same verse, server data wins (server is the source of truth for authenticated users).
Edge cases:
No dedicated UI — persistence is invisible. Users simply see their selections restored when they return to a verse.
Layer 1 — localStorage:
bibleweb_translationsRecord<string, string> where key = ${bookId}-${chapter}-${verse}-${wordPosition}, value = selected glossloadTranslations()selectMeaning() call via persistTranslations()Layer 2 — Server (authenticated only):
loadFromServer(bookId, chapter, verse) fetches GET /api/word-selections/{bookId}/{chapter}/{verse}syncToServer() calls POST /api/word-selections/... with {wordPosition, selectedGloss}DELETE requestDB table: word_selections
userId, bookId, chapter, verse, wordPosition, selectedGloss, updatedAt(userId, bookId, chapter, verse, wordPosition)onConflictDoUpdateUser ID: Authenticated users use session user ID. Anonymous users get a cookie-based ID via getUserId(cookies).
Files:
apps/web/src/lib/components/bible/InterlinearPopup.svelte — load/save logicapps/web/src/routes/api/word-selections/[bookId]/[chapter]/[verse]/+server.ts — GET/POST/DELETE APIapps/web/src/lib/server/queries/word-selections.ts — saveWordSelection() with upsertCurrent: DONE Milestone: v3 Priority: Core — without persistence, gloss selection would be useless
History:
Dependencies: