wrdler / CLAUDE.md
Surn's picture
v0.2.12 Update documentation
78d662e

A newer version of the Streamlit SDK is available: 1.52.2

Upgrade

CLAUDE

Wrdler v0.2.12

Wrdler - Project Context

Project Overview

Wrdler is a simplified vocabulary puzzle game based on BattleWords:

  • Python project (Streamlit, Python 3.12.8)
  • 8x6 grid (8 columns Γ— 6 rows, one word per row, horizontal only)
  • No scope/radar visualization
  • 2 free letter guesses at game start (all instances revealed)
  • Word composition: 2 four-letter, 2 five-letter, 2 six-letter words per puzzle

Current Version: 0.2.12 Last Updated: 2025-12-21 Repository: https://github.com/Oncorporation/Wrdler.git Branch: main

Recent Changes (v0.2.12)

  • Layout changes for improved usability
  • Fixed static spinner graphic and favicon
  • Background enable/disable toggles improved
  • Sidebar disabled for streamlined UI

Current Features (v0.2.12)

Core Gameplay

  • 8x6 grid with 6 hidden words (one per row, horizontal only)
  • Players choose 2 free letters at start; all instances are revealed
  • Click cells to reveal letters or empty spaces
  • Guess words for points (word length + bonus for unrevealed letters)
  • Game ends when all words guessed or all word letters are revealed
  • Incorrect guess history display (toggleable, default enabled)
  • 10 incorrect guess limit per game
  • All leaderboard and challenge submissions use the latest st.session_state, including challenge overrides.

Game Modes

  1. Classic Mode: Allows consecutive guessing after correct answers
  2. Too Easy Mode: Single guess per reveal

Scoring Tiers

  • Legendary: 45+ points
  • Fantastic: 42-44 points
  • Great: 39-41 points
  • Good: 35-38 points
  • Keep practicing: < 35 points

Settings Page & Management

  • All game settings moved from sidebar to a dedicated Settings page (?page=settings)
  • Accessible via footer navigation (βš™οΈ Settings link)
  • Local JSON-based settings persistence in wrdler/settings/
  • Latest settings auto-loaded on startup
  • Enhanced settings management: create, update, rename, and delete settings files
  • Split "Save Settings" into "Create Settings" and "Update Settings" actions
  • Improved settings loading and user feedback
  • Default sound effects enabled in settings
  • New default configuration: classic-classic-full_sound_free_letters.json
  • Deprecated configuration removed: classic-classic-2.json

Word List Management

  • Sort and filter word lists (filter using assets/filter.txt blocklist)
  • Dialog display of removed words after filtering

Challenge Mode & Remote Storage

  • Short URL-based challenge sharing via ?game_id=<sid>
  • Each player gets different random words from same wordlist
  • Multi-user challenge leaderboards (top 5 display)
  • Remote storage via HuggingFace datasets
  • Word list difficulty calculation
  • "Show Challenge Share Links" toggle (default OFF)
  • Integration:
    • Automatic submission after game completion (opt-in via game over popup)
    • Challenge scores also contribute to daily/weekly leaderboards
    • Source tracking via source_challenge_id field
    • Unified JSON format with entry_type field (daily/weekly/challenge)
  • Challenge settings override defaults on load, and all submissions use the current session state.

Access: 'Leaderboard' link in the footer navigation at the bottom of the page

