CodingIdeas.ai
← Browse All Ideas

Build Guide

How to Build a Notes App

A notes app with AI search is 10× more useful than Notion for 80% of users — and you can build the core in a weekend.

Beginner2–5 days

Notes apps are deceptively complex: rich text editing, fast full-text search, and cross-device sync are each a rabbit hole. Master them and you have the building blocks of every knowledge management tool.

Data model

The core tables you'll need before writing any UI.

Userid, email, created_at
Notebookid, user_id, name, created_at
Noteid, notebook_id, user_id, title, content (JSON — TipTap format), plain_text (for search), tags, pinned, updated_at

Build order

The sequence that minimises rewrites — build in this order.

1

Minimal text editor

Install TipTap with the StarterKit extension. Render an editor and a list of notes side by side. Save content to state on every change. No persistence yet.

2

Save notes to Supabase

Create the notes table. On editor change (debounced 1s), upsert the note. Store TipTap's JSON output in content and a plain-text version in plain_text for search.

3

Note list with search

Build the note sidebar — list of titles sorted by updated_at. Add a search input that filters by plain_text using Postgres ILIKE or full-text search (tsvector).

4

Tags and notebooks

Add a tags array to the note. Render tag pills in the editor header. Add a notebooks sidebar — notes belong to a notebook. Add a filter by notebook or tag.

5

Pin, archive, and delete

Add pinned and archived booleans to notes. Pinned notes appear at the top of the list. Archived notes are hidden unless the user opens the archive view.

6

AI Q&A over notes

Add a "Chat with your notes" panel. On each query, fetch the top 5 most relevant notes using Postgres full-text search, send them as context to Claude, and stream the response back.

7

Export to Markdown and PDF

Convert TipTap JSON to Markdown using the tiptap-markdown extension. For PDF, render the note in a hidden div and use html2canvas + jsPDF to export.

Done when

Observable behaviors that confirm V1 is complete — verify each one before you ship.

  • User creates a note, types content, and it auto-saves within 1 second — no manual save button

  • Full-text search returns the correct note within 500ms of typing in the search box

  • AI Q&A returns an answer grounded in the user's notes within 5 seconds

  • Exporting a note to Markdown preserves all formatting (bold, headings, lists)

  • App opens with 2 example notes so the editor is never blank on first visit

First Run Requirement

Seed 2 example notes on first login — a Getting Started guide and a demo note with rich formatting (bold, headers, lists). No blank editor on first use.

Build it with AI — Architect Prompt

Paste this into Claude, Cursor, Windsurf, or any AI coding tool. It includes the full context of this guide — data model, build order, done conditions, and pitfalls — so the AI starts with everything it needs.

ClaudeCursorWindsurfCopilotGemini
architect-prompt.txt
<context>
App: Notes App
Difficulty: Beginner
Estimated build time: 2–5 days
Tech stack (intermediate): Next.js + Supabase + TipTap + Postgres full-text search

Data model:
  User: id, email, created_at
  Notebook: id, user_id, name, created_at
  Note: id, notebook_id, user_id, title, content (JSON — TipTap format), plain_text (for search), tags, pinned, updated_at

FIRST RUN REQUIREMENT:
Seed 2 example notes on first login — a Getting Started guide and a demo note with rich formatting (bold, headers, lists). No blank editor on first use.

DONE WHEN — verify each before marking V1 complete:
  □ User creates a note, types content, and it auto-saves within 1 second — no manual save button
  □ Full-text search returns the correct note within 500ms of typing in the search box
  □ AI Q&A returns an answer grounded in the user's notes within 5 seconds
  □ Exporting a note to Markdown preserves all formatting (bold, headings, lists)
  □ App opens with 2 example notes so the editor is never blank on first visit

Recommended build order:
  1. Define API contract + schema + seed data (always first)
  2. Minimal text editor — Install TipTap with the StarterKit extension. Render an editor and a list of notes side by side. Save content to state on every change. No persistence yet.
  3. Save notes to Supabase — Create the notes table. On editor change (debounced 1s), upsert the note. Store TipTap's JSON output in content and a plain-text version in plain_text for search.
  4. Note list with search — Build the note sidebar — list of titles sorted by updated_at. Add a search input that filters by plain_text using Postgres ILIKE or full-text search (tsvector).
  5. Tags and notebooks — Add a tags array to the note. Render tag pills in the editor header. Add a notebooks sidebar — notes belong to a notebook. Add a filter by notebook or tag.
  6. Pin, archive, and delete — Add pinned and archived booleans to notes. Pinned notes appear at the top of the list. Archived notes are hidden unless the user opens the archive view.
  7. AI Q&A over notes — Add a "Chat with your notes" panel. On each query, fetch the top 5 most relevant notes using Postgres full-text search, send them as context to Claude, and stream the response back.
  8. Export to Markdown and PDF — Convert TipTap JSON to Markdown using the tiptap-markdown extension. For PDF, render the note in a hidden div and use html2canvas + jsPDF to export.
  9. End-to-end verification — walk every Done When condition above (always last)

Known pitfalls to avoid:
  - Saving on every keystroke — debounce saves by 500–1000ms or you'll exhaust your Supabase free tier in days with active use.
  - Forgetting to keep plain_text in sync — if you only store TipTap JSON, full-text search won't work. Strip HTML and store plain text on every save.
  - Losing cursor position on re-render — don't recreate the TipTap editor instance on every state change. Keep editor state inside the editor component and sync it out via onUpdate.
</context>

<role>
You are a Senior Full-Stack Engineer and product architect who has shipped production Notes Apps before. You know exactly where developers get stuck and how to structure the project to avoid rewrites.
</role>

