Word Weave
An ambitious themed-world word puzzler for iOS, in active development — drag letter tiles to weave crossword-style words across themed worlds (Frozen, Desert, Coastal…), with replay-for-stars. Backed by a custom puzzle-generator that guarantees every level is solvable.
The problem
Casual mobile word-game players who want more than a flat word list — themed-world progression, a reason to replay (new word combinations earn stars), and levels that are always fair.
The owned product bet: a word game lives or dies on feel and fairness — effort went into native-feeling tile interaction and guaranteeing no unsolvable level, not feature sprawl.
What I built
- Tile-weaving core — drag letters from a tray onto a 9×9 board; runs of 3+ validate against a TWL06 dictionary; submit when the board is a valid connected crossword.
- Themed worlds + progression — levels grouped into themed worlds with art; solved state persisted locally.
- Replay-for-stars — re-solving requires new word combinations.
- Guaranteed-solvable levels — verified by the companion generator before shipping (the owned product decision).
- Feel details — haptics on placement/validation, a tile "flight" drag preview, spring drops, and Skia-rendered world cards.
How it works
Stack — RN 0.81 / Expo SDK 54 (managed) / React 19 / TS; Expo Router; Reanimated 4 + Gesture Handler; Skia; React Query + AsyncStorage; Vitest. The generator is dependency-free Node.js (CLI + Vercel serverless functions + web UI).
Architecture — levels are static blueprints in src/constants/ (letters + board + theme); a gesture/animation layer drives drag-and-drop; a pure puzzle layer (scan-word-runs, validateBoard) scans grid runs and validates against the bundled dictionary; solved/replay state persists locally. The generator is a separate repo used at design time to author and verify solvable letter sets, hand-placed into the game — there is no runtime pipeline between them.
I wanted a guarantee that no player ever hits an unsolvable level, so I built a separate generator that produces a letter set and proves at least one valid solution exists before I ship it as a level. That is an architecture-level product/systems judgment, independent of the algorithm internals.
Under the hood
Two pieces carry the game's feel and its fairness:
Why Reanimated worklets (gesture-driven animation off the JS thread to avoid frame drops) and why Skia (GPU canvas) over plain RN views.
Backtracking constraint-satisfaction search with pruning (letter-inventory checks, intersection-required-after-first-word, connectivity BFS), dedup by word-set, and a wall-clock timeout tuned to Vercel's 10s cap (8s), inside a generate-then-verify reroll loop.