Book Map
A reading roadmap that shows what order to read in for a topic - the goal is showing the path, not a list of recommendations.
- React
- TypeScript
- Hono
- Reading
Landing - the one-liner ("we don't recommend books, we show you the order") plus the three value props: order, connection, your position
Reading journey - per-topic progress (1 of 7) and the status of each book on one screen
Topic map - book cards laid out along the path, with a "you are here" marker for position
Book detail - status, rating, purchase links, plus standardized "why read this," "what you'll take away," and "good prerequisites"
Book review with AI feedback - the AI returns "what you caught," "what to deepen," and a one-line verdict
End of review - two rails ("on the map / off the map") lead to the next book
My library - read, reading, and to-read gathered in three buckets
AI recommendations - using the review you wrote, the AI surfaces both "next on the map" and "off the map" picks
Setup
- Problem
Recommendation lists are everywhere; a map of "what to read in what order" is not. Beginners keep spending time picking the next book, and mentors don't have a single line they can hand someone.
- Context
Grew out of fourteen years of "which book should this beginner read first?" - the value of a book sits less in a single recommendation and more in laying down the path through a topic.
- Users
Self-learners taking on a new topic, and mentors who want to point a junior somewhere with one short answer.
- Hypothesis
Replace the catalog of book cards with a single map that shows order, connections, and your own position - and "what should I read next" turns from a search into a glance.
Build
- What I did
- Reading-map data model - sequence and stage relationships between books
- Map view - book cards laid out along the path, with a "you are here" marker
- Book detail - standardized into "why read this," "what you'll take away," and "good prerequisites"
- Book review with AI feedback - the AI returns "what you caught," "what to deepen," and a one-line verdict, ending with "next on the map" and "off the map" picks
- My library - read, reading, and to-read books gathered in one place; ratings and notes captured right on the card
- The frontend works statically; a Hono + Neon Postgres + Drizzle + JWT backend layers on for accounts, sync, and curator edits
- Product decisions
- Deliberately no "top-10 books" list - protecting the identity of showing the path, not the picks
- After-review recommendations split into two rails ("on the map / off the map") - the reader decides whether to stay on the route or branch out
- Backend kept as an optional layer - no signup friction at first entry; sync only when the reader wants it
- Curators can edit content without a code deploy - if "one map" is going to stay trustworthy over time, the operator needs reachability
- QA considerations
- Anonymous localStorage progress and logged-in server progress don't diverge - and the unsupported import is stated honestly on screen
- Optimistic updates (progress/rating writes) roll back exactly to the previous state on failure
- AI calls that fail to produce their
tool_useshape are rejected with a 502 so a malformed note never reaches the reader - When the AI key is absent, only /api/ai/* returns 503 while maps, progress, notes, and auth keep serving (dependency-failure isolation)
- Env vars are fail-fast validated with zod at boot so a misconfig can't slip through silently
Outcome
- Metrics
Alpha stage. Three topics registered (startup, writing, programming basics); real-user numbers not yet measured.
- Result / Learning
The frontend already works end to end, so the next round is defined as "polish one topic and watch for signal." Once curators get added, "what's the rule for what fits onto one map" becomes the biggest design question.
Process (planning → build)
The same template from problem and hypothesis through scope, spec (SSOT), build, the QA gate, and release - how this was planned and driven.
Process (planning → build)
Problem & hypothesis
The recurring problem, hit across 14 years of QA whenever recommending books to juniors: there are endless book lists but no map of what to read in what order. The hypothesis is that laying out order, connections, and a 'you are here' marker (per-book planned/reading/done status) on one map turns 'what do I read next?' from a search into a glance.
Skills · Problem framing · hypothesis
Scope & priority
Scope was pinned to 'a map that shows the order,' not a recommendation catalog or a reading log (README: the point is the path over recommendations, the map over the record), and the seed was kept deliberately small at 3 topics / 20 books rather than chasing breadth. To cut signup friction the map is usable anonymously with progress in localStorage (book-map:progress:v1), and logging in switches to server-backed cross-device progress - but importing that anonymous progress into the account is explicitly not supported yet, as the progress page states in as many words.
Skills · Scoping · prioritization
Spec-first (SSOT)
There is no separate PRD; the data model (server/src/db/schema.ts) and the seed content (server/src/db/seed-data.ts) stand in as the SSOT. AI responses are pinned to a fixed shape via tool_use input_schemas that act as contracts (callClaudeStructured in server/src/lib/ai.ts), and the root and server READMEs document the API surface as the interface spec.
Skills · Spec · documentation
Build & iteration
The frontend was built to work first, then a Hono backend was scaffolded and the app switched to API calls (commit order 149bd8a to ac82b84 to a604313, with static src/data/maps.ts deleted in a604313). On top of the initial migration the schema grew additively with three more (a notes table, a rating column, an AI-outputs table) for four total, and a logged-in user's progress/rating writes use TanStack Query optimistic updates that roll back to the previous state on failure.
Skills · Execution · delivery
Verification (QA gate)
The QA background shows up not as a test suite (there isn't one in the repo yet) but as contracts and failure isolation written into the code. Env vars are fail-fast validated with zod at boot (env.ts safeParse then process.exit on failure); AI calls that fail to produce their tool_use shape are rejected with a 502 so malformed output never reaches the reader, and results are upsert-persisted (onConflictDoUpdate) so a re-visit shows the same answer. When the AI key is absent only /api/ai/* returns 503 while maps, progress, notes, and auth keep serving - isolating the flakiest dependency's failure at the backend layer so it can't spread app-wide.
Skills · Quality · risk
Release
The frontend ships on Cloudflare Pages (book-map.pages.dev) and the backend on Render via a render.yaml Blueprint in the Singapore region, health-checked at /healthz. A real deploy bug - NODE_ENV=production skipping the build-tool devDependencies - was fixed with `npm install --include=dev` in the build command and is in the commit history (c2022bc); it is a 0.1.0 alpha with 3 topics seeded (startup, writing, intro programming) and 20 books, no user metrics measured yet.
Skills · Release
- Tech stack
- React 18
- TypeScript
- Vite
- React Router v6
- Tailwind
- Hono
- Drizzle ORM
- Neon Postgres
- JWT
- Cloudflare Pages
- Render
- Links