Projects
Project

fey

A Feynman-style teacher for the phone. Read a lesson, highlight what you did not get, ask, and explain it back. Claude Code answers from the laptop.

Sep 2026 - Presentproductaifullstacklearningreact
fey

fey is a learning app I built for myself and run every day. The idea is Richard Feynman's: you only know a thing when you can explain it plainly. So the app is built around one loop. Read a short lesson on the phone. Highlight the sentence you did not understand and ask. Get it explained in plain words, with an analogy first and the term second. Then say it back in your own sentence, and have the gap found.

The teacher is not a chat model inside the app. It is Claude Code running on my laptop, reaching the app through a small MCP server. The question lands in SQLite on the server, the runner on the laptop picks it up, reads the lesson and the thread, and answers through the fey tools. The answer appears on the phone the moment it is written. Nobody has to be at the laptop. The runner hands each question to a headless session and can use DeepSeek instead when I want it cheaper.

The screenshots here use the app's sample content, ten public courses on economics, statistics, history and the like, not my own courses.

What it does

  • Lessons and courses. Short lessons in a fixed shape: the image, the idea, where it bites, teach it back, a check, a drill, a move. Under 500 words, because a lesson is read on a phone on a bus. Courses nest, carry a colour, and have a map page of their own
  • Ask from a highlight. Select a sentence, choose explain, example, why or quiz me, and a thread opens anchored to that exact quote. Threads are live over Server-Sent Events, so the phone only ever listens and every write is a plain POST
  • Say it back. At the foot of a lesson, and again days later from the home page. The say-back is graded for the gap, not the wording. An idea that held is marked taught on the map, one that did not comes back as a gap
  • The knowledge map. Every answer records the ideas it touched, with a relation between them. The map is drawn with d3-force, coloured by mastery, from new through seen and shaky to known. The home page shows the ideas that are due
  • Roadmaps. Ask for a course on the home page and fey builds it: the stages, the lessons, the order. Or write a learning path as a folder of files and post it whole
  • Claims. A number or a rule with a source in a lesson is recorded as a claim. When the runner is idle it refetches the source and says whether it still holds, so a figure from 2024 reads as a figure from 2024
  • Moves. A lesson can end with something to do in the world. It lands on a list, and what happened goes back to the teacher as the next question
  • Imports. Hand it a markdown file, a YouTube link, a web page or a one-line brief, and it comes back as a lesson
  • Reading. A reading ring that fills as you scroll, time read per lesson, a Pomodoro, find in page, an outline, a lightbox for pictures, and a listen mode
  • Looks. Fifteen palettes. The lesson face is your pick: the device serif, or one of twenty self-hosted fonts loaded only when chosen. No font CDN, no component library, no icon font

How it is built

  • apps/web. Vite, React 19, React Router 7, TanStack Query, Tailwind v4. Phone first, and the desktop gets a margin and a sidebar. Charts are d3
  • apps/api. Fastify, Drizzle and one SQLite file in WAL mode. Everything the app holds, lessons included, is in that file. Tables are created on first boot, so a fresh install needs no migration step
  • packages/shared. zod schemas. The API validates with them and the web types from them, so the two cannot disagree about a shape
  • The runner. scripts/run.mjs watches for open questions and imports and hands each one to a headless Claude Code session, or to DeepSeek through scripts/agent.mjs. The fey MCP server exposes take, reply, finish, write lesson, record knowledge and wiki image. The tools refuse an em dash, an en dash or a semicolon, which is how the house style is enforced on a model
  • Auth. One user. A signed passcode cookie for the phone, a bearer token for the agent. Two secrets, two audiences, no user table
  • Deploy. One VPS. nginx serves the built web app as static files and proxies /api with buffering off for the event stream. The API runs under systemd. A push to main pulls and builds on the box

Why I built it

I read a lot and kept nothing. Highlights in a reader go nowhere, and a chat window forgets the lesson by the next day. fey keeps the lesson, the question, the answer and the say-back in one place, and it knows only what I tell it inside the app. No notes vault, no profile, no guessing at my life. The teacher reads the lesson and the thread, and nothing else.

The constraint that shaped it: I did not want to pay for a model inside the app. I already pay for Claude Code. So the laptop teaches, the server remembers, and the phone reads.