A note-taking app that answers questions about your notes using local semantic search and an AI chat interface.

Role

Developer

Timeline
February 2024

Technologies

  • Next.js
  • TypeScript
  • TailwindCSS
  • shadcn/ui
  • Prisma
  • SQLite (Turso/libSQL)
  • HuggingFace Transformers
  • Groq (GPT OSS-20B)
  • Vercel AI SDK

Tools

  • GitHub
  • Clerk v6
  • Radix UI

Background

I kept losing things in my own notes. Keyword search only works if you remember the exact word you wrote, and six months later you never do. I wanted to see if I could just ask my notes a question and get an answer back.

Solution

Notes are embedded locally via HuggingFace Transformers (bge-small-en-v1.5, 384-dim) at save time and stored in SQLite with cosine similarity queries, no external embedding API needed. Queries match by meaning, not exact characters. The chat model runs on Groq's free tier (gpt-oss-20b), streamed through the Vercel AI SDK. Clerk handles authentication so notes stay private to their owner. Everything runs on SQLite via Prisma + Turso/libSQL.

Process

I built plain note CRUD first, then spent most of the project on the retrieval side: getting embeddings generated reliably on note create/update, and wiring the chat assistant to pull from the index before answering. The tricky parts were keeping the embedding pipeline in sync with the database and making retrieval failures obvious instead of silently returning wrong answers.

Final Product

Impact

It works well enough that I stopped digging through old notes manually. It also taught me where semantic search breaks down. Short or ambiguous notes still return poor matches.

Reflection

The hard part wasn't any single service. It was keeping the database, the embedding pipeline, and the index in sync without the whole thing becoming fragile. The switch to local embeddings and SQLite removed two external API dependencies. If I rebuilt it today I'd look harder at search accuracy tuning and handling much larger note collections.