Project · ★★ · Intermediate
Five Letters
A daily word game you made yourself. Everyone who opens it today gets the same secret word, with no server, just maths on the date. Six guesses, tiles that flip green and yellow, a keyboard that remembers what you know. When you finish, one tap sends your friends a grid of coloured squares that shows how you did without spoiling the word. Then they want to play, and tomorrow there is a new one.
You need
- Set up your computer, so you have a terminal, git and Node.
- Claude Code or Codex, set up and logged in: Get Claude Code or Get Codex.
- How to work with an agent. Read it once. It saves hours.
- A free GitHub account, if you want to publish it: Save it on GitHub.
- Put it online with Cloudflare Pages, to put it online so friends can play.
What you'll learn
- A deterministic daily seed: turn a date into a number and the number into the same word on every phone.
- Seeded random numbers and why
Math.random()cannot do this. - Scoring with repeated letters, and writing tests for the tricky cases first.
- Saving game state and streaks in localStorage so a reload never loses your board.
- The Web Share API and the clipboard, for the "share your result" button.
What this shows the agent can do
- Write a tricky scoring function and the tests that prove it right, before the game uses it.
- Spot a time zone bug when you tell it "my friend in another country got a different word".
- Build a word list and a script that checks it, instead of trusting the list by eye.
The brief
Make a new folder for the project. Copy the brief below into a file called BRIEF.md in that folder, or download BRIEF.md. Open the agent in the folder and say:
Read BRIEF.md and start with milestone 1. Stop after each milestone so I can check it.
# Five Letters — a daily word game (★★) Build a daily five-letter word game. Everyone who opens it on the same date gets the same secret word, with no server: the word is picked from a list using the date as a seed. You get six guesses. After each guess the tiles flip and turn green (right letter, right place), yellow (in the word, wrong place) or grey (not in the word). An on-screen keyboard shows what you know about each letter. When you finish, one button shares your result as a grid of coloured squares, with no letters, so friends can compare without spoilers. Your streak is kept on this device. A hard mode forces you to use every hint you have found. ## Done looks like - A 6 by 5 grid and an on-screen keyboard. Physical keyboard works too: letters, Backspace, Enter. - A guess that is not five letters, or not in the word list, shakes the row and shows "Not in word list". It does not use up a guess. - Scoring handles repeated letters correctly (see milestone 2 for the exact test cases). - Two different browsers on the same date get the same word. The next local day gives a new word. - Add-on: reloading the page in the middle of a game keeps the board exactly as it was. - A stats panel shows games played, win percentage, current streak, best streak and a bar chart of guesses needed. - Add-on: share produces text like `Five Letters 214 4/6` followed by rows of green, yellow and dark square emoji. It uses `navigator.share` on phones and copies to the clipboard elsewhere, with a "Copied" message. - Hard mode is a toggle. With it on, a guess must keep every green letter in place and include every yellow letter. - Works offline once loaded. No console errors. ## Constraints - Static files, no build step: `index.html`, `style.css`, `game.js`, `words.js`. No frameworks. - `words.js` exports two lists: `ANSWERS` (common, friendly five-letter words; nothing offensive) and `ALLOWED` (every accepted guess, which includes all answers). Start with at least 300 answers. A small check script must prove every entry is five lower-case letters a to z with no duplicates. - Do not download a word list without asking me first and checking its licence. - The daily word: take the local date (year, month, day, not UTC), count whole days since 2026-01-01, and use that day number. Shuffle `ANSWERS` once with a seeded random number generator (for example mulberry32 with a fixed seed), then pick `shuffled[day % ANSWERS.length]`. The puzzle number in the share text is the day number. - All state in localStorage under keys starting `five.`. No server, no network calls, no tracking, no accounts. - Colours must also be told apart by shape or label for colour-blind players (a high-contrast option at least). - Phone works: the grid and keyboard fit a 360 px wide screen without scrolling. ## Milestones 1. **Grid and typing.** Draw the empty grid. Typing fills the current row, Backspace removes, Enter submits a full row (no scoring yet). Check: you can type five letters, delete one, retype, press Enter, and the next row becomes active. 2. **Scoring, with tests.** Write `score(guess, answer)` returning five marks: green, yellow or grey. Use two passes: greens first, then yellows counted against the letters left over. Add `tests.html` that runs the cases and prints pass or fail. Cases: answer `abbey`, guess `babes` gives yellow, yellow, green, green, grey. Answer `lever`, guess `eeeee` gives grey, green, grey, green, grey. Answer `crane`, guess `crane` gives five greens. Check: `tests.html` shows every case passing. 3. **Word list and the daily word.** Add `words.js` and the check script. Reject guesses not in `ALLOWED`. Pick today's word from the date as described. Check: the check script passes; open the game in two different browsers and both have the same answer (show it with `?debug=1`). 4. **Keyboard and reveal.** On-screen keyboard that types into the grid. Tiles flip one after another when a row is scored. Keys take the best colour known for that letter. Win and lose messages. Check: on a phone you can play a whole game with the on-screen keyboard, and a key that was green never turns back to yellow. 5. **Hard mode and polish.** Hard mode toggle (it can only be switched on before the first guess of the day). A high-contrast colour option. A countdown to the next word on the end screen. Check: in hard mode, a guess that drops a green letter is refused with a message naming the letter and position. > That is the whole game, for one day at a time. The next two make it remember and let you show off. 6. **Save and stats.** Save the board after every guess. Track played, wins, current streak, best streak and guess distribution. A streak breaks if you miss a day or lose. Check: reload mid-game and the board is unchanged; finish a game and the stats panel updates. 7. **Share.** Build the share text from the marks only. `navigator.share` if available, clipboard otherwise. Check: paste the result into a chat: it shows the puzzle number, your score and the coloured grid, and no letters. ## Stretch - A practice mode with a random word that does not touch your streak. - A six-letter weekend edition with its own list and seed. - A "how did everyone do" chart: a Worker and KV that count only how many guesses each player needed that day, no names. KV allows 1,000 writes a day on the free plan, so this suits a group of friends, not the whole internet. - Animations for a win: tiles bounce one after another. - A short definition shown after the game, written into the word list so no network is needed. - A themed word list for one week (animals, food, space). ## Leave out - Accounts, a server, ads. - Fetching words from an online dictionary. - Copying another game's name, look or word list. Start by reading WRITING.md and the guide chapter on data if you need storage.
Milestones
The same milestones as the brief. Tick each one off when its check passes. Do one per sitting if you like. The dot in the list marks the point where you have something that works on its own. Everything after it makes it remember things or work for more than one person. Stop at the dot and use what you built before you go on.
- Grid and typing. Draw the empty grid. Typing fills the current row, Backspace removes, Enter submits a full row (no scoring yet).
Check: you can type five letters, delete one, retype, press Enter, and the next row becomes active.
- Scoring, with tests. Write
score(guess, answer)returning five marks: green, yellow or grey. Use two passes: greens first, then yellows counted against the letters left over. Addtests.htmlthat runs the cases and prints pass or fail. Cases: answerabbey, guessbabesgives yellow, yellow, green, green, grey. Answerlever, guesseeeeegives grey, green, grey, green, grey. Answercrane, guesscranegives five greens.Check:
tests.htmlshows every case passing. - Word list and the daily word. Add
words.jsand the check script. Reject guesses not inALLOWED. Pick today's word from the date as described.Check: the check script passes; open the game in two different browsers and both have the same answer (show it with
?debug=1). - Keyboard and reveal. On-screen keyboard that types into the grid. Tiles flip one after another when a row is scored. Keys take the best colour known for that letter. Win and lose messages.
Check: on a phone you can play a whole game with the on-screen keyboard, and a key that was green never turns back to yellow.
- Hard mode and polish. Hard mode toggle (it can only be switched on before the first guess of the day). A high-contrast colour option. A countdown to the next word on the end screen.
Check: in hard mode, a guess that drops a green letter is refused with a message naming the letter and position.
- That is the whole game, for one day at a time. The next two make it remember and let you show off.
- Save and stats. Save the board after every guess. Track played, wins, current streak, best streak and guess distribution. A streak breaks if you miss a day or lose.
Check: reload mid-game and the board is unchanged; finish a game and the stats panel updates.
- Share. Build the share text from the marks only.
navigator.shareif available, clipboard otherwise.Check: paste the result into a chat: it shows the puzzle number, your score and the coloured grid, and no letters.
Make it yours
Once it works, pick one of these and ask for it as a new milestone.
- A practice mode with a random word that does not touch your streak.
- A six-letter weekend edition with its own list and seed.
- A "how did everyone do" chart: a Worker and KV that count only how many guesses each player needed that day, no names. KV allows 1,000 writes a day on the free plan, so this suits a group of friends, not the whole internet.
- Animations for a win: tiles bounce one after another.
- A short definition shown after the game, written into the word list so no network is needed.
- A themed word list for one week (animals, food, space).
If it goes wrong
Two phones get different words on the same day.
The date is being read in UTC instead of local time, or the list is shuffled with Math.random(). Say this to the agent:
Two browsers on the same date get different words. Make the day number come from the local year, month and day, shuffle with the seeded generator only, and show me the day number with ?debug=1.
A guess with a double letter shows two yellows when there should be one.
The scoring is doing one pass instead of two. Say this to the agent:
Scoring is wrong with repeated letters. Add the failing case to tests.html first, then fix score() with a greens-first two-pass method.
Share does nothing on the laptop.
navigator.share exists on phones but often not on desktop browsers. Say this to the agent:
The share button does nothing on my laptop. Fall back to the clipboard when navigator.share is missing, and show a "Copied" message.