Inspiration

I built Recall because I was tired of running into the same problem: I’d remember who someone was (“the talented developer from BSV,” “the investor from the hackathon”) but not their name or where I’d stored them. Contact info was scattered across my phone, spreadsheets, and notes.

Also, I lost all my business contacts one day because of a failed iPhone sync.

I researched traditional CRMs but they felt too rigid and manual.

I wanted a personal CRM that works the way I actually remember people, by context and situation, not just exact names, and that I could update quickly, including by voice, instead of copying and pasting into forms.

What I learned

  • I can reach the app from my phone over the local network, but ngrok makes it safer. Google is great for syncing contacts from Apple. I use it to keep my iPhone contacts in sync and avoid losing them again.
  • I found strong building blocks, including TanStack Table: a powerful table library with a great UI for sortable, filterable, resizable columns. I didn’t worry about its learning curve because Cursor handled the integration and wiring, so I could focus on features instead of API details.
  • I got more comfortable using the same Cursor chat and leaning on auto mode, without stressing about model choice or context windows.
  • Working with semantic embeddings (e.g. OpenAI’s) showed me how to search contacts by meaning instead of exact keywords.
  • Hackathons are super fun and I am comfortable working solo.

How I built the project

  • Solo, using Cursor and my Macbook Pro.
  • Tech Stack: Next.js 14 (App Router) with TypeScript, SQLite + Prisma, Tailwind, shadcn/ui, and TanStack Table.
  • AI: OpenAI for embeddings and extraction; ElevenLabs for voice-to-text. Semantic search uses in-memory cosine similarity over stored embeddings, with a text fallback.
  • Features: Natural-language add (text or voice), edit-by-voice with contact matching and a preview-before-apply flow, record & send email (transcribe → polish with GPT → Resend), and optional Google Contacts sync.
  • Data model: Contacts link to companies (many-to-one) and tags (many-to-many). Company context is included in embeddings so search understands “that person from X.”
  • Other services. ngrok. Google OAuth.

Challenges

  • Syncing contacts from my phone right after adding them. Figuring out how to do this was the main challenge.
  • Edit-by-voice flow: Getting the preview vs. apply flow right and the JSON payload (applyFromPreview, contactId, proposedUpdates) correct so updates actually saved.
  • Mobile recording: Chrome on iPhone limits MediaRecorder; I used ngrok to test on a real device and confirmed HTTPS + user gesture.

Built With

Share this project:

Updates