Study a little every day. Your newt grows up with you.
Knewt is a pomodoro study app. Upload notes, then teach them back on camera, take a quiz, or flip flashcards. Time and accuracy earn XP and coins. Your newt grows through stages, and you can dress it from the shop.
Teachers can create classes, assign materials, and see who finished.
- Study sessions -> 25 minutes of focus, then a 5-minute break. Modes:
- Active recall -> speak the topic back on camera; Gemini grades the recitation
- Quiz -> multiple choice generated from the upload
- Flashcards -> flip through generated cards
- Notes -> upload images, PDFs, PPTX, DOCX, or TXT. Text is extracted (OCR for photos) and turned into a teach-back brief, quiz, and flashcards.
- Pet -> every student gets a newt. XP and a 30-day minimum per stage move it from egg → baby → young → old.
- Shop & kennel -> spend coins on accessories and equip them.
- Classes -> teachers create a class with a join code, assign materials with optional due dates, and track completion. Students join and see assigned work on the Study page.
- PWA -> installable, with optional web-push “come back” notifications after a break.
Students land on Home (their newt). Teachers land on Classes.
- Next.js 15 (App Router) + React 19
- tRPC + TanStack Query
- Prisma + PostgreSQL (Neon on Vercel)
- Better Auth -> email/password, optional GitHub
- Google Gemini -> OCR, study content, spoken-recall grading
- Tailwind CSS + shadcn/ui
- Bun
You need Bun and a PostgreSQL database.
bun install
cp .env.example .envFill in .env (see below), then:
bun run db:migrate
bun run db:seed
bun run devThe app runs at http://localhost:3000.
db:seed upserts the shop accessory catalog. Prisma also generates the client on postinstall.
Copy .env.example to .env. The schema in src/env.js is the source of truth.
| Variable | Required | Notes |
|---|---|---|
DATABASE_URL |
yes | Pooled Postgres URL |
DATABASE_URL_UNPOOLED |
for migrations | Direct (non-pooled) URL. Prisma cannot run DDL over a pooler. |
BETTER_AUTH_SECRET |
production | Auth signing secret |
BETTER_AUTH_URL |
local | e.g. http://localhost:3000. On Vercel the host is derived from the deployment. |
BETTER_AUTH_GITHUB_CLIENT_ID / SECRET |
no | Enables GitHub sign-in when both are set |
GEMINI_API_KEY |
for study AI | OCR, teach-back topics, quizzes, flashcards, spoken-recall grading |
VAPID_* / NEXT_PUBLIC_VAPID_PUBLIC_KEY |
no | Break notifications. Generate with npx web-push generate-vapid-keys. |
On Vercel, Neon’s marketplace integration injects both database URLs.
| Script | What it does |
|---|---|
bun run dev |
Next.js with Turbopack |
bun run build / start |
Production build and server |
bun run check |
Lint + tsc --noEmit |
bun run db:migrate |
prisma migrate deploy |
bun run db:generate |
prisma migrate dev |
bun run db:push |
Push schema without a migration |
bun run db:studio |
Prisma Studio |
bun run db:seed |
Seed accessories |
bun run db:backfill-modes |
Backfill quiz/flashcards on existing materials |
Configured for Vercel. vercel.json runs prisma migrate deploy && next build.
Set the env vars above on the project. Production auth uses VERCEL_PROJECT_PRODUCTION_URL; preview deployments use their own host. Point DATABASE_URL_UNPOOLED at a direct Neon connection so migrations can run.
Uploads live in the function temp directory only long enough to extract text in the same request. They are not stored durably.