Adds Google OAuth alongside existing Apple and email/password auth. Follows the same patterns as Apple Sign-In: state cookie for CSRF, anonymousId migration, and user linking by email. Key differences: Google callback is a GET redirect (sameSite: lax) and uses a static client secret instead of a signed JWT.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Achievements system:
- Add src/lib/server/milestones.ts with full achievement definitions and
calculation logic (16 achievements: streaks, book set completions,
community milestones like Overachiever/Procrastinator/Outlier, and fun
ones like Prodigal Son, Extra Credit, Is This A Joke To You?)
- Wire calculateMilestones() into the progress page server load
- Replace the old ad-hoc milestone cards with a proper achievements grid
(3/4 col, uniform min-height cards, larger text)
- Change "With God, All Things Are Possible" from "every game solved in 1"
to "solve in 1 guess for each of the 66 books at least once"
Game page hint overlay:
- After a correct testament/section/first-letter match, display a subtle
text hint below the verse prompt (e.g. "It is in the Old Testament.")
- Hints fade in 2.8s after a guess (after the row flip animation)
- Hints are only shown to new players (fewer than 3 tracked wins) to
avoid being patronising to experienced players
Progress page:
- Hide Skill Growth chart with {#if false && showChart} pending rework
- Fix book tier colour scheme: explored=blue, mastered=purple, perfect=emerald
(was amber/emerald — now consistent across grid, legend, and stat cards)
- Simplify GuessesTable row colour: remove proximity gradient, use flat red
for wrong guesses
- Add "Come back tomorrow!" encouragement text in CountdownTimer for new
players (fewer than 3 wins)
- Fix GamePrompt text colour to always be gray-100
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracted game state management, share logic, and stats API calls into dedicated modules (game-persistence.svelte.ts, share.ts, stats-client.ts), and moved daily verse loading to client-side to fix timezone issues. Added a guesses column to daily_completions for cross-device state restoration for logged-in users, a new GET /api/stats endpoint, and a staging deploy script.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Refactored the daily verse system to properly handle users across different
timezones. Previously, the server used a fixed timezone (America/New_York),
causing users in other timezones to see incorrect verses near midnight.
Key changes:
**Server-side refactoring:**
- Extract `getVerseForDate()` into `src/lib/server/daily-verse.ts` for reuse
- Page load now uses UTC date for initial SSR (fast initial render)
- New `/api/daily-verse` POST endpoint accepts client-calculated date
- Server no longer calculates dates; uses client-provided date directly
**Client-side timezone handling:**
- Client calculates local date using browser's timezone on mount
- If server date doesn't match local date, fetches correct verse via API
- Changed verse data from `$derived` to `$state` to fix reactivity issues
- Mutating props was causing updates to fail; now uses local state
- Added effect to reload page when user returns to stale tab on new day
**Stats page improvements:**
- Accept `tz` query parameter for accurate streak calculations
- Use client's local date when determining "today" for current streaks
- Prevents timezone-based streak miscalculations
**Developer experience:**
- Added debug panel showing client local time vs daily verse date
- Added console logging for timezone fetch process
- Comprehensive test suite for timezone handling and streak logic
**UI improvements:**
- Share text uses 📜 emoji for logged-in users, 📖 for anonymous
- Stats link now includes timezone parameter for accurate display
This ensures users worldwide see the correct daily verse for their local
date, and streaks are calculated based on their timezone, not server time.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Brought in latest changes from main including:
- RSS feed implementation
- First letter edge case fixes
- Updated ranking formula
Resolved conflicts by:
- Combining .env.example variables from both branches
- Keeping auth version (3.0.0alpha)
- Preserving extended user schema from auth
- Keeping onMount umami approach and adding RSS feed link
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add test-specific Drizzle config and database connection
- Create test version of auth module using test database
- Add comprehensive integration tests for signin migration logic
- Add unit tests for deduplication algorithm
- Tests cover edge cases like multiple duplicates, timing, and error handling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes unique constraint on (anonymousId, date) to a regular index for better performance and to support the migration logic where duplicates may temporarily exist before deduplication.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>