Spaced-repetition flashcards for system design interviews.
Original cards, rubric-based grading, FSRS scheduling, zero accounts.
Try it · Browse the cards · Contribute a card
Most interview prep tells you to "practise out loud". MetaStack is the deck you practise against.
- 64 original cards in three decks: Fundamentals (39), Estimation (10), Classic designs (15).
- Rubric grading. Every card has three to six key points. Before the reveal, a short exercise drawn at random (recall the points one by one, recall them from plain-language hints, match hints to points, or pick the points out of a mixed list) makes you produce the answer; the points you got are ticked for you, and your coverage sets the rating. Design prompts are broken into interview stages (requirements, estimates, API, data model, high-level design, deep dives, failure modes), each with its own rubric.
- FSRS scheduling via a small, pure, 100%-tested wrapper around ts-fsrs. Cards you fumble return tomorrow; cards you nail wait weeks.
- Works without an account. Progress is stored in your browser (IndexedDB) and can be exported or imported as JSON. Sign in with GitHub if you want a server copy on Neon.
- Keyboard first.
Spacereveals,1–9tick key points,Enteraccepts the suggested rating. Quick mode:1–4rate directly. - Fast, dark-mode, mobile, accessible. Pages are pre-rendered. Sign-in and sync use small server routes.
git clone https://github.com/masaok/metastack.git
cd metastack
pnpm install
pnpm dev # http://localhost:3000Requires Node 20.9+ and pnpm 12 (corepack enable will pick up the pinned version).
Other useful commands:
pnpm validate # lint every card against the schema
pnpm test # unit tests for the scheduler and content pipeline
pnpm test:coverage # same, enforcing 100% on packages/srs
pnpm e2e # Playwright drill-flow tests
pnpm build # production build
pnpm db:seed # add the repository's cards to the configured databaseflowchart LR
md["packages/content/cards/**/*.md<br/>Markdown + YAML front matter"] -->|zod validate| json["generated/cards.json"]
json -->|seed| neon[("Neon<br/>cards")]
neon --> web["apps/web (Next.js)"]
srs["packages/srs<br/>FSRS wrapper, pure functions"] --> web
web -->|reads / writes| idb[("IndexedDB<br/>card states, reviews, settings")]
idb -->|export / import| file["JSON file"]
- Cards are Markdown files with front matter. A compile step validates them with zod (closed tag vocabulary, 3–6 key points, at least one public reference,
reviewed: true) and writes a JSON bundle. Invalid cards fail the build. - That bundle seeds the
cardstable in Neon. The web app reads cards from the database and pre-renders every page, refreshing them in the background. With no database configured it serves the bundle directly, so a fork runs withpnpm devalone. - In the browser,
buildSessionmerges due reviews with new cards (default limit 10/day),ratingFromRubricmaps your tick count to a rating, andrateasks FSRS for the next due date.
Read more in docs/ARCHITECTURE.md and the ADRs.
SM-2 (1987) multiplies the interval by a fixed ease factor. FSRS fits a three-component memory model (difficulty, stability, retrievability) to your actual review history and schedules for a target retention, 90% by default. Across published benchmarks it needs noticeably fewer reviews for the same retention. ADR 0002 has the reasoning and the parameters we use.
apps/web/ Next.js 16 app (App Router, Tailwind v4, Dexie)
packages/content/ cards/*.md (the database seed), schema, compiler, validator
packages/srs/ FSRS wrapper: createCardState, rate, buildSession, ...
docs/ architecture notes and ADRs
scripts/check-public.sh CI guardrail for a public repository
The most valuable contribution is a good card. See CONTRIBUTING.md for the content rules (original wording, rubric style, references) and run pnpm validate before opening a PR. Found an error? Report it.
MIT. Card content is also MIT, written from scratch for this project with references to public sources.