Create beautiful, interactive experiences to tell someone how you feel.
HeartNote lets you craft a personalized, shareable love letter experience — complete with animated envelopes, interactive quizzes, curated playlists, and the big question — all wrapped in a starfield.
Each HeartNote walks the recipient through four immersive steps:
1. The Letter — An animated envelope opens to reveal a scrollable, heartfelt letter with markdown support.
2. The Quiz — A playful questionnaire (favorite date spot, love language, vibe...) with emoji-powered options.
3. The Songs — A curated playlist of songs that remind you of them, with a built-in player and the ability to "love" tracks.
4. The Question — The big moment. A proposal with a celebration screen on "Yes" — and a "No" button that playfully runs away.
Every step is optional and fully customizable through a live-preview editor.
- Shareable links — Each experience gets a unique URL (
/for-you/:id) - Real-time analytics — See when they opened it, how long they spent, which step they're on, and their final answer
- Live preview — See your changes in real-time as you build
- Music search & player — Search songs via JioSaavn, add notes, reorder tracks
- 3D starfield background — Powered by Three.js
- Smooth animations — GSAP-driven transitions throughout
- Fully customizable flow — Enable or disable any of the four steps
| Layer | Tech |
|---|---|
| Frontend | Vue 3, Vue Router, Pinia |
| Animations | GSAP, Three.js |
| Database & Backend | Convex (real-time serverless) |
| Music API | Express.js + JioSaavn API |
| Build | Vite |
| Deploy | Vercel (frontend + backend as separate projects) |
heartnote/
├── src/
│ ├── views/ # Pages
│ │ ├── ExperienceView # The main experience (/for-you/:id)
│ │ ├── CreateView # Create a new HeartNote
│ │ ├── EditView # Edit an existing one
│ │ └── HerRepliesView # Analytics dashboard
│ ├── components/ # UI components
│ │ ├── LandingSection # Envelope + letter animation
│ │ ├── QuestionnaireSection
│ │ ├── SongsSection # Music player
│ │ ├── ProposalSection # The big question
│ │ ├── StarBackground # Three.js starfield
│ │ ├── ConfigForm # Multi-step editor
│ │ └── LivePreview # Real-time preview
│ ├── stores/ # Pinia state
│ └── router/ # Vue Router config
├── convex/ # Convex backend
│ ├── schema.ts # Database schema
│ ├── experiences.ts # Experience CRUD
│ ├── files.ts # File upload/download
│ ├── responses.ts # Quiz responses
│ ├── acceptance.ts # Proposal answers
│ ├── analytics.ts # Engagement tracking
│ └── lovedSongs.ts # Favorited songs
└── vercel.json # Frontend deployment config
- Node.js 20+
- A Convex account
npm installThe backend API is in a separate repo and deployed independently on Vercel.
Copy the example and fill in your values:
cp .env.example .envVITE_CONVEX_URL=https://your-deployment.convex.cloud
VITE_DOWNLOAD_SERVER=https://your-backend.vercel.app# Terminal 1 — Frontend
npm run dev
# Terminal 2 — Convex
npx convex devvercelSet VITE_CONVEX_URL and VITE_DOWNLOAD_SERVER in the Vercel dashboard.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/search?query= |
Global search |
GET |
/api/search/songs |
Search songs |
GET |
/api/search/albums |
Search albums |
GET |
/api/search/artists |
Search artists |
GET |
/api/songs/:id |
Song details |
GET |
/api/songs/:id/suggestions |
Song suggestions |
GET |
/api/albums?id= |
Album details |
GET |
/api/artists/:id |
Artist details |
GET |
/api/artists/:id/songs |
Artist's songs |
GET |
/api/playlists?id= |
Playlist details |
POST |
/api/download |
Download + upload to Convex |
POST |
/api/download/batch |
Batch download (max 10) |
GET |
/api/download/url/:songId |
Get direct stream URL |
| Table | Purpose |
|---|---|
experiences |
Stores experience configurations (letter, quiz, songs, proposal) |
analytics |
Tracks opens, time spent, current step, completion |
responses |
Quiz answers (emoji + label per question) |
acceptance |
The final yes/no answer |
lovedSongs |
Which songs the recipient hearted |
Made with love, for love.