<task id="step-1-clarify">
Before writing any code or spec, ask me 3–5 clarifying questions that will meaningfully change the architecture. Focus on: scale expectations, auth requirements, platform (web / mobile / both), must-have vs nice-to-have features for the MVP, and any hard constraints (budget, deadline, existing infrastructure).

<example>
BAD: "What tech stack do you want to use?" — too broad, doesn't change architecture decisions.
GOOD: "Do you need real-time sync across devices, or is single-device with periodic refresh acceptable? This decides whether we use WebSockets or simple REST polling and significantly affects infrastructure complexity."
</example>

⚠️ Do NOT start planning or writing code until I answer. Present the questions, then stop and wait.
</task>

<task id="step-2-architect">
After I answer your questions, produce the following in order:

1. TECHNICAL SPECIFICATION
   - System architecture using → to show data and event flow
   - Core data model (refer to data model in <context>)
   - API contract — list ALL routes with request/response shapes BEFORE any implementation
     WHY: agreeing on contracts first prevents rewrites when frontend and backend shapes diverge
   - External APIs and integration points

2. MVP PLAN in three phases:

   SETUP   ✦ Step 1 (always): API contract + schema migration + seed data
     Done when: schema is migrated, seed script runs, app starts with demo data, zero manual setup.

   CORE FEATURES — build in this exact order:
   2. Minimal text editor
   3. Save notes to Supabase
   4. Note list with search
   5. Tags and notebooks
   6. Pin, archive, and delete
   7. AI Q&A over notes
   8. Export to Markdown and PDF

   DONE WHEN — one observable condition per feature:
   □ User creates a note, types content, and it auto-saves within 1 second — no manual save button
   □ Full-text search returns the correct note within 500ms of typing in the search box
   □ AI Q&A returns an answer grounded in the user's notes within 5 seconds
   □ Exporting a note to Markdown preserves all formatting (bold, headings, lists)
   □ App opens with 2 example notes so the editor is never blank on first visit

   STRETCH GOALS — post-launch additions that are explicitly out of V1 scope.

3. BLOCKER ANALYSIS
   Flag: API rate limits, auth complexity, scope risks, cold-start problems, top 2–3 failure modes.

   FIRST RUN REQUIREMENT: Seed 2 example notes on first login — a Getting Started guide and a demo note with rich formatting (bold, headers, lists). No blank editor on first use.
   ✓ Done when: app launches with seed data and the full user journey works without any manual setup.

<self_check>
Before presenting your output, verify:
□ Every answer I gave to clarifying questions is reflected in the spec
□ Step 1 is ALWAYS: API contract + schema + seed — never UI first
□ Done When criteria are observable user behaviors, not internal states
□ The plan is realistic for one person to ship within 2–5 days
□ All known pitfalls from <context> are addressed in the spec
</self_check>
</task>

<task id="step-2.5-agents-md">
Generate an AGENTS.md file at the project root. This file is read automatically by Claude Code, Cursor, Windsurf, and all major AI coding tools at the start of every session.

Include:
- Project overview (2–3 sentences)
- Tech stack with exact version numbers
- Folder structure with one-line descriptions per directory
- Key architectural decisions and the WHY behind each
- Coding conventions: camelCase components, kebab-case files, max 200 lines per file, one concern per file
- Available commands: dev, build, test, lint, db:migrate, db:seed
- MVP scope boundaries — features explicitly out of V1

Note in the file: "Cursor users: symlink .cursorrules → AGENTS.md. Claude Code users: symlink CLAUDE.md → AGENTS.md."
</task>

<task id="step-3-implement">
Implement the full project in the exact order from step 2. For each step:
- Write complete code (no placeholders or TODOs)
- Confirm the step works before moving to the next

<constraints>
- Step 1 is ALWAYS: define all API routes + TypeScript request/response interfaces + run schema migration
  WHY: agreeing on contracts before writing a single component prevents shape mismatches that require rewrites
- Final step is ALWAYS: start the app and walk every Done When condition from <context> end-to-end
  WHY: a spec that passes unit tests but breaks the core user journey is not done
- Max 200 lines per file. WHY: every file must fit in one AI context window for complete reasoning
- One concern per file. WHY: mixing auth logic into API routes makes it impossible to reuse — extract to lib/auth.ts
- TypeScript strict mode, no `any` types. WHY: catches data shape mismatches at compile time, not in production
- All database queries in server components or API routes only. WHY: keeps credentials server-side
- All environment variables documented in .env.example. WHY: next developer sets up in under 5 minutes
</constraints>
</task>

How to use this prompt

  1. 1.Copy the prompt above
  2. 2.Open Claude, Cursor (Cmd+L), or Windsurf
  3. 3.Paste the prompt and send — the AI will ask 3–5 clarifying questions
  4. 4.Answer the questions, then it generates your full project spec
  5. 5.Continue in the same session to implement step by step

Common mistakes

What trips up most developers building this for the first time.

⚠️

Saving on every keystroke — debounce saves by 500–1000ms or you'll exhaust your Supabase free tier in days with active use.

⚠️

Forgetting to keep plain_text in sync — if you only store TipTap JSON, full-text search won't work. Strip HTML and store plain text on every save.

⚠️

Losing cursor position on re-render — don't recreate the TipTap editor instance on every state change. Keep editor state inside the editor component and sync it out via onUpdate.

Recommended tech stack

Pick the level that matches your experience.

Beginner

React + TipTap + localStorage — working editor in a day

Intermediate

Next.js + Supabase + TipTap + Postgres full-text search

Advanced

Next.js + Supabase + pgvector for semantic search + Claude API for Q&A over notes

Take it further — related ideas

Each comes with revenue math, a full build guide, and a prompt to paste into Claude or Cursor.