Solo Project · 2026

Sudokue.

Designer & Developer · One week build

Product Design Frontend Development AI-Assisted Workflows Design Systems Solo Build React · TypeScript Rapid Prototyping Accessibility · WCAG AA
Sudokue board with hint active: column 2 highlighted in orange and blue, lime placement target at R2C8, candidates and reasoning panel visible.

A Sudoku app built around learning. The client-side hint engine names the technique instead of filling in the answer. A technique library you can study on its own. A neobrutalist UI where colour does the teaching.

Built in React 19, TypeScript, and Vite. Runs entirely in the browser, with no backend involved. 12 engine patterns are live; 16 techniques are documented in the library.

12
Engine patterns shipped
16
Techniques in the library
0
Ads, trackers, dark patterns

Intermediate players plateau

They know naked singles and hidden singles. They never learn the rest, because the help they can reach spoils the puzzle. Every free Sudoku app treats players as ad inventory. Paid ones reveal answers instead of teaching. The coaching gap in the middle does not exist in any mainstream Sudoku product.

01
"Reveal answer" hints

Tap a button, the app fills in the next cell. Fast, satisfying, and the only help available the moment you're stuck.

What it teaches

Nothing. The hint ends the puzzle instead of teaching the pattern that would survive into the next one.

02
Ad-funded noise

Banner ads on a quarter of the screen. Interstitials between puzzles. "Watch a video to unlock a hint" gates.

What it teaches

That you are the inventory. The business model is engagement time, and the UI is engineered for it.

03
Wiki articles

Open a tab, read about X-Wing on a static page, come back to a board that does not know what you just read.

What it teaches

The technique, in theory. Application stays unsolved. The grid never points at the pattern you just learned.

Three reference points

What to keep, what to leave behind. No user interviews, no surveys, no metrics. A one-week build doesn't earn that work yet.

NYT Sudoku
Clean input, confident typography, a daily rhythm, proof that a puzzle app can feel like a real product. Hints are cell-reveals with no context. You get unstuck without learning why. That gap is the product opportunity.
Sudoku Solver
Named the technique. Highlighted the constraint cells. Walked through logic step by step, the closest reference to what a hint should actually do. Looks like a forum from 2008, though. Nothing about it invites return visits from anyone who isn't already a serious solver. The coaching is right; design quality is the unlock.
Play Store top 10
Confirmation the category has given up on design and pedagogy. "Powers" that pretend to be mechanics while being IAP. Dopamine loops. Banner ads. The lesson isn't what to copy. Competing on their axes at all is the mistake.
Synthesis

The coaching is on the wrong surface. The design hasn't moved in a decade. The business is built against the player. None of the three references fix all three at once. That's the gap.

Five calls that shaped the product

01
Hint payload contract

Progressive reveal across three button taps, escalating from region to focus to answer.

One request returns one full payload. Technique name, region, reasoning, placement: all together.

Progressive reveal looks pedagogical but works like a slot machine. The player gets stuck once. The hint should carry the full explanation in a single response. "Get Another Hint" runs the engine on the new board state and returns the next independent step.

02
Visual direction

Clean, Material-leaning. Predictably accessible, predictably forgettable.

Neobrutalism. Thick black borders. Hard-offset shadows that never blur. Saturated accents on a yellow canvas.

The category is visually dead. Looking different keeps the product from blending in. Beyond that, the high-contrast palette does double duty for the pedagogy. Each colour maps to a hint role (orange = region scan, blue = chain logic, lime = placement, coral = error).

03
Difficulty colour mapping

A brand-specific palette, internally consistent and externally meaningless.

Borrow the loot-rarity palette from games. Green = common (Easy). Blue = rare (Medium). Purple = epic (Hard). Orange = legendary (Expert).

Anyone who's played Hearthstone, TFT, Overwatch, or Borderlands reads the sequence without thinking. Expert puzzles feel earned because the colour already says 'legendary' to those players.

04
Where the engine runs

Server-side hint engine, with cleaner separation and swappable algorithms without shipping clients.

Client-side, in-process. TypeScript. Runs on the same board state the user is looking at.

Latency dominates the UX. A hint that takes 400ms over the wire is a different product from a hint that returns instantly. Privacy too: there's no good reason a Sudoku app should phone home with the in-progress board.

05
Persistence model

Accounts plus cross-device sync from day one, the standard "real product" expectation.

Local-first via localStorage. No accounts, no backend, no sync.

The proficiency state machine that would justify cross-device sync doesn't exist yet. Building accounts now would be infrastructure-for-infrastructure's-sake. Local-first is the right default until the thing being synced is itself worth syncing.

Hint quality is the product

One request returns one hint. Technique name, region, reasoning, and placement: all together. Each colour step is more assertive than the last: orange for the region scan, blue for the chain logic, lime for the placement commit.

Typical app

3 9 8 8 7 9 5 5 4 7 8 9 3 2 7 4 4 2 3 6 5 2 1 3 8 2 2 6 8 2 1 2 1 6 8 8 5 7 3 8 7 4 8 9 7 6 3 1

