A verse date is a player's local calendar day, spanning D-1 10:00Z
(UTC+14) through D+1 12:00Z (UTC-12). The old UTC end-of-day cutoff both
dropped late-night finishes in negative timezones and could persist a
partial day.
- Scope snapshot loads by the verse date column; use completedBefore only
to pin an in-progress point-in-time build.
- Gate persistence on isDayClosed (D+1 12:00Z); open days are computed
live and never written.
- Build the cron snapshot for latestClosedDate instead of EST yesterday,
and read the same date for the community page.
- Add all-time best single day to snapshot totals.
- Bump PAYLOAD_SCHEMA_VERSION to 4 and extend snapshot/window tests.
- Cap /feed.xml at the current America/New_York calendar day so
pre-scheduled future verses (and stray 2124 rows) can no longer
surface at the top of the feed
- Emit DST-aware RFC 822 pubDates (correct -04:00/-05:00 offset) instead
of a hardcoded EST offset, and parse calendar days as UTC so titles
no longer shift by one day on UTC hosts
- Add content-addressed ETag + Last-Modified with If-None-Match /
If-Modified-Since conditional handling
- Add atom:link rel=self, content:encoded, channel pubDate/generator/image
- Move RSS auto-discovery <link> into app.html: the root route sets
ssr=false, so the layout <svelte:head> link never reached the raw HTML
and feed readers could not discover /feed.xml
- Extract feed helpers into $lib/server/rss and add unit tests
146 tests covering evaluateGuess, grading, ordinals, bible data
integrity, section counts, share text generation, and stat
string helpers. Also fixes toOrdinal for 111-113 (was using
>= 11 && <= 13 instead of % 100 check).
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>
- 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>