Local flashcard app for interview prep (NeetCode 150 catalog). One problem at a time, in a triangular climb/descend order per section. Progress persists in the browser (localStorage).
Also includes a CLI Socratic tutor (backend only for now — not wired into the web UI) that recreates concept-first, quiz-until-expert NeetCode study sessions against the shared local Qwen 4-bit server (same stack as ~/projects/scheduler).
The home page has two practice cards (NeetCode 150 and AI interview) and a local chat on the right. History is stored under scripts/.neetcode-stack/home-chat.json. Attach or paste images (screenshots, whiteboard photos); they go to the same local LLM server as the tutors.
Image transcriber mode (toggle in the chat header) is for confidential screenshots that must not leave this machine. Drop or paste images into a queue; each page is OCRed on-device with Apple Vision, then the local model fortifies that page into a running markdown transcript. Images are not written to disk (except a short-lived temp file during OCR) and are not saved in the transcript file (scripts/.neetcode-stack/home-transcribe.json).
Primary path (do not use ad-hoc npm run dev as the operator story):
./scripts/neetcode-local-stack.sh restartThen open http://127.0.0.1:5188/ (home: practice tracks + local chat). NeetCode flashcards: http://127.0.0.1:5188/flashcards.html. Question bank: http://127.0.0.1:5188/question-bank.html
| Command | Behavior |
|---|---|
./scripts/neetcode-local-stack.sh start |
Background Vite on 127.0.0.1; wait for health; print URL + stop/restart/logs |
./scripts/neetcode-local-stack.sh stop |
SIGTERM → SIGKILL from pidfile; free port; clear pidfile |
./scripts/neetcode-local-stack.sh restart |
Full stop then start |
./scripts/neetcode-local-stack.sh status |
Each named pid: running / not running |
./scripts/neetcode-local-stack.sh logs |
tail -f service logs |
./scripts/neetcode-local-stack.sh run |
Start + foreground log tail; Ctrl+C stops the stack |
Requires Node.js, npm, and python3 on PATH (python3 runs the offline Solve harness). Optional NEETCODE_VENV / LOCAL_STACK_VENV / $ROOT/.venv. State under scripts/.neetcode-stack/ (pids, logs/; gitignored).
Columns: flashcard + Solve (Python editor + local tests under the card), problem statement, notes sheet (off by default), and tutor chat. Statements and local tests come from web/data/neetcode150-problems.sqlite — no network at runtime. Populate / refresh:
node --experimental-strip-types scripts/scrape-neetcode-problems.ts
node --experimental-strip-types scripts/enrich-problem-tests.ts
# or from web/: npm run scrape-problems && npm run enrich-tests| Flag | Meaning |
|---|---|
--limit N |
First N catalog problems (smoke test) |
--only <slug|id> |
Single problem |
--delay-ms N |
Scrape pause between requests (default 120) |
Solve is Python-only. Run / Pass local tests execute against scraped sample goldens (not NeetCode’s full hidden suite). Unsupported design problems show a notice instead of the runner.
Pregenerated 0-to-expert study guides live at notes/neetcode/<section-slug>/<id>.md and in notes_sheet_md on the problems table. Open them from Menu → Views → Notes sheet. Format: prompts/neetcode-notes-sheet.md.
node --experimental-strip-types scripts/import-neetcode-notes-sheets.ts
# or from web/: npm run import-neetcode-notes-sheetsSeparate page with topic cards, backed by local SQLite (web/data/ai-interview-questions.sqlite). Source: amitshekhariitbhu/ai-engineering-interview-questions.
Scrape keeps the full bank. Applied build/implement/design prompts are rewritten to How would you build or implement…; general knowledge prompts stay as written. Each question gets an Easy / Medium / Hard label (same as NeetCode); within every section the deck is sorted Easy → Medium → Hard.
The Question Bank uses the same triangular flashcard path as NeetCode (per section: climb A → A,B → A,B,C… then descend). Browse the full bank via Open list (L). Progress is separate (localStorage + scripts/.neetcode-stack/question-progress.json).
Practice is on the card: write your attempted answer, then Open in Grok (new grok.com chat with an interviewer prompt + your answer prefilled) or Coach locally (same loop against the machine’s vLLM). There is no separate chat pane. Pregenerated guidebooks stay under Menu → Views → Notes sheet. Prompt: prompts/socratic-ai-interview-system.md.
Each question stores:
- source_context_md — supplementary learnings from the public bank (original wording + linked blogs/videos)
- tutor_context_md — generated teaching brief (vocabulary, build walkthrough, tradeoffs, quiz seeds, spoken answer) used as ground truth by the coach
- notes_sheet_md — pregenerated 0-to-expert answer guidebook (also on disk as
notes/ai-interview/<section>/<id>.md)
Open the guidebook from Menu → Views → Notes sheet. Format: prompts/ai-interview-notes-sheet.md.
node --experimental-strip-types scripts/scrape-ai-interview-questions.ts
# or from web/: npm run scrape-question-bank
# Optional: import regenerated teaching briefs (gitignored local JSON batches):
# node --experimental-strip-types scripts/import-question-tutor-context.ts web/data/tutor-context/batch-*-output.json
# Import / refresh notes sheets from markdown (or JSON batches):
node --experimental-strip-types scripts/import-question-notes-sheets.ts
# or from web/: npm run import-notes-sheetsInteractive backend script: paste a NeetCode problem (+ reference solution), then get quizzed concept → dry-run → code → memory write → mastery → notes sheet.
Reuses the machine’s shared local LLM — same OpenAI-compatible server / served model as the scheduler stack. It never launches a second copy. Discovery order:
--api-base/--modelif you pass themVLLM_14B_BASE_URL+VLLM_14B_MODEL(scheduler env names)- Scheduler gateway
http://127.0.0.1:8766/health→vllm_api_base+vllm_model - Direct probe of
http://127.0.0.1:${SCHEDULER_VLLM_PORT:-8000}/v1
# Shared stack once (Qwen 4-bit :8000 + gateway :8766 + Heartbeat UI)
~/projects/scheduler/scripts/scheduler-local-stack.sh start
# Tutor (activates ~/.venv-mlx-qwen, sources ~/.env for HF_HOME)
./scripts/run-socratic-tutor.sh
./scripts/run-socratic-tutor.sh --problem-file ./examples/encode-decode-strings.md
./scripts/run-socratic-tutor.sh --wait-sec 180 # if model still loading| Env / flag | Meaning |
|---|---|
VLLM_14B_BASE_URL |
Optional override; otherwise taken from gateway health |
VLLM_14B_MODEL / SCHEDULER_VLLM_SERVED_NAME |
Served OpenAI model id (must match /v1/models) |
MLX_SCHEDULER_LLM_API |
Gateway origin for discovery (default :8766) |
NEETCODE_VENV / LOCAL_STACK_VENV |
Same venv default as scheduler: ~/.venv-mlx-qwen |
--wait-sec N |
Retry discovery while the model finishes loading |
--thinking |
Enable Qwen thinking tokens |
--resume sessions/<id>.json |
Continue a prior transcript |
In-session commands: /notes, /mastery, /reask, /next, /save, /title …, /status, /quit.
Transcripts land in sessions/ (gitignored) as .json + .md. System prompt: prompts/socratic-neetcode-system.md. Discovery helper: backend/local_vllm.py.
For each NeetCode section with problems (P_1..P_n):
- Climb — expand prefixes: (P_1), then (P_1..P_2), …, then (P_1..P_n)
- Descend — expand from the end: (P_n), then (P_n..P_{n-1}), …, then (P_n..P_1)
Sections are concatenated in roadmap order.
- I'm done — mark the unique problem complete and advance the deck
- Skip — advance without mastering
- Open Grok — opens https://grok.com
- NeetCode (or the problem title) — opens the problem on neetcode.io
- Jump — leap to any section; Export / Import backup progress JSON
Space/D done · S skip · G Grok · N NeetCode · C copy title · U undo · J jump · ? shortcuts
- Problems mastered — unique problems marked done at least once (out of 150)
- Deck progress — position through the full triangular flashcard sequence
- Today / session — cards advanced today (persisted) and this browser session
Progress is saved on every action to:
- Browser
localStorage— survives page reloads and browser restarts - Disk backup —
scripts/.neetcode-stack/progress.jsonvia the local stack (/api/progress)
On launch the app hydrates from both and keeps the farther-along copy. Stack restarts do not wipe progress. Use Export / Import for an extra portable backup.
web/— Vite + TypeScript UIweb/src/data/neetcode150.ts— the 150 problems (titles / URLs)web/data/neetcode150-problems.sqlite— offline statements + local golden testsweb/data/ai-interview-questions.sqlite— AI engineering question bank (+ source, tutor context, notes sheets)notes/ai-interview/— pregenerated answer guidebooks (<section-slug>/<id>.md)web/lib/problems-db.ts— SQLite schema helpers for scrape + Vite APIweb/lib/question-bank-db.ts— question bank SQLite helpersweb/lib/question-difficulty.ts— Easy/Medium/Hard classifier + within-section sortscripts/import-question-tutor-context.ts— import teaching briefs into SQLite (optional regen)scripts/import-question-notes-sheets.ts— import notes-sheet markdown into SQLiteprompts/ai-interview-notes-sheet.md— guidebook section order and quality barweb/index.html— home (tracks + local chat)web/flashcards.html— NeetCode 150 triangular deckweb/question-bank.html— question bank triangular deck + coachprompts/home-chat-system.md— home chatbot system promptprompts/home-transcribe-system.md— image transcriber (OCR + fortify) system promptscripts/vision-ocr.swift— on-device Apple Vision OCR helper used by Image transcriberweb/src/lib/triangular.ts— shared climb/descend deck builderprompts/socratic-ai-interview-system.md— beginner AI interview tutor protocolscripts/scrape-neetcode-problems.ts— scrape NeetCode → SQLitescripts/scrape-ai-interview-questions.ts— scrape AI interview Q bank → SQLitescripts/enrich-problem-tests.ts— build local goldens via official Python solutionsbackend/harness/run_problem.py— offline Python judgebackend/— Socratic tutor CLI + vLLM OpenAI clientprompts/socratic-neetcode-system.md— tutoring protocolscripts/neetcode-local-stack.sh— flashcard local stackscripts/run-socratic-tutor.sh— tutor launchersessions/— saved tutor transcripts (gitignored)examples/— sample problem pastes for the tutor