Just an answer dropped into R2C8. No technique named, no reasoning. The same pattern next puzzle finds you stuck again.

Sudokue

3 9 8 8 7 9 5 5 4 7 8 9 3 2 7 4 4 2 3 6 5 2 1 3 8 2 2 6 8 2 1 2 1 6 8 8 5 7 3 8 7 4 8 9 7 6 3 1 4 5 7 1 5 1 2 4 6 1 2 6 1 4 6 1 6 9 1 6 7 9 5 9 1 2 5 6 1 9 1

Three techniques chain to the same placement: The player sees the why, not just the what.

Hidden pair: In column 2, digits 2 and 6 can only live in R2C2 and R8C2. Everything else in those cells is eliminated.
XY-wing: Pivot R5C2 (5,9), wings R1C2 (5,1) and R3C2 (9,1). Removes 1 from cells that see both wings: R1C1, R2C1, R2C3, R3C3.
Hidden single: Row 2 now has only one cell that can hold 1: R2C8. Place 1 there.

Engine architecture: one pass, one payload

Every hint follows the same path: board state in, technique match, payload out. The engine runs entirely client-side and is deterministic. Same board in, same hint out, every time.

Input
Board state

81 cells with values, pencil marks, and candidates. The exact grid the player sees.

Process
Pattern matcher

12 technique strategies run in order of complexity. First match wins. Each returns null or a partial payload.

Output
Hint payload

Technique name, region cells, focus cells, placement cell, reasoning. One self-contained object the panel renders.

16 techniques. Three tiers

The engine currently returns 12 patterns. The four remaining advanced entries are library-only until the engine catches up. A player never requests a technique the engine can't prove. Solid chips are engine-backed; dashed are library-only.

Beginner · 3
Naked single Hidden single Candidate elimination
Intermediate · 5
Naked pair Naked triple Hidden pair Pointing pair Box-line reduction
Advanced · 8
X-wing Swordfish Skyscraper Y-wing / XY-wing Coloring / chains Jellyfish BUG + 1 Forcing chains

Neobrutalism, on purpose

Thick black borders. Hard-offset shadows that never blur. Saturated accents on a yellow canvas. Nunito at weight 900 almost everywhere. Sharp corners, matching the grid.

The choice is pedagogical, not aesthetic. Colour helps players build associations. When colour carries meaning, you stop needing to explain it.

Mobile is the primary surface, since most Sudoku players solve on phones. The grid sits centred and dominant. The number pad docks below for thumb reach without occluding cells. The hint panel slides over the bottom half on demand, never above the grid. On desktop the same layout opens out: grid stays the focus, hint panel anchors right. One component handles both viewports. No separate mobile or desktop forks.

Touch targets stay at 44pt minimum even as the grid scales to fill the viewport. The number pad has its own input zone with large hit areas. The hint panel never overlaps the grid; it covers the keypad instead, since the keypad is what the player can spare while reading the hint.

Sharp by default, soft on intent
Every structural surface uses 0px corners. Pills exist only on interactive primitives where the softer hit area earns the exception.
Hard shadows, no blur. Ever
Every elevation is a hard-offset shadow with zero blur. The shadow scale only varies offset distance. Blur would dilute the neobrutalist intent.
Press is physical
Hover and active states translate the element by the same offset as the shadow loss. The pixel doesn't move down. The page rises around it.
Black text on every coloured surface
Every coloured surface pairs with black text. No opacity tricks. Cuts a class of accessibility regressions before they start.
Reuse over abstraction
Three CSS classes carry 90% of the visual identity: .neo-card, .neo-btn, .neo-chip.
Colour carries meaning, not decoration
Every colour maps to a role: yellow = brand, lime = success / hint target, sky = info / intermediate tier, orange = advanced tier, coral = destructive / error. Decorative colour use is a problem.

Tokens carry the pedagogy

Three-tier tokens are the starting point. The interesting part is that hint.l1 / l2 / l3 and tier.beginner / intermediate / advanced exist as semantic tokens, not just hue aliases. The system doesn't know about lime or lilac in any meaningful sense. It knows what a region looks like and what a beginner technique looks like.

Primitive lime400

Raw hue, no opinion on usage.

Semantic hint.l1

Pedagogical role: the region nudge.

Component sudokuGrid.cellTargetL1

A specific cell state on the board.

The UI references the semantic token, never the primitive. Change a primitive once, every downstream reference updates. The visual language is derived from pedagogy, not picked from a swatch.

Hint levels, mapped end-to-end

Three semantic tiers. Each maps a primitive colour to a specific cell state on the board.

Primitive
Semantic
Component
Role
lime400
hint.l1
sudokuGrid.cellTargetL1
Region nudge: the technique's working set
sky400
hint.l2
sudokuGrid.cellTargetL2
Chain step: intermediate logic in the hint sequence
orange400
hint.l3
sudokuGrid.cellTargetL3
Placement commit: where the digit goes

