MCP test repository
  • JavaScript 95.3%
  • CSS 4.2%
  • HTML 0.5%
Find a file
2026-08-16 19:22:05 -04:00
.opencode Add Bad Wordle game 2026-08-14 19:20:08 -04:00
data Accept Urban Dictionary words as valid words 2026-08-16 13:48:09 -04:00
openspec Archive remove-word-pool 2026-08-16 19:22:05 -04:00
src Remove word-pool submission feature 2026-08-16 19:11:15 -04:00
test Remove word-pool submission feature 2026-08-16 19:11:15 -04:00
vendor Upgrade visual design to Neon Glass Noir 2026-08-15 16:58:17 -04:00
.gitignore Add Bad Wordle game 2026-08-14 19:20:08 -04:00
index.html Upgrade visual design to Neon Glass Noir 2026-08-15 16:58:17 -04:00
package.json Add Bad Wordle game 2026-08-14 19:20:08 -04:00
README.md Remove word-pool submission feature 2026-08-16 19:11:15 -04:00
style.css Add hint button with three escalating hints 2026-08-16 18:16:26 -04:00

Bad Wordle

A single-player Wordle-loop browser game with an offensive vocabulary. No server, no accounts, no build step — plain HTML + vendored Phaser 4.

Content warning: the answer words are raunchy. The game shows a content warning gate on first visit (remembered in localStorage).

Look & feel

The game is styled "Neon Glass Noir": a near-black indigo base with glass-panel tiles and keys, neon magenta/violet/teal accents, drifting ambient glow blobs, and a slow color-cycling title. All SFX are synthesized at runtime with the Web Audio API (no audio files).

  • Fonts: two OFL faces are vendored in vendor/fonts/ — Unbounded (display) and Space Grotesk (text) — so the look works fully offline.
  • Mute: a speaker button in the top-right toggles sound, persisted in localStorage (bad-wordle:muted); the game starts muted if that flag is set.
  • Crisp on HiDPI: the canvas backs at up to 2× device pixel ratio; text and panels are baked at that scale.
  • Canvas fallback: append ?canvas to force the Canvas renderer (used automatically when WebGL is unavailable); WebGL-only ambient garnish is skipped.

Run it

Any static file server works. From the repo root:

python3 -m http.server 8888
# then open http://127.0.0.1:8888/

The app must be served over HTTP (not file://) because it loads ES modules.

How to play

  • Guess the 5-letter answer in 6 tries.
  • Letters are validated against the standard American-English 5-letter dictionary or the curated Urban Dictionary 5-letter word list — a guess that isn't in either list is rejected.
  • Green = right letter, right place. Yellow = right letter, wrong place. Gray = not in the word.
  • On-screen keyboard or physical keyboard both work.
  • After a win or loss, an overlay shows the result. If the word has a bundled Urban Dictionary definition (every word from the bundled urban list) it also shows that definition (with credit). Words without a bundled definition show no definition line.
  • Click NEW ROUND for a fresh answer (never the same word twice in a row).

Word lists

Three bundled lists in data/:

  • dictionary-words.json — plain JSON array of ~16k standard American-English 5-letter words. The first "valid word" source (see below).
  • urban-words.json{ notes, words, definitions } object: a curated 5-letter Urban Dictionary word list (hilarious, raunchy, or offensive in character). The second "valid word" source; definitions maps each word to its bundled Urban Dictionary definition. It is a superset of the answer pool — every word in answer-words.json appears here with the same definition (the test suite asserts this).
  • answer-words.json{ notes, words, definitions } object with the curated raunchy 5-letter answer pool. definitions maps each answer word to a bundled Urban Dictionary definition shown on the win/lose overlay. The notes field documents curation rules; wordlists.js accepts this shape, the urban shape, or a plain array.

Valid word rule

A word (for in-round guesses) is valid if and only if it is exactly 5 letters and present in either the standard American-English dictionary (dictionary-words.json) or the curated Urban Dictionary list (urban-words.json). The union is computed once at load (loadWordDatavalidWords).

Curation rules (answer pool and urban list)

  • Exactly 5 lowercase ASCII letters, no duplicates.
  • Hilarious, raunchy, or offensive in character — no slurs or hate speech, no proper nouns or personal names.
  • Every word needs a short plain-language definition in the definitions map (Urban Dictionary style).
  • The list must stay a superset of answer-words.json with matching definitions.
  • To add words, append to the words array and a matching definitions entry, then run npm test — the test suite asserts the invariants (5 letters, lowercase, unique, defined, superset) for the word lists.

Curation rules (dictionary)

  • Exactly 5 lowercase ASCII letters, no duplicates.
  • Extend by appending to the array; npm test validates.

Tests

npm test

Runs the node-based unit tests (no framework): rules engine (round state machine, feedback with duplicate-letter handling, guess validation), answer selection, and word-list invariants.

Project layout

index.html          entry page
style.css           page styling
src/app.js          Phaser game bootstrap (HiDPI config, mute, exposes window.__game)
src/scene.js        WarningScene + GameScene (board, keyboard, overlays, control bar)
src/theme.js        palette, fonts, easing/duration constants (single source of truth for the look)
src/textures.js     boot-time texture bakes (glass, glow, confetti shard, vignette) + HiDPI scale
src/audio.js        Web Audio SFX synthesis + mute state (no audio files)
src/rules.js        round state machine, feedback, validation (pure, no DOM)
src/wordlists.js    loads word data (answer pool, urban + dictionary lists, bundled definitions)
data/               word lists
vendor/             vendored phaser.min.js (Phaser 4.2.1, MIT) + fonts/ (OFL WOFF2) + LICENSE-NOTES
test/               node --test unit tests

Debug hooks

  • window.__game — the Phaser game instance (scenes, input).
  • window.__badWordle — round state, current guess, feedback, setAnswer(word), pool size. Used for deterministic E2E assertions.