Build log
What we've been building
A reverse-chronological log of meaningful steps in building Capuchino. Small fixes and routine polish are folded into nearby entries.
Profile dashboard: assessment recap + bucket breakdown
The /app/profile knowledge map turned into a real dashboard. Up top, a one-line recap of your latest assessment — the date, where your cliff sits in plain language (e.g., "the top ~6,000 words"), and the band number underneath for the precise read. Below that, three rows — Known, Shaky, Unknown — each with the total broken into confirmed (you rated it, or we showed it to you in the assessment) versus inferred (extrapolated from your cliff). Watching the inferred numbers shrink is the new long-arc progress signal.
Analyze on the marketing pages
The /app/analyze feature is live, but the public-facing pages were still describing it as roadmap. Fixed in two places: the /how-it-works bullet flipped from "on the roadmap" to live — with the honest caveat that URL fetching is still future, so the label drops "or URL". And the homepage gained a short teaser section between the topic preview and the founder note: eyebrow, problem framing, sample paragraph with above-the-cliff words highlighted, and a soft sign-up CTA. Public surfaces now match what the product actually does.
Knowledge map + confidence cues
Surfaced two long-overdue distinctions on the gap-list UI. (a) Each row now shows a small confidence icon — a filled check for confirmed statuses (assessed, overridden, mastered), an outline circle for inferred statuses (presumed from your cliff). (b) A new "Your knowledge map" section on /app/profile shows how many of the 10,000 lemmas you've personally confirmed vs. how many are still our best guess. Both surfaces auto-update as you take the assessment, override flags, or analyze new texts.
Text upload analysis (preview)
Shipped /app/analyze: paste a Spanish article (news, blog, lyrics — anything you'd actually want to read) and we'll show you which words sit above your cliff. Each text is saved to your private archive — open it again later to watch the gap shrink as your Spanish grows. Inline override controls let you correct our guesses on the fly; the "in gap" rule respects explicit "I know this" overrides so your judgment beats our heuristics. Honest-limitations note on every result: we're useful, not airtight.
Backfill: activity_events + exports tables
While building the text-upload feature, caught that two tables planned in the original user-side schema (migration 03) had silently been dropped during build: activity_events (telemetry) and exports (export audit log). Wrote them now — append-only, own-rows RLS — and wired the new analyze flow to use both from day one. Retrofit for the existing gap-list and topic-detail exports is on the backlog.
FAQ page
Added /faq — eight straight-talking questions covering audience scope (yes, English speakers learning Spanish; no, not the other way round for now), the 10,000 number's defensible oversimplifications, product mechanics (why self-rating, why feed Anki), and what's not in Capuchino yet. Plain scrollable list, no accordion. Linked from the top nav.
Tatoeba per-sentence attribution
Jeff Doozan (the upstream maintainer of our lexicon source) flagged that Tatoeba's terms of use require per-sentence author attribution. The data was already in our database but wasn't surfacing in the UI. Every example sentence in the assessment now shows its source — 'via Tatoeba — author1 & author2 (CC-BY 2.0 FR)' — with quiet hyperlinks to the platform and the license. Compliance closed.
Landing page
Replaced the placeholder hero on / with a proper landing page: problem-first headline ("Master the 10,000 words that stand between you and C1"), three-step product loop, topic teaser, and a build-in-public founder note with a Reid Hoffman quote. Tone leans founder-y — named what's thin (no audio yet, one frequency list, basic self-rating) rather than polishing in private. /about and CLAUDE.md updated to match the audience framing (past B1, working toward C1).
Topic-based sub-lists (preview)
Shipped the first topic-based sub-list — the human body. Two new tables (topics + lemma_topics with confidence and source columns), 528 lemmas tagged conversationally in a Claude Code session and ingested via the pipeline. /app/topics shows the eight-card catalog (one live, seven "coming soon"); /app/topics/human-body lists the lemmas with the same status filters and TSV/CSV export as the gap list. /how-it-works updated to point at the live preview.
Build log page
Added this /log page so progress on Capuchino is visible in one place. Reverse-chronological, lightly curated.
How it works: roadmap additions
Expanded the "What's not yet there" section on /how-it-works with two upcoming features: topic-based sub-lists, and analyzing a pasted text or URL to surface unknown top-10k words.
How it works page
Created /how-it-works with a plain-language walkthrough of the product loop — assessment, gaps, export. Translated to Spanish. Top nav reordered to About → How it works → Sign up → Sign in → language toggle.
Export to your SRS
Shipped clean export of the gap list as TSV or CSV — Anki-compatible by default; Quizlet, RemNote, and Mochi all take the same format. We don't reinvent SRS; we feed the one you already use. Filter at export time: only the unknown, shaky + unknown, or everything that isn't solid.
Gap list
Built the Gaps view: every word above your cliff plus anything you marked shaky or unknown, with manual overrides ("actually I know this", "actually I don't"). Filter by frequency band, status, or source; pick up where you left off across sessions.
Temperature-check assessment
Implemented the 50-item assessment with stratified sampling across the ten frequency bands. Self-rating in context (solid / shaky / unknown) on real example sentences. Result: a soft anchor showing where your knowledge drops off, not a verdict. Resumable mid-flight.
Lexicon import pipeline
Built the Python ingestion (in a separate repo) that loads doozan/spanish_data into Supabase: 10,000 lemmas across 10 frequency bands, 21,668 senses (Wiktionary glosses), 108,706 example sentences (Tatoeba, quality ≥ 5), and 577,731 form-to-lemma mappings. Imported data lives in read-only tables, separate from app-authored content — a clean license boundary for the ShareAlike obligation.
About page
Published the About page covering the project's mission, the libraries we lean on, and the data sources behind the lexicon — every upstream credited with its license.
Authenticated app shell
Added the signed-in app layout, profile page, and protected routes. Sign up, sign in, password reset, and email confirmation flows are all live.
Supabase backend
Wired up the backend: Postgres schema for the multi-list lexicon, Supabase Auth (with Resend as the SMTP provider for transactional email), and row-level security on every table from day one.
Internationalization (EN + ES)
Set up i18next with English and Spanish locales and a header language toggle. Interface is fully bilingual; word glosses remain in English for v1.
Project bootstrap
Spun up the project on React + Vite + Tailwind, wired the design system tokens, connected the capuchino.co domain, and shipped the landing page with the capuchin-monkey footer narrator and rotating advanced-vocabulary taglines.