Source: src/tokens.ts. Storybook page renders these rows live, with hover states + token usage examples.

Component anatomy: one grid, four states

The same SudokuGrid component renders the empty board, the L1 placement target, the L2 chain step, and the L3 earlier-context cell. Each state pulls from a single component-tier token. No conditional CSS in JSX. No inline overrides.

  • DefaultEmpty cell, no state. sudokuGrid.cellBg
  • L1 targetThe placement cell: where the hint concludes. sudokuGrid.cellTargetL1
  • L2 chainIntermediate step in the hint sequence. sudokuGrid.cellTargetL2
  • L3 contextEarliest step: the technique's anchor. sudokuGrid.cellTargetL3

Logged, not assumed

Every accessibility decision is recorded in docs/ACCESSIBILITY.md with date and reason. Accessibility drifts silently. A log with dates turns "we should have thought about this" into "we decided this on April 14th because of X."

In place

Semantic grid roles: role="grid" with aria-label per cell including row, column, value or "empty"
Full keyboard input: arrow keys navigate, 1–9 enter digit, Backspace clears, Ctrl+Z undoes, P toggles candidate mode
Non-colour error indication: conflict cells get coral tint and an error square marker. Never colour-alone.
WCAG AA contrast enforced: black ink on yellow, lime, lilac, sky all verified
Reduced motion: all motion under 300ms, single-axis translates. No parallax, no loops.
Focus trap on dialogs: NewPuzzleDialog cycles Tab inside the sheet, initial focus on close button
Focus-visible ring on .neo-btn: 3px black outline + 5px yellow halo, meets WCAG 1.4.11

Not done yet

Screen reader narration of hint reasoning is partial. Chain explanations could be more legible when read linearly.
No automated a11y test in CI. @storybook/addon-a11y installed but set to test: 'todo'. Needs a triage pass to flip to 'error'.
Colorblind-safe palette variant is a roadmap item. Current palette verifies by contrast, not colour-independence of every hint tier.

How a solo designer ships in a week

Sudokue was designed and built by one person using Cursor and Claude Code as implementation partners. Not "AI-assisted" as a buzzword. AI as the second seat in the pair. Claude Code wrote production TypeScript while I wrote specs, made design decisions, and reviewed every diff.

Where AI accelerated

  • Component scaffolding First-draft React components from a spec and a screenshot reference. I shaped the API; Claude filled in the implementation. 60–80% of the keystrokes weren't mine.
  • Token audits Once the system was tabulated as data, asking "where does the success colour drift from the token?" became one regex + one read.
  • Documentation surface area Each Storybook component page has 5 sections. Manually that's ~50 sections. With Claude as drafting partner: ~3 minutes per section, every page consistent.
  • Refactors with breadth BoardDock extraction touched 340 lines across three breakpoint branches in a 1900-line file. Done in one session because the AI could hold the entire file in context.
  • Accessibility wiring Focus traps, ARIA labels, keyboard maps: patterns I know but tedious to type. Faster to specify + verify than to write.

Where AI didn't help

  • The bet "Each hint is one self-contained payload" is not a thing AI can decide for you. It comes from looking at three competitors, naming what they all miss, and pricing the exception.
  • The loot-palette insight Borrowing Hearthstone's rarity palette requires having played those games and noticing the player would already read the sequence. AI doesn't have the lived context.
  • What to cut Deciding to ship without OCR, without accounts, without dark mode: that's product judgment. AI defaults to building what you ask for.
  • Voice and tone "GET HINT" not "CLICK HERE TO GET A HINT" is a taste call. AI will write either if you let it.

Three lessons that compound

Speed compounds if you know what you want
Every iteration is cheap now. The bottleneck isn't execution, it's direction. If you know the move, you'll ship three drafts before someone without a point of view has finished the brief. If you don't know, you'll ship three drafts of the wrong thing.
When iteration cost collapses, taste becomes the bottleneck
Four drafts of the hint panel in an afternoon. Six palette variations. The question stops being "can I build it" and becomes "can I decide which one is right, fast." Freeing if your taste is sharp. Dangerous if it isn't.
The spec is the design
Pixel decisions became specification decisions. Vague specs produce vague features. The most productive hour is the one you spend writing down exactly what something should do, for whom, before anything is drawn.

In order of priority

  • Real OCR in Scan flow. UI path is built, recognition is stubbed. Add the actual computer-vision step.
  • Wire the proficiency state machine: ProficiencyMap renders demo data today. Replace with event-sourced transitions: not-seen → introduced → practiced → proficient.
  • Hosted staging URL with a public beta cohort. Move from no metrics to actual usage data.
  • Public beta: Close the loop on the proficiency hypothesis.
Outcome

Designed, built and shipped solo in one week. 12 engine patterns. 16 techniques in the library. No ads, no accounts, no dark patterns. Live at sudokue.vercel.app ↗

More cases