← tatsumosoft.com

How This Was Built

What went into a themed crossword generator from idea to working app

~3hrsIdea to working app
~800Lines of code
1API call per puzzle
~$0.01Cost per generation

The Problem

I got hooked on crossword apps on my phone, but kept running into the same issues: recycled clues, vague hints, and answers that felt like a stretch just to avoid repeating a previous puzzle. There's no way to pick a topic you're actually interested in, and no guarantee the grid is valid at every intersection.

The AI Piece

Claude (Anthropic's AI) generates the themed word list and clues. I send it a structured prompt with the theme, grid size constraints, and rules about clue quality. It returns a JSON array of answers and clues, which the placement engine then arranges into a valid crossword. The AI handles the creative part (coming up with clever, fair clues that actually relate to the theme), while the algorithm handles the structural part (making sure every letter intersection is valid).

For multi-word answers, the app automatically calculates the word count indicator. If the answer is "BACK HOME," the clue displays (4,4) at the end. If it's "HERE I AM," you see (4,1,2). This is computed from the display form of the answer, not hardcoded by the AI.

The Crossword Engine

This was the real engineering challenge. Generating words is easy. Placing them in a valid crossword grid where every intersection checks out is a constraint satisfaction problem.

How placement works

Words are sorted longest-first. The first word goes horizontally near the center. For each subsequent word, the engine scans every cell of every placed word looking for matching letters to create perpendicular intersections. It validates bounds, letter conflicts, unintended parallel adjacency, and word boundaries. Multiple shuffled orderings are tried, and the densest valid layout wins.

What "valid" means

Every crossing must produce real letters in both directions. No word can accidentally extend into another. No parallel words can touch without a proper crossing. The cell before and after each word must be empty. These constraints are checked for every candidate position of every word.

Tech Stack

React (CDN)Vanilla CSSClaude APICloudflare WorkersConstraint Solver

The app is a single self-contained HTML file with React loaded via CDN. No build step, no bundler, no framework overhead. The Cloudflare Worker acts as a proxy so the API key stays server-side. The crossword placement engine is ~200 lines of pure JavaScript with no dependencies.

What I'd Add Next

Difficulty settings that control clue obscurity. A timer and scoring system. Saving puzzle state so you can close the tab and come back. A "hint" button that reveals a single letter instead of the whole puzzle. Pre-generated puzzle packs for offline play.