A softer way to study.
Built on learning science. Designed to feel like home.
βΆ Watch the 3-min demo Β Β·Β Live app Β Β·Β Blog post Β Β·Β Run locally Β Β·Β Architecture Β Β·Β Documentation Β Β·Β Product spec
"You don't become knowledgeable in a day. You become knowledgeable one remembered idea at a time."

βΆΒ Watch the 3-minute demo
A full walkthrough β the learning loop, the AI pipeline, and the TestSprite verification story.
Nora is an entry in TestSprite Hackathon Season 3 β "Build the Loop." The TestSprite CLI was used as the checker in a real write β verify β fix β verify loop, running browser tests in the cloud against the live app and handing back one self-consistent failure bundle the coding agent acts on.
| 57 durable scenarios (50 browser + 7 backend) | 57 / 57 passing |
Every test createdFrom: cli |
not the portal β genuine CLI loop |
| 55 loop iterations Β· 100+ runs Β· 7 build days | 10 real product bugs caught & fixed |
| Coverage grew 20 β 57 live | 2 features shipped under the loop |
When two new tests came back blocked, the run summary drove the fix and a rerun turned them green β a clean create β blocked β diagnose β fix β rerun β pass cycle. Across 55 iterations the loop caught 10 genuine bugs, from duplicate UI cards to mood-sync contradictions and an onboarding tour that re-appeared on every fresh browser session. The full per-iteration story is in LOOP.md, the submission write-up in SUBMISSION.md, and the banked plans + an archived failure bundle in testsprite_tests/.
(Jump to the verification loop section for the details.)
Nora is a study operating system β not a flashcard app, not a timer with a coat of paint, and not an AI homework generator. It wraps six evidence-based learning strategies from cognitive science inside a cozy pixel-art world where a companion grows as your understanding deepens.
The whole product is built on one belief: the AI should help you think, never think for you. It asks questions, finds real academic sources, surfaces the gaps in your understanding, and schedules your review at the right moment β but you always do the thinking, because the thinking is the point.
Nora is a living product. The core loop and all 22+ features are functional and tested (394 unit tests, 57 TestSprite scenarios, all green). Development continues β there's always another room to make warmer.
βοΈ Welcome home.
β
π Revisit three fading memories.
β
π‘ Explain one difficult idea in your own words.
β
ποΈ Catch one mistake the AI planted.
β
πΎ Your companion notices you're getting better.
β
Close your laptop
knowing a little more
than yesterday.
Most study apps try to make you study longer. Nora tries to help you understand better. Four things set it apart:
- A full learning system, not a single trick. Feynman explanation, grounded research, active video study, spaced-repetition review, practice exams, a memory garden, and a journal all live in one cohesive world β each feeding the next, not bolted on.
- AI that teaches, never authors. Every evaluation is grounded in real source material. Every citation links to a real paper (OpenAlex, Crossref, Unpaywall). When Nora isn't sure, it says "unverified" instead of inventing an answer. It never writes your explanation for you.
- Compassionate by design. No streaks to break, no leaderboards to shame you. Miss a few days and nothing resets β your garden simply fades (as knowledge does), your friends get a gentle "check on them" quest, and your companion says welcome back.
- A place with a memory and an identity. The companion remembers what was hard last week. The garden and the journal quietly accumulate your growth over months. It reads as a place you return to, not a tool you operate.
And underneath all of it: every learning feature is backed by published cognitive-science research, cited in the code and in the science section below.
Your companion remembers what you've been working on. It notices when something was hard yesterday. It celebrates when you finally get it.
It never judges. It never pressures. It just studies with you.
"I remember this one gave us trouble yesterday."
Understanding matters more than memorization.
Curiosity beats pressure.
AI should teach, not think for you.
Knowledge grows slowly β and that's okay.
(The full design philosophy lives in docs/WHY_NORA.md, docs/CRAFT.md, and docs/DESIGN_PRINCIPLES.md.)
Nora is organized as places, not pages β each with its own mood and pace.
Start each session with a calm overview. Your companion speaks. Fading memories surface gently. No dashboards β just clarity about what today asks of you.
Explain ideas in your own words until they click. Nora listens as an "inquisitive student," asks 2β3 probing questions, paraphrases you back in technical terms, and marks each part of your explanation green / amber / red. When you attach a source, feedback is graded against the real passage. When you don't, it's clearly labelled unverified.
The AI writes an explanation with hidden mistakes. Can you find them? Grounded in research on productive failure β catching and correcting errors strengthens far-transfer understanding more than avoiding them.
Reviews appear right before you'd forget them. Grade how well you recalled each one; the FSRS-6 scheduler moves the familiar ones further away and brings the shaky ones back sooner.
Ask a question in plain words. Get an answer grounded in real academic papers, with every citation linking to a real source. Two modes: from your papers (hybrid retrieval over your indexed PDFs) and from the web (live academic search). When fewer than two sources are found, it says so.
Watch lectures with AI-generated, timestamped notes. A Tiptap editor turns any moment into a clickable timestamp. Explain what you just watched, and every video becomes flashcards that link back to the exact second.
Your notes become a two-voice study conversation you can listen to on a walk β the AI explains, then asks, and pauses so you can think.
Each topic is a plant. Blooming means you remember well; wilting means it's fading. Tap a wilting plant to review just those cards. Not punishment β nature.
See how your concepts connect across subjects. Tap a node to explore its relationships and watch mastery spread.
Surprising connections between topics you'd never link on your own. Physics meets economics. Biology meets programming. The best learning happens at the edges.
Your story, in your own words. Every explanation you wrote, in order β the ones you struggled with and the ones that finally clicked. No graphs. Just the arc of becoming someone who understands.
Upload your notes; the AI builds a timed exam from your material β multiple choice, short answer, and explain-in-your-own-words. Missed questions become flashcards.
Sessions spread across the week with expanding gaps, because spacing beats cramming. The planner does the math, merges your real university calendar, and forward-fills a missed session instead of compressing the rest.
Small study groups with shared weekly goals. When someone disappears, the group gets a "check on them" quest β never a leaderboard, never shame.
Import a study group's deck with one click, then study it on your schedule with fresh scheduling.
Each place feeds the next. Notes and papers become questions; questions become explanations; explanations become memories; memories bloom into a garden and a journal.
Your notes Β· papers Β· videos
β
Research Desk (OpenAlex + hybrid RAG)
β
Knowledge Web (how ideas connect)
β
Feynman Mode (explain β grounded evaluation)
β
Flashcards + Error Spotter
β
FSRS-6 scheduling (the right interval)
β
Memory Garden (knowledge, visualized)
β
Journal (who you're becoming)
Every AI answer follows the same grounded path β retrieve real sources first, generate second, and never let the model invent. This is the actual data flow in code (rag/parser.ts β lib/rrf.ts β lib/llm.ts), not a marketing diagram:
Your notes Β· PDFs Β· a question
β
βΌ
Ingestion parser.ts β chunker β embedder
β (OpenAI text-embedding-3-small,
βΌ optional; FTS-only fallback)
paper_chunks (Postgres + pgvector)
β
βΌ
Retrieval ββ pgvector cosine (match_paper_chunks RPC)
queryRag() ββ Postgres FTS (ts_rank_cd)
β β
βββββΊ Reciprocal Rank Fusion (lib/rrf.ts, unit-tested)
β
βΌ
Generation Groq (Llama 3.3 70B) ββfallbackβββΊ OpenRouter
β grounded ONLY in the retrieved chunks;
β < 2 sources β says so Β· unverified β labelled
βΌ
Answer + real citations (OpenAlex Β· Crossref Β· Unpaywall Β· Semantic Scholar)
Outbound fetches (papers Β· web Β· calendars) pass through lib/ssrf.ts.
Web search (optional) via Tavily. Retrieved text is data, never a prompt.
For the full system design β data model, AI pipeline, retrieval, and security boundaries β see ARCHITECTURE.md.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Server Actions, RSC) |
| Language | TypeScript (strict), Node.js β₯ 20 |
| UI | React 19, Tailwind CSS v4, a custom pixel-UI component library |
| Database | Supabase β Postgres, pgvector, Row-Level Security, Storage (22 SQL migrations) |
| Auth | Supabase Auth, gated at the edge via proxy.ts |
| Spaced repetition | ts-fsrs (MIT) β FSRS-6 DSR model |
| AI (primary / fallback) | Groq Cloud (Llama 3.3 70B) β OpenRouter |
| Embeddings | OpenAI text-embedding-3-small (optional; Postgres FTS fallback) |
| Academic sources | OpenAlex (CC0), Crossref, Unpaywall, Semantic Scholar |
| Web search | Tavily (optional) |
| RAG retrieval | pgvector cosine + ts_rank_cd FTS β Reciprocal Rank Fusion |
| Rich text | Tiptap v3 (custom timestamp mark) |
| Video | YouTube IFrame API + transcript extraction (Groq Whisper fallback) |
| Testing | Vitest + fast-check (property-based) β 394 tests across 26 files |
Every learning feature is a decision grounded in published research, not a guess.
| Feature | Grounding |
|---|---|
| FSRS scheduler | Ye et al. (2022) β reduces review load ~20β30% vs SM-2 at equal retention |
| Interleaving | Brunmair & Richter (2019) β helps procedural/visual (g Γ’β°Λ 0.34β0.67), hurts vocabulary (g Γ’β°Λ β0.39) |
| Spacing | Cepeda et al. (2008) β optimal gap scales with the retention interval |
| Error spotting | Springer (2023) β deliberate erring improves far-transfer learning |
| Confidence calibration | MIT (2025) β metacognitive feedback reshapes study behaviour |
| Self-explanation | Chi (2000); Fiorella & Mayer (2016) β explaining to learn |
Nora applies these conditionally β for example, it interleaves math and visual topics but deliberately blocks vocabulary, because the evidence says interleaving hurts there.
- 394 tests across 26 files (Vitest), including property-based tests (fast-check) for the parts where correctness is subtle: FSRS scheduling, spacing math, timezone-safe due dates, and the study-mix queue. Core logic is written as pure functions so it can be tested without a database.
- Production build is type-checked end to end (
tscinnext build) under TypeScript strict mode. - End-to-end flows (auth, review, Feynman, research, planner) are exercised with TestSprite scenario plans (see
.testsprite/plans/).
npm test # run the suite (Vitest)
npm run build # production build + full type-checkSecurity posture β Row-Level Security on every user-owned table, SSRF protection on all outbound fetches, and authorization-scoped SECURITY DEFINER database functions β is documented in SECURITY.md.
Nora is an entry in TestSprite Hackathon Season 3 β "Build the Loop." The TestSprite CLI runs real browser tests in the cloud against the live app (norastudy.vercel.app) and hands back one self-consistent failure bundle the coding agent acts on: create β run β failure get β fix β rerun, and every pass is banked. The suite is 57 scenarios, all green, every one createdFrom: cli β 50 frontend flows plus 7 backend security/schema checks.
What the loop covers β a durable suite of frontend scenarios spanning the critical path and feature depth:
| Area | Banked scenarios |
|---|---|
| Entry & auth | Landing page + sign-up CTA Β· Login β dashboard Β· Signup β onboarding wizard |
| Core loop | Dashboard stats + daily quests Β· Sidebar navigation Β· Review card full flow Β· Review JOL confidence gate |
| Learning features | Feynman evaluation + gap analysis Β· Study Mix interleaved queue Β· Research Desk sources + synthesis Β· Study Room video search Β· Study Planner weekly calendar Β· Practice Exam setup Β· Listen Mode Β· Error Spotter |
| Knowledge tools | Knowledge Web explorer Β· Eureka connections Β· Memory Garden Β· Journal ("Your Story") |
| World & social | Pixel Room pet + missions Β· Party create/join Β· Card Market Β· Analytics dashboard Β· History Β· Settings theme persistence Β· Create subject/topic |
Backend (--type backend) |
Schema + FSRS/gamification column validation Β· RLS data isolation (cards / topics / feynman reject anon) Β· RLS reward-manipulation rejection |
Testing what the browser can't see. A frontend run proves a page renders; it can't prove the database rejects an unauthorized request. Row-Level Security is invisible from the UI, so three checks were written as backend tests (testsprite test create --type backend) that hit the database as an anonymous client and confirm the rejection β anon can't read another user's cards or topics, can't insert forged cards, and can't call the reward RPC to mint XP. The feature isn't just tested; it's proven safe. Full table in LOOP.md β Backend Testing on TestSprite.
Real fixes the loop caught (see LOOP.md for the full per-iteration log):
- Signup redirect β a new account landed on a blank
/app; the loop caught it and the fix redirects straight to/app/onboarding. - Analytics navigation β a banked test was reaching a dead
/app/room/analyticsURL (404); the failure bundle showed the route mismatch, and the plan was corrected to open the real/app/analyticsroute. - Knowledge Web & Eureka
blockedβ green β while expanding coverage toward the final 43-test suite, both pages rendered correctly but a verbose two-branch assertion made the testing agent run out of runway before a verdict. The run summary revealed the exact empty-state controls, so each plan was tightened to a single decisive assertion, pushed withtest plan put, and reran green β a textbookcreate β blocked β diagnose β fix β rerun β passcycle.
One honest limitation, documented not faked: the mobile bottom-nav test was removed after two runs proved the cloud runner uses a fixed desktop viewport and can't simulate a mobile-width resize. The BottomNav is correctly wired and works for real users β this is a runner limitation, out of scope per the "state outside the test's control" rule.
The banked suite lives on the TestSprite platform under the submitting account; the plan files, an archived failure bundle, and a full ID-level index are in testsprite_tests/, with per-run artifacts under .testsprite/.
| Requirement | Version | Notes |
|---|---|---|
| Node.js | β₯ 20 | Required by ts-fsrs |
| Supabase project | any | Local CLI stack or a hosted project |
| Groq API key | β | Free tier is enough to start |
git clone https://github.com/lxcario/Nora.git
cd Nora
npm install
cp .env.example .env.local
# fill in your keys (minimum: Supabase URL + anon key, and GROQ_API_KEY)Apply the database schema to your Supabase project (run the SQL in supabase/migrations/ in order via the Supabase SQL editor, or supabase db push with the CLI), then start the dev server:
npm run devOpen localhost:3000.
Nora degrades gracefully β a missing optional key disables one feature, it never breaks the app.
| Variable | Required? | Enables |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY |
Required | Database, auth |
GROQ_API_KEY |
Required | Feynman, research synthesis, RAG answers |
OPENROUTER_API_KEY |
Recommended | LLM fallback when Groq is rate-limited |
ACADEMIC_API_EMAIL / ACADEMIC_API_MAILTO |
Recommended | Higher-rate "polite pool" academic search; Unpaywall OA PDFs |
TAVILY_API_KEY |
Recommended | Web results in the Research Desk |
OPENAI_API_KEY |
Optional | Vector (semantic) RAG; without it, ranked keyword search is used |
YOUTUBE_API_KEY |
Optional | Video search (direct URLs still work without it) |
FIRECRAWL_API_KEY |
Optional | Automated university-calendar discovery |
SEMANTIC_SCHOLAR_API_KEY |
Optional | Richer academic metadata / TLDRs |
See .env.example for the annotated, complete list.
Nora/
βββ src/
β βββ app/
β β βββ (auth)/ Login / signup
β β βββ (protected)/app/ The app shell + every "place"
β β β βββ _actions/ Server Actions (business logic)
β β β βββ _components/ Shared app-shell components
β β β βββ feynman/ review/ research/ study-room/ planner/
β β β βββ memory-map/ journal/ exam/ party/ analytics/ β¦
β β β βββ layout.tsx Auth gate + app shell
β β βββ _components/ Landing page
β β βββ globals.css Pixel design system (tokens, sprites, motion)
β βββ proxy.ts Edge auth gate / session refresh
β βββ components/pixel-ui/ The pixel-art component library
β βββ lib/ FSRS, spacing, RAG, SSRF guard, voice, copy
βββ supabase/
β βββ migrations/ 22 SQL migrations (schema, RLS, RPCs)
β βββ tests/ SQL tests (e.g. hybrid search)
βββ docs/ Philosophy, product spec, architecture notes
βββ public/ Sprites, fonts, images
βββ .env.example Annotated environment reference
Nora's docs are meant to be read, not skimmed. Start with the philosophy β it explains every product decision.
| Document | What it covers |
|---|---|
docs/WHY_NORA.md |
Why the product exists, in plain language |
docs/DESIGN_PRINCIPLES.md |
The five (plus one) rules behind every decision |
docs/CRAFT.md |
The design beliefs guiding Nora's future |
docs/VOICE.md |
How Nora speaks β the vocabulary and tone |
docs/PRODUCT_DESCRIPTION.md |
The complete feature-by-feature product spec |
ARCHITECTURE.md |
System design, data model, AI pipeline |
SECURITY.md |
Auth, RLS, SSRF, and secret handling |
A full index lives in docs/README.md.
Nora has a voice and a set of beliefs, and staying true to them matters more than shipping fast.
- Read
docs/VOICE.mdfirst β it defines how Nora speaks. - Then
docs/DESIGN_PRINCIPLES.mdβ five rules. - Before opening a PR, ask the question from
CRAFT.md: does this make Nora feel more alive, help someone understand more deeply, and still belong here five years from now?
If your change makes Nora feel more like Nora β welcome.
Application code is MIT. Assets carry their own licenses: LPC character art is CC BY-SA 3.0 / GPL 3.0, and the UI sprites are CC0. Academic data comes from OpenAlex (CC0), Crossref, and Unpaywall under their respective terms. See docs/ASSETS.md for the full attribution list.
Companion pet visuals are treated as third-party demonstration assets and are excluded from the MIT source-code grant. Nora is an independent, non-commercial educational project; third-party content remains with its respective owners.
Nora is an educational, non-commercial project. Third-party content is used for technical demonstration only, and all rights remain with their respective owners.
π±
Knowledge grows slowly.
Thank you for growing with Nora.
Built by Resque.
