{Wordkin} Project Report
1. The Concept
Wordkin is a casual word-association puzzle for phones: sixteen tiles, four hidden groups. The player taps four words that belong together, presses Connect, and repeats until all four groups are found.
One sentence: *spot the link, connect the four, clear the board.*
The loop is Connections-style, but the product identity is a bright pocket campaign — not a newspaper grid. Easy / Medium / Hard each hold 50 levels (150 total). Easy is concrete sets (FRUITS, COLORS, PETS). Medium is knowledge (CAPITALS, PLANETS). Hard is lateral (___ LIGHT, THINGS WITH KEYS, DOUBLE MEANINGS). A winding map, coin HUD, and short sessions make it feel like a smartphone game, not a quiz site.
Design followed Sakurai-style rules already in the repo: one job per screen, beginner + expert in the same mechanic, risk/reward in hints (2 per level) versus solving clean, and a portrait shell that reads as a game. Level 1 teaches twice — a How to play card, then a pointing-hand coach on the real board — so the first Connect is shown, not guessed.
2. The Stack
Built as a zero-build, zero-dependency product so it can ship and play the same day.
Layer Choice ----------- ---------------------------------------------------------------- Structure index.html (home, campaign map, play + intro / hand tutor / result) UI Vanilla CSS (~2,080 lines): tokens, 3D pills, map path, safe-area Logic Vanilla JavaScript (~900 lines): groups, map, coins, audio, tutorial Art CSS tiles + campaign SVG path; UI icons (icon-back, icon-hint, icon-shuffle as .webp) Audio Web Audio API (looping music-box BGM, pick taps, success chimes) Progress localStorage — completed levels, coins, campaign meta Target Phone browser, portrait game-shell (min(100vw, 56.25vh)) Fonts Nunito 700–900 (Google Fonts)
No framework, no bundler, no npm — open index.html and play.
Architecture choices: a CATEGORY_BANK per difficulty feeds makeLevel() so 150 stages exist without a level editor; campaign layout is generated (generateRoute, SVG path, 50 nodes, five worlds); UI copy and design constraints live in sakurai/ and rules/, not in a separate engine.
3. The 1 Day Sprint (+ polish pass)
The day was treated as a full vertical slice: concept → playable core → campaign → juice → shippable demo. Scope stayed tight: one mechanic (pick 4 → Connect), one visual world, three difficulties. Anything that did not serve “find the groups and feel good doing it” was cut.
Morning (Hours 1–3):
- Locked the fantasy: colorful word pills, navy play screen, Connect as the one commit action — a phone puzzle, not a spreadsheet of tags.
- Built the app shell: home (PLAY + floating word chips), campaign map, in-game HUD.
- Defined the bank: 12 easy, 12 medium, 12 hard categories;
makeLevel()slices four groups per stage; 50 levels × 3 difficulties. - Implemented selection, Connect match, solved cards, Mix, and Hint (reveal two words from an unsolved group).
- Got a first playable loop: tap four related tiles, Connect, see the group lock, continue.
Outcome: A clickable prototype that already felt like the game, not a wireframe.
Afternoon (Hours 4–6):
- Built the campaign: winding SVG route, 50 nodes, Easy / Medium / Hard tabs, worlds (Sunny Meadow → Star Garden), coin HUD.
- Wired progress: unlock along the path, complete-level save, treasure chests at milestones, confetti on clear.
- Styled the board: compact colorful pills, dark navy ring on selection (unselected dim), 3D Connect pill that lights only with four tiles.
- Economy pass: default 690 coins, +10 per group with fly-to-HUD, result reward +40.
- First juice: success copy cycle (Nice! → Great! → Excellent! → Perfect!), pick taps, music-box BGM unlocked on first gesture.
Outcome: A real campaign, not a single hand-made puzzle.
The Finish Line (Hour 7-8):
- Result modal: white card, green check / red ×, Level complete, Next + Play again as pills.
- Level 1 How to play overlay (three steps + clothes example + Let’s play).
- Pointing-hand tutorial after intro: bounce on the first group’s tiles, then on Connect; dismiss after the first successful group.
- Mobile tuning: safe-area insets, portrait shell, reduced-motion fallback, Mix repositions the hand.
- Pass for “open file → play” confidence.
Outcome: A self-contained demo ready to show, share, or iterate.
Polish (Aug 10):
Playtesting the map and board drove most of the visual/feel fixes:
- Map path vs. nodes: SVG
preserveAspectRatio="none"so the route actually hits percentage-placed nodes. - Progress stroke that stopped early (looked stuck at level 6 while playing 8): dropped
pathLength/stroke-dasharrayhacks on.route-progress. - Play that did nothing: a duplicate
function render()had swallowed event listeners — removed the extra wrapper. - Connect color vanishing:
background-image: noneafter a gradient wiped the blue pill; disabled state is an explicit grey gradient instead. - SCHOOL (and other) solved banners jittering:
render()no longer rebuilds solved cards on every tap;renderSolved(true)only on a new group, with.solved-card.is-newfor pop. - Hint/Mix sized down (~42px); Hint icon restored (
icon-hint.webp); lives crowns replaced by the wood coin HUD. - Header: title Wordkin, glass overlay, 3D back (
icon-back.webp); squared map card; word chips on the map instead of trees/chests/clouds.
Later polish (Aug 20) stayed in the same spirit: Level 1 intro card, then a coach-mark hand that teaches tap-four-then-Connect on the live board.
4. The Roadblocks
- Map geometry vs. CSS percent — Nodes sit in % of the map box; the SVG path was drawn in viewBox space and stretched with
preserveAspectRatio="none"missing, so the line missed every node. Matching coordinate systems fixed “pretty path, wrong game.”
- Progress that lied — Dash-array / pathLength on the route looked clever and then stopped short of the current node. Simpler stroke progress was more honest.
- Silent Play button — Two
render()declarations in one file meant the second ate the first and listeners never bound. A one-day file still needs a single owner for the board.
- CSS that deleted the hero button — Resetting
background-imageafter a linear-gradient made Connect invisible/grey at the wrong time. Gradients are the color; don’t none them out.
- Re-render as animation bug — Rebuilding solved-group DOM on every tile tap made banners twitch. Separate “board render” from “celebrate a new group.”
- Audio without assets — No sound pack in a 1-day sprint. Web Audio had to carry BGM, picks, and chimes; browsers still need a user gesture to unlock the context.
- Teaching without a cutscene — Rules text is not play. Intro explains Connect; the hand has to point at real tiles or first-time players still stall.
- Scope vs. time — Daily mode, ads, accounts, and a full shop were tempting. Seeded category rotation + 2 hints + coins kept the loop complete without a backend.
5. Key Takeaways
- One sentence concept + three static files is enough to ship a 150-level × 3-difficulty campaign in a day.
- Familiar rules (four-of-a-kind associations) + a local identity (campaign path, colorful pills, Connect as commit) beats inventing a new mechanic under time pressure.
- Feel is product: tile ring, Connect light-up, coin arcs, and a still 3D button mattered as much as
submitGroupfor “this is a game.” - Re-creating DOM every tap is a bug farm. Animate the thing that changed; leave the rest.
- Coordinate systems (SVG vs. CSS %) are gameplay, not decoration — if the path misses the node, the map is broken.
- Design docs upfront (
sakurai/,rules/) kept screens honest: one job, portrait, smartphone — not a dashboard. - Teach on the board. An intro card plus a pointing hand is cheaper than a failed first level.
My final thought:
A one-day game only works when the concept is a single sentence and the stack stays out of the way. Wordkin proves that: tap four, Connect, clear four groups; a winding map; coins that fly home; Level 1 that actually teaches. The next steps are optional — handcrafted early boards, richer audio, a real daily seed — but the core already delivers what mattered most: see the link, press Connect, smile, next.