Ship It: Supabase + Vercel · lesson 3 of 3
How This Site Works
claude.upliftduo.com is itself a worked example of most topics in this wiki. The end-to-end shape:
Obsidian vault (markdown + wiki-links)
→ build-content.mjs (parse frontmatter, MCQs, flashcards)
→ static JSON
→ Next.js 16 App Router (static pages + client islands)
→ Supabase (auth + RLS-protected ca_ tables)
→ Remotion Player explainers
→ Vercel (hosting, cron)
← weekly Claude Code automation (re-research → regenerate → redeploy)
Content layer: an Obsidian vault
All content is plain markdown in an Obsidian vault — notes like this one, connected by wiki-links. Authors (human or QSTORM) never touch the site code; they write notes.
Build pipeline: build-content.mjs
A build script converts the vault to static JSON the app consumes. Its three parsers:
- Lenient frontmatter parser — the
---block on these notes is not strict YAML (tags: [#level/401, ...]would choke a YAML parser on#); the parser reads the known keys by pattern instead. - MCQ parser — practice questions are markdown under
## Q1-style headings with answers declared as**Q1: B.**; the parser lifts them into structured items. - Flashcard extractor — every
- **Term** — definitionbullet in a "Key terms" section becomes a flashcard automatically. (That is why every 401 note carries a Key terms section — the bullets are the deck.)
Frontend: Next.js 16 App Router
Content pages are statically generated at build time from the JSON — fast, cacheable, SEO-friendly. Interactivity (quiz runner, flashcard reviews, video controls) lives in client components islanded inside the static shell. Deployed as in vercel-deployment.
Persistence: Supabase
Auth plus RLS-protected ca_-prefixed tables in a shared Supabase project (the pattern detailed in supabase-for-app-devs) store per-user state:
- reading progress
- quiz attempts (per item, for weakness targeting — the adaptive step of the quiz-me loop)
- SM-2 flashcard scheduling state
Spaced repetition: SM-2
Flashcards are scheduled with the classic SM-2 algorithm. Each card carries an easiness factor (EF, initialized 2.5, floored at 1.3) and a review interval:
I(1) = 1 day
I(2) = 6 days
I(n) = I(n-1) × EF for n > 2
after each review with quality q ∈ 0..5:
EF' = EF + (0.1 − (5 − q) × (0.08 + (5 − q) × 0.02))
if q < 3: relearn (interval resets; repetitions restart)
Intuition: q=5 nudges EF up (+0.1), q=4 leaves it roughly flat, q=3 drags it down slightly; anything below 3 doesn't just lower EF — it sends the card back to relearning. EF's 1.3 floor prevents "ease hell" from driving intervals to zero growth.
Video: Remotion Player
Concept explainers are remotion-player embeds — the composition runs live in the browser with inputProps (zero render cost, personalizable per learner), rather than pre-rendered MP4s.
Automation: the weekly loop
A scheduled Claude Code job closes the loop weekly:
- Re-research covered courses/exams against current official docs (the STORM-style grounded research).
- Regenerate stale notes, questions (storm-for-exams), and flashcards.
- Redeploy via Vercel.
The site is thus a standing instance of agentic-patterns: an agent with tools (research, file edits, deploy) on a cron, with humans reviewing diffs rather than writing content.
Key terms
- build-content.mjs — the vault→JSON build pipeline: lenient frontmatter parsing, MCQ parsing (
## Q1/**Q1: B.**), and flashcard extraction. - Lenient frontmatter — this site's non-strict-YAML frontmatter dialect (e.g.
#-prefixed tags inside brackets), read by pattern rather than a YAML library. - Flashcard extraction pattern — the exact
- **Term** — definitionbullet shape from which the pipeline auto-generates flashcards. - Static generation + client islands — Next.js 16 App Router pattern: content pages prebuilt from JSON, interactivity confined to client components.
- ca_ tables — the RLS-protected, prefix-namespaced Supabase tables storing progress, quiz attempts, and flashcard schedules.
- SM-2 — the spaced-repetition algorithm scheduling reviews: EF starts 2.5 (floor 1.3), I(1)=1, I(2)=6, I(n)=I(n−1)×EF.
- Easiness factor (EF) — SM-2's per-card multiplier, updated as EF' = EF + (0.1 − (5−q)(0.08 + (5−q)×0.02)) after each quality-q review.
- Relearn — SM-2's response to quality < 3: the card's interval resets and it re-enters the learning phase.
- Weekly regeneration loop — the scheduled Claude Code automation that re-researches sources, regenerates content, and redeploys the site.
See also
- storm-for-exams — where the practice questions come from
- supabase-for-app-devs / vercel-deployment — the infrastructure halves
- remotion-player — the explainer surface