# Bibdle Game Architecture Plan

## Overview

Bibdle is a daily Bible verse guessing game inspired by Wordle. Players guess the book of the Bible for a random daily verse. Features:

- Infinite guesses
- Feedback grid: Guess | Testament (Old/New) | Section | Proximity (! if adjacent book)
- Daily verse fetched from Bible API (`/data/web/random`) and cached in DB by calendar day (YYYY-MM-DD)
- Hierarchical book categorization for feedback

## Data Structures

### BibleBook Interface

```typescript
interface BibleBook {
  id: string; // e.g. 'GEN'
  name: string; // e.g. 'Genesis'
  testament: "old" | "new";
  section: string; // e.g. 'Law', 'Gospels'
  order: number; // Canonical position 1-66
  url: string;
}
```

### Full Books Array

Static data derived from provided JSON + hierarchy:

```typescript
export const bibleBooks: BibleBook[] = [
  {
    id: "GEN",
    name: "Genesis",
    testament: "old",
    section: "Law",
    order: 1,
    url: "https://bible-api.com/data/web/GEN",
  },
  {
    id: "EXO",
    name: "Exodus",
    testament: "old",
    section: "Law",
    order: 2,
    url: "https://bible-api.com/data/web/EXO",
  },
  // ... (all 66 books mapped similarly)
  // Full list to be implemented in src/lib/bible.ts
];
```

**Mapping Summary**:

- **Old Testament** (1-39):
  - Law (1-5): GEN-EXO-LEV-NUM-DEU
  - History (6-17): JOS-JDG-RUT-1SA-2SA-1KI-2KI-1CH-2CH-EZR-NEH-EST
  - Wisdom (18-22): JOB-PSA-PRO-ECC-SNG
  - Major Prophets (23-27): ISA-JER-LAM-EZK-DAN
  - Minor Prophets (28-39): HOS-JOL-AMO-OBA-JON-MIC-NAM-HAB-ZEP-HAG-ZEC-MAL
- **New Testament** (40-66):
  - Gospels (40-43): MAT-MRK-LUK-JHN
  - History (44): ACT
  - Pauline Epistles (45-57): ROM-1CO-2CO-GAL-EPH-PHP-COL-1TH-2TH-1TI-2TI-TIT-PHM
  - General Epistles (58-65): HEB-JAS-1PE-2PE-1JN-2JN-3JN-JUD
  - Apocalyptic (66): REV

### DailyVerse

```typescript
interface DailyVerse {
  id: string;
  date: string; // 'YYYY-MM-DD'
  bookId: string;
  text: string;
  reference: string; // e.g. 'John 3:16'
}
```

### Guess

```typescript
interface Guess {
  book: BibleBook;
  isCorrect: boolean;
  isAdjacent: boolean; // Math.abs(guess.order - correct.order) === 1
}
```

## Database Schema Additions

Extend [`src/lib/server/db/schema.ts`](src/lib/server/db/schema.ts):

```typescript
export const dailyVerses = sqliteTable("daily_verses", {
  id: text("id").primaryKey(),
  date: text("date").unique().notNull(), // YYYY-MM-DD
  bookId: text("book_id").notNull(),
  verseText: text("verse_text").notNull(),
  reference: text("reference").notNull(),
  createdAt: integer("created_at", { mode: "timestamp" }).defaultNow(),
});
```

## Key Services (Server-Side)

### 1. Bible Service [`src/lib/server/bible.ts`]

- Load `bibleBooks` array
- Methods: `getBook(id)`, `getBooksByTestament()`, `getBooksBySection()`, `isAdjacent(book1, book2)`

### 2. Bible API Service [`src/lib/server/bible-api.ts`]

```typescript
export async function fetchRandomVerse(): Promise<
  Omit<DailyVerse, "date" | "id">
> {
  const res = await fetch("https://bible-api.com/data/web/random");
  // Parse response to extract text, reference, bookId
}
```

### 3. DailyVerse Service [`src/lib/server/daily-verse.ts`]

```typescript
export async function getDailyVerse(
  date = getTodayDate()
): Promise<DailyVerse> {
  let verse = await db
    .select()
    .from(dailyVerses)
    .where(eq(dailyVerses.date, date))
    .get();
  if (!verse) {
    const apiVerse = await fetchRandomVerse();
    verse = await db
      .insert(dailyVerses)
      .values({
        ...apiVerse,
        date,
        id: crypto.randomUUID(),
      })
      .returning();
  }
  return verse;
}
```

## Frontend Components Structure

```
src/lib/components/
├── Game.svelte                 # Main game
├── VerseDisplay.svelte
├── BookSearch.svelte           # Autocomplete book selector
├── GuessesGrid.svelte          # Rows: Book | Testament | Section | !
└── Keyboard.svelte             # Virtual keyboard (optional)
```

## Game Flow

```mermaid
graph TD
  A[Load page] --> B[getDailyVerse()]
  B --> C[Display verse]
  C --> D[Book selector]
  D --> E[Submit guess]
  E --> F[Get feedback]
  F --> G[Add row to grid]
  G --> H{Correct?}
  H -->|Yes| I[Win screen]
  H -->|No| D
```

## Proximity Logic

```
isAdjacent(guess: BibleBook, correct: BibleBook): boolean {
  return Math.abs(guess.order - correct.order) === 1;
}
```

## Implemented Features

- ✅ Bible data structures & full books array in `src/lib/types/bible.ts`
- ✅ DB schema `daily_verses` & migration
- ✅ Bible API service with random + next 2 verses range fetch
- ✅ Daily verse loader in `+page.server.ts`
- ✅ Interactive UI in `+page.svelte`: search, guesses, 3-column feedback grid (Book/Testament/Section green/red), win screen
- ✅ Responsive Tailwind design

## Remaining / Future

- Stats tracking
- ✅ Share functionality
- Virtual keyboard
- Animations
- Multi-day history

## Updated Feedback Grid

3 columns (Close hidden secret):

- Book: green exact, red incorrect
- Testament: green match, red mismatch
- Section: green match, red mismatch

- Implement static bibleBooks array with full metadata
- Update DB schema + migrate
- Create server actions/load functions for daily verse
- Build core game logic
- UI implementation

This plan covers the core data structures and architecture. Ready for implementation?
