mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-04-05 17:33:31 -04:00
166 lines
7.8 KiB
Markdown
166 lines
7.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Bibdle is a daily Bible verse guessing game built with SvelteKit 5. Players read a verse and try to guess which book of the Bible it comes from. The game provides feedback hints (Testament match, Section match, Adjacent book, etc.) similar to Wordle-style games. Progress is stored locally in the browser and a new verse is generated daily.
|
|
|
|
You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
|
|
|
(Make sure you use the Svelte agent to execute these commands)
|
|
|
|
## Available MCP Tools:
|
|
|
|
### 1. list-sections
|
|
|
|
Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths.
|
|
When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections.
|
|
|
|
### 2. get-documentation
|
|
|
|
Retrieves full documentation content for specific sections. Accepts single or multiple sections.
|
|
After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task.
|
|
|
|
### 3. svelte-autofixer
|
|
|
|
Analyzes Svelte code and returns issues and suggestions.
|
|
You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned.
|
|
|
|
## Tech Stack
|
|
|
|
- **Framework**: SvelteKit 5 with Svelte 5 (uses runes: `$state`, `$derived`, `$effect`, `$props`)
|
|
- **Styling**: Tailwind CSS 4
|
|
- **Database**: SQLite with Drizzle ORM
|
|
- **Auth**: Session-based authentication using Bun's built-in cryptographically secure functions
|
|
- **Deployment**: Node.js adapter for production builds
|
|
- **ML**: `@xenova/transformers` for verse embeddings (initialized in server hook) (currently disabled, was a test for a cancelled project)
|
|
|
|
## Development Commands
|
|
|
|
```bash
|
|
# Start development server
|
|
bun run dev
|
|
|
|
# Type checking
|
|
bun run check
|
|
bun run check:watch
|
|
|
|
# Run tests
|
|
bun test
|
|
bun test --watch
|
|
bun test tests/timezone-handling.test.ts # Run a single test file
|
|
|
|
# Build for production
|
|
bun run build
|
|
|
|
# Preview production build
|
|
bun run preview
|
|
|
|
# Database operations
|
|
bun run db:push # Push schema changes directly (avoid in prod)
|
|
bun run db:generate # Generate migrations
|
|
bun run db:migrate # Run migrations
|
|
bun run db:studio # Open Drizzle Studio GUI
|
|
```
|
|
|
|
## Critical: Date/Time Handling
|
|
|
|
**Bibdle is played by users across many timezones worldwide. The verse shown to a player must always be the verse for the calendar date at *their* location — not the server's timezone, not UTC. A user in Tokyo on Wednesday must see Wednesday's verse, even if the server (or a user in New York) is still on Tuesday.**
|
|
|
|
**NEVER use server time or UTC time for user-facing date calculations.**
|
|
|
|
- Get today's date client-side: `new Date().toLocaleDateString("en-CA")` → `YYYY-MM-DD`
|
|
- Pass the date to the server as a query param or POST body (`localDate`)
|
|
- Server-side date arithmetic must use UTC methods on the client-provided date string: `new Date(dateStr + 'T00:00:00Z')` + `setUTCDate`/`getUTCDate`
|
|
- `src/routes/+page.ts` has `ssr = false` so the load runs client-side with the true local date
|
|
- Never set the user-facing URL to include their date as a parameter. It should always be passed to an API route behind the scenes if needed.
|
|
|
|
### Streak Calculation
|
|
|
|
A streak counts consecutive calendar days (in the user's local timezone) on which the user completed the puzzle. The rules:
|
|
|
|
- The client passes its local date (`localDate`) to the streak API. The server never uses its own clock.
|
|
- A streak is **active** if the user has completed today's puzzle *or* yesterday's puzzle (they still have time to play today).
|
|
- Walk backwards from `localDate` through the `dailyCompletions` records, counting each day that has a completion. Stop as soon as a day is missing.
|
|
- A streak of 1 (completed only today or only yesterday, with no prior consecutive days) is **not displayed** — the minimum shown streak is 2.
|
|
- "Yesterday" and all date arithmetic on the server must use UTC methods on the client-provided date string to avoid timezone drift: `new Date(localDate + 'T00:00:00Z')`, then `setUTCDate`/`getUTCDate`.
|
|
|
|
## Architecture
|
|
|
|
### Database Schema (`src/lib/server/db/schema.ts`)
|
|
|
|
- **user**: `id`, `firstName`, `lastName`, `email` (unique), `passwordHash`, `appleId` (unique), `isPrivate`
|
|
- **session**: `id` (SHA-256 hash of token), `userId` (FK), `expiresAt`
|
|
- **daily_verses**: Cached daily verses with book ID, verse text, reference, and date
|
|
- **dailyCompletions**: Game results per user/date with guess count, grade, book; unique on `(userId, date)`
|
|
|
|
Sessions expire after 30 days and auto-renew when < 15 days remain.
|
|
|
|
### Bible Data (`src/lib/types/bible.ts`)
|
|
|
|
The `bibleBooks` array contains all 66 Bible books with metadata:
|
|
- Testament (old/new), Section (Law, History, Wisdom, Prophets, Gospels, Epistles, Apocalyptic)
|
|
- Order (1-66, used for adjacency detection)
|
|
|
|
### Daily Verse System (`src/routes/+page.server.ts`)
|
|
|
|
`getTodayVerse()` checks the database for today's date, fetches a verse if missing, caches permanently, and returns verse with book metadata.
|
|
|
|
### Game Logic (`src/routes/+page.svelte`)
|
|
|
|
**State Management:**
|
|
- `guesses` array stored in localStorage keyed by date: `bibdle-guesses-${date}`
|
|
- Each guess tracks: book, testamentMatch, sectionMatch, adjacent
|
|
- `isWon` derived from whether any guess matches the correct book
|
|
|
|
**Hint System, for share grid:**
|
|
- ✅ Exact match | 🟩 Section match | 🟧 Testament match | ‼️ Adjacent book | 🟥 No match
|
|
|
|
### Authentication System (`src/lib/server/auth.ts`)
|
|
|
|
- Token generation: base64-encoded random bytes; stored as SHA-256 hash in DB
|
|
- Cookie name: `auth-session`
|
|
- Anonymous users: identified by a client-generated ID; stats migrate on sign-up via `migrateAnonymousStats()`
|
|
- Apple Sign-In supported via `appleId` field
|
|
|
|
### Stats & Streak (`src/routes/stats/`)
|
|
|
|
- Stats page requires auth; returns `requiresAuth: true` if unauthenticated
|
|
- Streak calculated client-side by calling `GET /api/streak?userId=X&localDate=Y`
|
|
- Streak walk-back: counts consecutive days backwards from `localDate` through completed dates
|
|
- Minimum displayed streak is 2 (single-day streaks suppressed)
|
|
|
|
## API Endpoints
|
|
|
|
- `POST /api/daily-verse` — Fetch verse for a specific date
|
|
- `POST /api/submit-completion` — Submit game result with stats
|
|
- `GET /api/streak?userId=X&localDate=Y` — Current streak for user
|
|
- `GET /api/streak-percentile` — Streak percentile ranking
|
|
|
|
## Key Files
|
|
|
|
- `src/routes/+page.svelte` — Main game UI and client-side logic
|
|
- `src/routes/+page.server.ts` / `+page.ts` — Server load (verse) + client load (`ssr: false`)
|
|
- `src/routes/stats/+page.svelte` / `+page.server.ts` — Stats UI and server calculations
|
|
- `src/lib/server/auth.ts` — Session management, password hashing, anonymous migration
|
|
- `src/lib/server/bible-api.ts` — Random verse fetching from local XML Bible
|
|
- `src/lib/server/bible.ts` — Bible book utility functions
|
|
- `src/lib/types/bible.ts` — Bible books data and TypeScript types
|
|
- `src/lib/server/db/schema.ts` — Drizzle ORM schema
|
|
- `src/hooks.server.ts` — Session validation hook; initializes ML embeddings
|
|
- `tests/` — Bun test suites (timezone, game, bible, stats, share, auth migration)
|
|
|
|
## Environment Variables
|
|
|
|
Required in `.env`:
|
|
- `DATABASE_URL` — Path to SQLite database file (e.g., `./local.db`)
|
|
|
|
## Deployment
|
|
|
|
Uses `@sveltejs/adapter-node`. See `bibdle.service` systemd configuration.
|
|
|
|
## A Note
|
|
|
|
The main developer of this project is still learning a lot about developing full-stack applications. If they ask you to do something, make sure they understand how it will be implemented before proceeding.
|