Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Classic Hangman word-guessing game built with React + Hono on Val Town.
Visit the live URL and start guessing words!
- 4 Difficulty levels — Easy, Medium, Hard, Expert (each with different word pools, guess limits, and score multipliers)
- Scoring system — Base points × difficulty multiplier + time bonus − hint/wrong penalties
- Hint system — Reveal a letter at the cost of score points
- Statistics — Tracks wins, losses, streaks, best score, and per-difficulty breakdown
- Settings — Default difficulty, hint toggle, keyboard input toggle (persisted via localStorage)
- Physical keyboard — Type letters directly (A–Z) or use the on-screen keyboard
- Mobile friendly — Responsive layout with touch-friendly buttons
- Accessible — ARIA labels, keyboard navigation, screen reader support
Rendering mermaid diagram...
index.ts ← Hono server (serves HTML + static assets)
frontend/
root.tsx ← HTML shell
index.tsx ← React entrypoint
favicon.svg ← App icon
game/
types.ts ← TypeScript interfaces (shared contracts)
constants.ts ← Difficulty configs, scoring, defaults
words.ts ← Word lists by difficulty (100+ words)
engine.ts ← Pure game logic (guess, win/lose, score, hint)
components/
App.tsx ← Main app (useReducer state machine)
Home.tsx ← Menu / difficulty selection
GameScreen.tsx ← Active gameplay (hangman + word + keyboard)
HangmanDrawing.tsx ← Progressive SVG hangman figure
WordDisplay.tsx ← Letter slots (revealed / hidden)
Keyboard.tsx ← A–Z on-screen keyboard
Victory.tsx ← Win screen with score breakdown
GameOver.tsx ← Loss screen with word reveal
SettingsScreen.tsx ← Settings (difficulty, toggles)
StatsScreen.tsx ← Statistics dashboard
The engine (frontend/game/engine.ts) is 100% pure functions — no React dependency, fully testable:
selectWord()— Picks a random word by difficulty, avoiding recent repeatsisValidGuess()— Validates single A-Z letter, not already guessedcheckWin()— All unique letters guessed?checkLose()— Wrong guesses ≥ max?calculateScore()— Base × multiplier + time bonus − penaltiesgenerateHint()— Reveals one unrevealed letter, returns penaltyupdateStats()— Aggregates game result into statistics