A free, original crossword word-tile game. Play against the computer (Easy, Medium, or Hard), pass-and-play with a friend, or play a friend remotely by exchanging links — no accounts, no server. Zero dependencies, zero build step — plain HTML/CSS/JS that runs from a local file or any static host (e.g. GitHub Pages).
Open index.html in a browser, or serve the directory statically:
python3 -m http.server
Rules
- 15×15 board; the first word must cross the center star.
- Click a rack tile, then click a board square to place it (drag and drop also works). Click a placed tile to pick it back up.
- While your tiles form a valid play, the Play button previews its score.
- Every word formed must be in the dictionary. Premium squares — 2L/3L (double/triple letter) and 2W/3W (double/triple word) — apply only to newly placed tiles.
- Using all 7 tiles in one turn earns a +40 bonus.
- Blank tiles (2 in the bag) stand in for any letter and score 0.
- Instead of playing you may swap tiles (while the bag has tiles) or pass. Four scoreless turns in a row ends the game.
- When the bag is empty and a player uses their last tile, they collect the value of the opponent's rack; otherwise unplayed tiles are deducted.
Games are auto-saved locally and resume when you return. The 📊 button tracks your local stats (wins per difficulty, streaks, best word, bingos); the 🎨 button switches between dark/light themes and three board skins (Classic, Ocean, Ember).
Link play: choose "Play a Friend by Link". After each move you get a URL carrying the entire compressed game state in its fragment — send it over any messenger; your friend opens it, moves, and sends one back. It's honor-system correspondence play: the link technically contains both racks, so it's for friendly games, not tournaments.
TileLoom is a PWA: when served over HTTP(S) it works fully offline after the first visit and can be installed to a phone's home screen. Tiles can be dragged with mouse or touch, or placed tap-by-tap.
engine.js— rules, board, bag, move validation, scoring (pure logic)ai.js— computer opponent: full move search over the dictionary; Hard mode weighs rack leave, premium-square exposure, and endgame tile dumping (benchmark it withAI_BENCH=15 node test/run.js)link.js— link play: game state ⇄ deflate-compressed base64url URL fragmentui.js— rendering and interactionsound.js— sound effects, synthesized with WebAudio (no audio files; mute button in the header, honorsprefers-reduced-motionfor animations)words.js— dictionary (public-domain ENABLE list, 168k words, generated)sw.js— service worker (stale-while-revalidate; bumpCACHEon release)- No frameworks, no build. Tests:
node test/run.js
TileLoom is an original work. The board layout (premium-square pattern), letter distribution and values, tile count (102), bonus values, name, and visual design were all created for this project and intentionally differ from any commercial word game. Crossword-tile game mechanics as such are not subject to copyright. The dictionary is the public-domain ENABLE word list. TileLoom is not affiliated with or endorsed by the makers of any commercial word game.
MIT — see LICENSE. Dictionary: public domain.