Daily & Weekly Leaderboards

  • Settings-Based Separation: Each unique settings combo creates separate leaderboard
    • Settings: game_mode, wordlist_source, show_incorrect_guesses, enable_free_letters, puzzle_options (spacer, may_overlap)
  • Auto Score Submission: Checks qualification for top 25 after game completion
  • Storage: Folder-based discovery at games/leaderboards/{daily|weekly}/{period}/{file_id}/settings.json
  • File ID Format: {wordlist_source}-{game_mode}-{sequence} (e.g., classic-classic-0)
  • Leaderboard Page: Four tabs (Today, Daily, Weekly, History) accessible via ?page=today|daily|weekly|history using query parameter routing and custom navigation links (not Streamlit native tabs)
  • Leaderboard files use UTC for all period boundaries.
  • When displaying daily leaderboards, show the UTC period as a PST date range.
  • Example: For UTC file date 2025-12-08, display: 2025-12-08 00:00:00 UTC to 2025-12-08 23:59:59 UTC and 2025-12-07 16:00:00 PST to 2025-12-08 15:59:59 PST The leaderboard expander label should show: Mon, Dec 08, 2025 4:00 PM PST – Tue, Dec 09, 2025 3:59:59 PM PST [settings badge]

Game Over Dialog & Leaderboard Integration

  • Game over dialog now integrates leaderboard submission and displays qualification results (rankings)
  • After submitting your score, the dialog will show if you qualified for the daily or weekly leaderboard and your rank

AI Word Generation

  • Topic-based word list generation via HuggingFace Spaces or local transformers
  • Automatic word saving (max 1000 words per file)
  • Retry mechanism (up to 3 attempts) for insufficient word counts
  • Fallback to dictionary words if AI unavailable

Audio & Visuals

  • Ocean-themed gradient background with wave animations
  • Toggleable background music with volume control (configured via Settings page, played globally)
  • Sound effects (hit/miss/correct/incorrect) with volume control (configured via Settings page, enabled by default)

PWA Support

  • Installable as Progressive Web App on desktop and mobile
  • Service worker for offline caching of static assets
  • Works offline for basic functionality

Footer Navigation

  • Navigation links to Leaderboard, Play, and Settings pages are in the footer (not the sidebar)
  • Footer navigation prevents reloading active pages

Technical Architecture

Technology Stack

  • Framework: Streamlit 1.52.1
  • Language: Python 3.12.8 (requires >=3.12, <3.13)
  • Remote Storage: huggingface_hub (>=0.20.0)
  • AI Generation: transformers, gradio_client
  • Testing: Pytest
  • Package Manager: UV or pip

Project Structure

wrdler/
β”œβ”€β”€ app.py                    # Streamlit entry point
β”œβ”€β”€ wrdler/                   # Main package
β”‚   β”œβ”€β”€ __init__.py          # Version: 0.2.10
β”‚   β”œβ”€β”€ models.py            # Data models (Coord, Word, Puzzle, GameState)
β”‚   β”œβ”€β”€ generator.py         # Puzzle generation with deterministic seeding
β”‚   β”œβ”€β”€ logic.py             # Game mechanics (reveal, guess, scoring)
β”‚   β”œβ”€β”€ ui.py                # Streamlit UI with query param routing
β”‚   β”œβ”€β”€ oauth.py             # HuggingFace OAuth utilities
β”‚   β”œβ”€β”€ settings_page.py     # Settings page UI (enhanced)
β”‚   β”œβ”€β”€ leaderboard.py       # Leaderboard system (daily/weekly)
β”‚   β”œβ”€β”€ leaderboard_page.py  # Leaderboard UI page
β”‚   β”œβ”€β”€ word_loader.py       # Word list management
β”‚   β”œβ”€β”€ word_loader_ai.py    # AI word generation
β”‚   β”œβ”€β”€ game_storage.py      # HF game storage wrapper
β”‚   β”œβ”€β”€ version_info.py      # Version display
β”‚   β”œβ”€β”€ modules/             # Shared utility modules
β”‚   β”‚   β”œβ”€β”€ __init__.py      # Module exports
β”‚   β”‚   β”œβ”€β”€ storage.py       # HuggingFace storage & URL shortener
β”‚   β”‚   β”œβ”€β”€ storage.md       # Storage module documentation
β”‚   β”‚   β”œβ”€β”€ constants.py     # Storage-related constants
β”‚   β”‚   └── file_utils.py    # File utility functions
β”‚   └── words/               # Word list files
β”‚       β”œβ”€β”€ classic.txt      # Default word list
β”‚       β”œβ”€β”€ fourth_grade.txt # Elementary word list
β”œβ”€β”€ tests/                   # Unit tests
β”œβ”€β”€ specs/                   # Documentation
β”œβ”€β”€ static/                  # PWA assets (manifest.json, service-worker.js)
β”œβ”€β”€ .env                     # Environment variables (HF credentials)
β”œβ”€β”€ pyproject.toml           # Project metadata
β”œβ”€β”€ requirements.txt         # Dependencies
β”œβ”€β”€ uv.lock                  # UV lock file
β”œβ”€β”€ Dockerfile               # Container deployment
β”œβ”€β”€ README.md                # User-facing documentation
β”œβ”€β”€ CLAUDE.md                # This file - project context for Claude
β”œβ”€β”€ GAMEPLAY_GUIDE.md        # User guide with tips and strategies

