Study Like a Sloth: EchoDeck Turns Your Notes into Self-Grading Flashcards, Offline A developer built EchoDeck, an open-source voice-first flashcard coach that generates cards from notes and grades spoken answers, adding a fully local mode for the Hacktoberfest Open-Source AI Challenge. The local mode runs on Ollama with small open-weight models, whisper.cpp for speech-to-text and Piper for text-to-speech, while Leitner-box spaced repetition scheduling stays deterministic code so malformed model output cannot corrupt review schedules. The server is written in TypeScript on Node 24, exposes its features as Model Context Protocol tools, and stores data in a JSON file with atomic writes and corrupt-file recovery. This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady https://dev.to/challenges/hacktoberfest-week3-2026-10-19 EchoDeck is a flashcard coach for people who want to learn without running a study system. Flashcards work, but the chores around them are what make people quit: writing the cards, deciding what to review today, and keeping a streak alive. EchoDeck takes those chores over. EchoDeck started as an Alexa+ MCP add-on for hands-free study on an Echo Show. For this challenge I added a fully local mode that runs on your own machine with no internet connection and no cloud account. Both modes share the same scheduling engine and the same data file, so nothing about your progress depends on which mode you use. It is for students, language learners, and anyone cramming for an exam or certification who would rather spend their effort answering questions than building cards. EchoDeck runs on a laptop, so the quickest way to see it is to run it. This is the whole setup: 1. Start Ollama with a small open-weight model ollama pull llama3.2 or: ollama pull qwen2.5-coder:3b ollama serve 2. Run EchoDeck in local mode cd server npm run build MODE=local npm start Then open http://127.0.0.1:3000/ : If the model is down or returns something unusable, self-rating buttons appear so a study session never gets stuck. Voice-first flashcard coach with spaced repetition — an Alexa+ MCP add-on server. EchoDeck lets learners create study decks, get quizzed, and track progress entirely by voice through Alexa+. It uses Leitner-box spaced repetition to schedule reviews and provides a visual card UI for Echo Show devices. This project uses ES modules throughout: "type": "module" in package.json "module": "Node16" and "moduleResolution": "Node16" in tsconfig.json .js extensions TypeScript resolves these to .ts at compile time node --version cd server npm install @modelcontextprotocol/sdk @modelcontextprotocol/ext-apps express zod npm install -D typescript tsx vitest vite vite-plugin-singlefile @types/node @types/express After installing, verify: node --version Must be = 24.0.0 npm ls --depth=0 All packages should be listed without ERR Also check that the installed zod version satisfies… The server is TypeScript ES modules, Node 24 with Express and zod, and it exposes its features as tools over the Model Context Protocol MCP . Data lives in a JSON file with atomic writes and corrupt-file recovery. The UI is a single-file Vite build that works both as an Echo Show card and as a standalone browser app. | Piece | What it does | Open tool | |---|---|---| | LLM | Generates cards from notes and judges answers | Ollama , with small open-weight models llama3.2 , qwen2.5-coder:3b , mistral | | Speech to text | Transcribes spoken answers | whisper.cpp adapter, with browser speech recognition as a fallback | | Text to speech | Reads questions aloud | Piper adapter, with browser speech synthesis as a fallback | Leitner scheduling and streak math are plain deterministic code. The LLM does only two language jobs: it creates cards, and it judges an answer and returns a rating. That rating is validated with zod and then passed into the existing SRS function. A wrong or malformed model output can never corrupt your review schedule, and the scheduling tests stay exact. server/src/local/ : LlmProvider , SttProvider and TtsProvider interfaces with Ollama, whisper.cpp and Piper implementations. Core domain and storage code has zero dependency on any provider, so swapping a model is a setting OLLAMA MODEL , not a rewrite. CardGenerator validateCards step so limits, trimming and de-duplication apply to AI-generated cards exactly as they do to hand-made ones. AnswerJudge /api in local and both modes : status , decks , generate-deck , study/next , study/judge , study/self-grade , stt and tts . MODE=alexa|local|both , defaulting to alexa , so existing behavior is unchanged. In local mode the server binds to 127.0.0.1 by default. generate deck from notes , available when the local controller is configured. The four original tools are untouched. Small models 3B to 8B parameters drift on formatting. They return a single object instead of an array, or wrap JSON in markdown code fences even when told not to. Three things made it reliable: {"cards": ... } instead of a bare array. The back of a card is never rendered in the DOM or returned over HTTP before you submit an answer. /api/study/next returns the front only, and the back is revealed in the response to /api/study/judge . This holds in both the REST API and the UI, and it is covered by tests. MODE=alexa . qwen2.5-coder:3b . It covers health, provider status, card generation from notes, confirming next card omits the back, answer judging with model feedback, revealing the back, and streak persistence. I want to be upfront about this. The whole local flow card generation, judging, SRS, streaks, answer-leak prevention was verified end to end with a real local model. The whisper.cpp and Piper adapters are covered by unit tests with mocked servers, but I did not run the real binaries , because neither was installed on my machine. I tested voice input and output through the browser's built-in speech features instead. Those browser features are convenient, but depending on your browser, speech recognition may use an online service. If you need strictly offline voice, use the whisper.cpp and Piper path. Typed answers are always fully local. My first version of EchoDeck only worked through Alexa+. That made it great on an Echo Show, and it also made me notice what I'd given up: all of the intelligence belonged to someone else's platform. Moving the language work to open-weight models changed what was possible. EchoDeck removes the three chores that make flashcards a hassle: After the one-time setup, a study session is: open the page, answer what you're asked, and close it.