https://github.com/andresjmorales/cognote
CogNote: Open Source Music Note Practice Tool πΉ
https://github.com/andresjmorales/cognote
flashcards key memorization musical notation quiz signature
Last synced: 3 months ago
JSON representation
CogNote: Open Source Music Note Practice Tool πΉ
- Host: GitHub
- URL: https://github.com/andresjmorales/cognote
- Owner: andresjmorales
- License: mit
- Created: 2026-03-02T19:55:35.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-23T17:03:28.000Z (4 months ago)
- Last Synced: 2026-03-24T14:06:58.084Z (4 months ago)
- Topics: flashcards, key, memorization, musical, notation, quiz, signature
- Language: TypeScript
- Homepage: https://cognote.fun
- Size: 1.72 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# CogNote
**Music note memorization for piano students β quizzes, flashcards, and spaced repetition.**
CogNote is an open-source web app that helps piano teachers assign and track music exercises for their students. Teachers create customizable lesson plans β note identification drills, musical symbol quizzes, or both β share them via unique URLs, and monitor progress through an analytics dashboard. Students β primarily children ages 5β14 β open a link and immediately start practicing. No login, no signup.
---
## Features
### For Teachers
- **Student management** β Add students, track their practice history, and see per-note accuracy breakdowns
- **Customizable lesson plans** β Two plan types: note identification (clef, key signature, specific notes) and musical symbols & concepts (dynamics, tempo, articulation, note values, and more)
- **Reusable templates** β Create lesson plan templates and assign them to multiple students with one click
- **Share via URL** β Each student gets a unique practice link; copy it to clipboard and send to parents
- **Analytics dashboard** β See which notes students struggle with, session history, accuracy trends
### For Students
- **Quiz mode** β Multiple-choice note identification or symbol/concept questions with immediate feedback and score tracking
- **Free practice** β Unlimited questions with no pressure, practice at your own pace
- **Flashcard mode** β Spaced repetition (SM-2 algorithm) for both notes and symbols, with kid-friendly emoji ratings
- **Zero friction** β Open the link, tap "Start", begin practicing. No account needed
- **Kid-friendly UI** β Large buttons, friendly fonts, gentle feedback animations
### Music Notation
- Real staff rendering with [VexFlow](https://www.vexflow.com/) β treble and bass clefs, key signatures, accidentals, ledger lines
- Clean, large notation sized for tablet screens
- **Standalone symbol SVGs** β Clefs, notes, rests, dynamics, articulations, and more are rendered from pre-extracted Bravura (SMuFL) vector paths in `public/symbols/`. No runtime font loading; consistent on all devices including iOS (no βtofuβ from missing Unicode music fonts).
- Built-in library of 40+ musical symbols and concepts across 7 categories
---
## Spaced Repetition
The flashcard mode uses the **SM-2 algorithm** (same as Anki) and works for both note identification and symbol/concept plans. Students rate each card with kid-friendly labels:
| Button | SM-2 Rating | Effect |
|--------|------------|--------|
| π No clue | 1 (Again) | Card resets, shown again this session |
| π€ Tricky | 2 (Hard) | Card resets, shown again this session |
| π Got it! | 4 (Good) | Card graduates, next review in 1βN days |
| β Too easy! | 5 (Easy) | Card graduates, interval grows faster |
See [notes/spaced-repetition.md](notes/spaced-repetition.md) for full algorithm documentation.
---
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Framework | [Next.js 16](https://nextjs.org/) (App Router, Turbopack) |
| Language | TypeScript |
| Styling | Tailwind CSS 4 |
| Music Notation | VexFlow 5 |
| Database | [Supabase](https://supabase.com/) (PostgreSQL + Auth + Row Level Security) |
| Hosting | Vercel (recommended) |
---
## Getting Started
### Prerequisites
- **Node.js 18+**
- **Docker Desktop** β required by the Supabase CLI to run PostgreSQL, Auth, and the REST API locally
### Setup
```bash
# Clone the repo
git clone https://github.com/youruser/cognote.git
cd cognote
# Install dependencies
npm install
# Start local Supabase (pulls Docker images on first run β takes a few minutes)
npx supabase start
# Apply database migrations and seed with test data
npx supabase db reset
# Create your environment file
cp .env.example .env.local
```
After `npx supabase start`, you'll see output with your local credentials. Update `.env.local` with the **Publishable** key (as `NEXT_PUBLIC_SUPABASE_ANON_KEY`) and the **Secret** key (as `SUPABASE_SERVICE_ROLE_KEY`). Generate a token encryption key:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
Your `.env.local` should look like:
```
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
TOKEN_ENCRYPTION_KEY=<64-char hex string you generated>
```
Then start the dev server:
```bash
npm run dev
```
Open [http://localhost:3000](http://localhost:3000).
### Seed Data (Local Development Only)
Running `npx supabase db reset` loads `supabase/seed.sql` with a test teacher account, sample students, lesson plans, and practice history so you can explore the full dashboard immediately. See `seed.sql` for credentials β these are for **local development only** and should never be used in production.
### Clearing students and plans (e.g. production reset)
To wipe all students and lesson plans (and their assignments, sessions, and progress) while keeping teachers and auth intact, run `supabase/clear-data.sql` in the [Supabase SQL Editor](https://supabase.com/dashboard) or via:
```bash
psql $DATABASE_URL -f supabase/clear-data.sql
```
After clearing, **production** is ready for a fresh start. For **local dev**, run `npx supabase db reset` to reapply migrations and seed sample data.
### Local Dev Tools
| Tool | URL |
|------|-----|
| App | [http://localhost:3000](http://localhost:3000) |
| Supabase Studio | [http://127.0.0.1:54323](http://127.0.0.1:54323) |
| Mailpit (email) | [http://127.0.0.1:54324](http://127.0.0.1:54324) |
---
## Project Structure
```
cognote/
βββ app/
β βββ (teacher)/ # Teacher pages (auth required)
β β βββ dashboard/ # Overview with stats and recent activity
β β βββ students/ # Student list + detail views
β β β βββ [id]/ # Per-student analytics
β β βββ plans/ # Lesson plan list, editor, detail views
β β βββ [id]/
β β βββ new/
β βββ (student)/ # Student pages (no auth)
β β βββ practice/
β β βββ [token]/ # Quiz, free practice, flashcard modes
β βββ api/ # API routes
β β βββ auth/ # Teacher account setup
β β βββ dashboard/ # Dashboard summary
β β βββ plans/ # Lesson plan CRUD + assignment
β β βββ practice/ # Student session + attempt tracking
β β βββ students/ # Student CRUD + analytics
β βββ login/ # Teacher login/signup
β βββ page.tsx # Landing page
βββ components/
β βββ music/ # VexFlow renderer, quiz engine, flashcards
β βββ teacher/ # Teacher-specific components
β βββ ui/ # Shared primitives (Button, Card, etc.)
βββ lib/
β βββ supabase/ # Client, server, and middleware helpers
β βββ music.ts # Note utilities, answer generation, presets
β βββ symbol-paths.ts # Auto-generated: Bravura SVG path data (do not edit)
β βββ symbols.ts # Musical symbols & concepts library
β βββ srs.ts # SM-2 spaced repetition algorithm
β βββ token.ts # AES-256-GCM token encryption
βββ public/
β βββ symbols/ # Standalone SVG files (Bravura glyphs)
βββ scripts/
β βββ extract-bravura-glyphs.js # One-time: extract Bravura β SVG + lib/symbol-paths.ts
βββ supabase/
β βββ migrations/ # SQL schema migrations
β βββ seed.sql # Test data for local development
β βββ clear-data.sql # Wipe students & plans (prod-safe; teachers unchanged)
βββ notes/ # Design docs and specs
```
---
## Database Schema
```
teachers
βββ students (one-to-many)
βββ plans (one-to-many)
βββ student_plans (students β plans, many-to-many)
βββ practice_sessions (one-to-many)
β βββ note_attempts (one-to-many)
βββ flashcard_progress (one-to-many, per note or symbol)
```
All teacher data is protected by **Row Level Security** β a teacher can only see their own students, lesson plans, and analytics. Student practice endpoints use token-based access with no authentication.
Migrations live in `supabase/migrations/` and are applied with `npx supabase db reset` (local) or `npx supabase db push` (remote).
**Local:** To apply new migrations (e.g. after pulling changes that add columns), run `npx supabase db reset`. This reapplies all migrations and refreshes the schema cache; it also re-runs the seed, so youβll get fresh test data. If you see errors like βCould not find column X in the schema cacheβ, the DB is out of date β run `npx supabase db reset` (with Docker and `npx supabase start` running).
---
## API Routes
### Teacher-side (authenticated)
| Method | Route | Purpose |
|--------|-------|---------|
| GET | `/api/students` | List teacher's students |
| POST | `/api/students` | Create student |
| PUT | `/api/students/[id]` | Update student |
| DELETE | `/api/students/[id]` | Remove student |
| GET | `/api/students/[id]/analytics` | Student analytics |
| GET | `/api/plans` | List teacher's lesson plans |
| POST | `/api/plans` | Create lesson plan |
| PUT | `/api/plans/[id]` | Update lesson plan |
| DELETE | `/api/plans/[id]` | Remove lesson plan |
| POST | `/api/plans/[id]/assign` | Assign lesson plan to student, get practice URL |
| GET | `/api/dashboard/summary` | Dashboard metrics |
### Student-side (token-based, no auth)
| Method | Route | Purpose |
|--------|-------|---------|
| GET | `/api/practice/[token]` | Resolve token β student name + plan config |
| POST | `/api/practice/[token]/session` | Start a practice session |
| POST | `/api/practice/[token]/session/[id]/attempt` | Record a note attempt |
| PUT | `/api/practice/[token]/session/[id]/complete` | Mark session complete |
| GET | `/api/practice/[token]/flashcards` | Get flashcard state (notes or symbols) |
| PUT | `/api/practice/[token]/flashcards` | Update flashcard after review (notes or symbols) |
---
## Deploying to Production
### 1. Create a Supabase project
Sign up at [supabase.com](https://supabase.com) (free tier is sufficient) and create a new project.
### 2. Push the schema
```bash
npx supabase login
npx supabase link --project-ref
npx supabase db push
```
`db push` applies migrations only β it does **not** run `seed.sql`. Your production database will have the schema but no test data.
### 3. Configure Supabase Auth redirects
If you use email confirmation, Supabase must know where to redirect users after they click the confirmation link:
1. Go to [Supabase Dashboard](https://supabase.com/dashboard) β your project β **Authentication** β **URL Configuration**
2. Set **Site URL** to your production URL (e.g. `https://your-app.vercel.app`)
3. Add your production URL to **Redirect URLs** (e.g. `https://your-app.vercel.app/**`)
4. To support both local and production, add both: `http://localhost:3000/**` and `https://your-app.vercel.app/**`
Without this, confirmation links will redirect to localhost.
### 4. Deploy to Vercel
Connect your GitHub repo to [Vercel](https://vercel.com) and set these environment variables:
| Variable | Where to get it |
|----------|-----------------|
| `NEXT_PUBLIC_SUPABASE_URL` | Supabase Dashboard β Settings β API β Project URL |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Supabase Dashboard β Settings β API β anon (public) key |
| `SUPABASE_SERVICE_ROLE_KEY` | Supabase Dashboard β Settings β API β service_role key (click Reveal) |
| `TOKEN_ENCRYPTION_KEY` | Generate with `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` |
**Important:** Use the keys from your **cloud** Supabase project, not from `.env.local` (which has local Docker keys). Only `TOKEN_ENCRYPTION_KEY` can be copied from local β or generate a new one for production.
Variables without the `NEXT_PUBLIC_` prefix (like `SUPABASE_SERVICE_ROLE_KEY`) are server-only and never exposed to the browser.
### 5. Try a Lesson
The landing page "Try a Lesson" button links to `/try`, a standalone practice page that works without any seed data or database records. Visitors pick a note set and get the same experience students see β Start Lesson, Free Practice, and Flashcards.
---
## Contributing
1. Fork and clone the repo
2. Run `npx supabase start` (requires Docker)
3. Run `npx supabase db reset` to apply migrations and seed data
4. Copy `.env.example` to `.env.local` and fill in the local credentials
5. Run `npm run dev`
6. Full stack is running locally β no cloud accounts needed
### Adding a new migration
```bash
npx supabase migration new
# Edit the generated SQL file in supabase/migrations/
npx supabase db reset # Apply it
```
### Regenerating musical symbol SVGs
Symbols (clefs, notes, dynamics, articulations, etc.) are rendered from Bravura glyphs extracted into `public/symbols/` and `lib/symbol-paths.ts`. To add or update symbols:
```bash
npm install --save-dev opentype.js wawoff2
node scripts/extract-bravura-glyphs.js
```
Edit the `GLYPHS` map in `scripts/extract-bravura-glyphs.js` to add SMuFL code points (see [SMuFL](https://w3c.github.io/smufl/gitbook/)), then run the script. It reads Bravura from the VexFlow package, writes SVGs to `public/symbols/`, and regenerates `lib/symbol-paths.ts`. You can then remove the dev deps if desired.
---
## License
[MIT](LICENSE)