Page Navigation System

Uses query parameter-based routing (NOT Streamlit multi-page):

  • ?page=today|daily|weekly|history β†’ Leaderboard pages
  • ?page=settings β†’ Settings page
  • ?game_id=<sid> β†’ Challenge mode
  • No query params β†’ Main game page

Data Models

Core Classes

@dataclass
class Coord:
    x: int  # row, 0-based
    y: int  # col, 0-based

@dataclass
class Word:
    text: str
    start: Coord
    direction: Direction  # "H" or "V"
    cells: List[Coord]

@dataclass
class Puzzle:
    words: List[Word]
    may_overlap: bool
    spacer: int
    uid: str  # Unique identifier

@dataclass
class GameState:
    grid_rows: int  # 6 for Wrdler
    grid_cols: int  # 8 for Wrdler
    puzzle: Puzzle
    revealed: Set[Coord]
    guessed: Set[str]
    score: int
    last_action: str
    can_guess: bool
    game_mode: str
    points_by_word: Dict[str, int]
    start_time: Optional[datetime]
    end_time: Optional[datetime]

Environment Variables

Create a .env file in the project root:

# Challenge Mode & Leaderboards (Remote Storage)
HF_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxx  # HuggingFace API token with write access
HF_REPO_ID=YourUsername/YourRepo       # Dataset repo for challenge storage

# AI Word Generation
USE_HF_WORDS=false                     # Enable HF Space API for word generation
HF_WORD_LIST_REPO_ID=YourUsername/WordRepo  # Dataset repo for AI word lists

# OAuth Admin Access
ADMIN_USERS=username1,username2        # Comma-separated list of admin usernames
MAX_DISPLAY_ENTRIES=25                 # Max leaderboard entries to display (default: 25)

HF_REPO_ID Structure

HF_REPO_ID/
β”œβ”€β”€ shortener.json                   # URL shortener mappings
β”œβ”€β”€ games/{uid}/settings.json        # Challenge data (entry_type: "challenge")
└── games/leaderboards/
    β”œβ”€β”€ daily/{YYYY-MM-DD}/{file_id}/settings.json    # Daily leaderboards
    └── weekly/{YYYY-Www}/{file_id}/settings.json     # Weekly leaderboards

Development Workflow

Running Locally

# Install dependencies
uv pip install -r requirements.txt --link-mode=copy

# Run app
streamlit run app.py

Testing

pytest tests/

OAuth-Protected Settings Page

  • Settings page at ?page=settings, protected by HuggingFace OAuth (admin-only access)
  • Uses query parameter routing and checks admin access via ADMIN_USERS env var

Technical Notes

  • 8Γ—6 grid: grid_rows=6, grid_cols=8
  • Horizontal-only placement: One word per row
  • Query param routing: All pages use ?page=<name> system
  • Session state management: Heavy use of st.session_state
  • All leaderboard and challenge submissions use the latest st.session_state, including challenge overrides.

Deployment Platforms

  1. HuggingFace Spaces (Primary) - Dockerfile deployment with OAuth support
  2. Local Development - Streamlit run
  3. Docker - Containerized deployment

Git Configuration