DEV Community

Cover image for How I built the sudoku site I always wanted (Next.js 15, Supabase, keyboard-first)
Raz Chiriac
Raz Chiriac

Posted on

How I built the sudoku site I always wanted (Next.js 15, Supabase, keyboard-first)

Every sudoku site I've ever used has the same two problems: ads everywhere, and a mouse-only UI that makes fast solving feel clunky. I play sudoku to think, not to fight with my browser.

So I built my own. It's called Kodiak Sudoku — free, no ads, keyboard-first, with vim bindings and a leaderboard that doesn't lie. Here's what went into it.


The stack

  • Next.js 15 with the App Router
  • React 19
  • TypeScript throughout
  • Supabase for the database (auth, leaderboard storage, daily puzzle state)
  • Drizzle ORM on top of Supabase
  • Tailwind CSS
  • Vercel for hosting + Edge Config for feature flags

Nothing exotic — just a stack I could move fast with and trust in production.


The three things I actually cared about

1. Free with no ads

This sounds simple but it shapes every decision. No ad SDK to load, no layout shift, no third-party trackers. The page is fast because there's nothing slowing it down. I'm covering hosting costs out of pocket for now — Vercel and Supabase's free tiers go surprisingly far for a side project at this scale.

2. Keyboard-first, with vim bindings

Most sudoku sites are built for mouse/touch. Clicking individual cells is fine on mobile, but on desktop it's slow. I wanted to navigate the board the way I navigate everything else — with hjkl, or arrow keys, or number keys to fill in digits instantly.

The input handling ended up being one of the more interesting parts of the build. React's synthetic event system and the browser's native focus behavior don't always agree, especially when you're trying to make a grid feel like a text editor. Getting vim-style navigation to feel snappy without fighting the DOM took a few iterations.

If you're into this kind of thing — keyboard-driven UIs, focus management, accessibility — I'd love to hear how you've solved similar problems.

Kodiak Sudoku Home Page

3. Honest leaderboards

This one bugged me about every other sudoku leaderboard I've seen: hint-assisted times compete directly against pure runs. Someone who used three hints finishing in 4 minutes shouldn't outrank someone who solved it clean in 5.

Kodiak separates the two. Pure runs and hint-assisted runs are ranked independently. It's a small thing but it changes how the leaderboard actually feels — it's something you can be proud of, not just a number.


Interesting technical bits

Daily puzzle state at the edge

The daily puzzle is the same for everyone, every day. I'm using Vercel Edge Config to store and serve the active puzzle, which means the puzzle data is globally distributed and available with essentially zero latency. State per-user (progress, timer, hints used) lives in Supabase.

Drizzle + Supabase

I'd used Prisma before and wanted to try Drizzle. The type inference is excellent and the query builder feels closer to writing SQL, which I prefer. The integration with Supabase was smooth — I'm using Supabase for auth and RLS policies, with Drizzle handling the query layer.

Puzzle generation vs. curation

I ended up curating puzzles rather than generating them on the fly. Generated puzzles can technically be valid but feel mechanically similar. Hand-selected (or at least filtered) puzzles have more character. For the daily puzzle specifically, I wanted something people would actually enjoy solving, not just a valid grid.


What I used Claude for

Claude was my pair-programmer throughout. Not in a "it wrote the whole thing" way — more like having a senior dev available to rubber-duck architecture decisions, catch edge cases in my input handling logic, and help me move faster on the parts I found tedious (writing marketing copy, mostly).

The parts that required actual judgment — how to structure the leaderboard, how to handle timer state across tab visibility changes, how to make the keyboard UX feel right — those were conversations, not prompts. Worth being honest about the difference.


What's next

The site is live now at kodiaksudoku.com. Daily puzzles, leaderboards, full keyboard support including vim bindings.

Things I'm thinking about for v2:

  • Mobile experience improvements (touch is functional but not delightful yet)
  • Puzzle difficulty ratings based on solving technique, not just time
  • A "practice mode" for specific techniques (naked pairs, X-wing, etc.)
  • A Loom walkthrough once I've seen how real users actually play

If you build keyboard-first apps, care about honest UX, or just play a lot of sudoku — I'd genuinely love to hear from you. What would make this better?


Built with Next.js, Supabase, Drizzle, Tailwind, and Vercel. Pair-programmed with Claude.

Top comments (1)

Collapse
 
raz_chiriac_b5dbbe8de7932 profile image
Raz Chiriac

Hey dev.to — maker here.

A decision I almost made differently: generating puzzles algorithmically vs. curating them. Generation is the obvious technical choice, and I built it, but the puzzles felt samey. Switched to curation for the daily and haven't looked back — there's something about a puzzle that was actually selected that makes it feel worth solving.

The thing I'm least happy with right now is mobile touch. It works, but it doesn't feel good the way the keyboard UX does on desktop. If anyone's built a grid-based input experience that felt genuinely delightful on touch, I'd love to know how you approached it.

And if you play sudoku — come try the daily. Leaderboard is real and ad-free is permanent.