A local-first personal CRM to help you maintain meaningful relationships. Track contacts, log interactions, monitor relationship health, and never miss a birthday.
- π Relationship Health Dashboard - Visual health scores based on contact frequency
- π₯ Contact Management - Full contact profiles with tags, notes, and gift ideas
- π¬ Interaction Logging - Track calls, messages, meetups, and emails
- π Reminders - Set follow-up alerts for any contact (NEW in v1.1)
- π¨βπ©βπ§ Contact Groups - Organize contacts (Family, Work, etc.) (NEW in v1.1)
- βοΈ Custom Fields - Add your own data fields (NEW in v1.1)
- π₯ CSV Export - Download all contacts with one click (NEW in v1.1)
- π Birthday Reminders - Upcoming birthdays at a glance
β οΈ Action Items - See who you should reach out to- π Search & Filter - Find contacts by name, tags, or notes
- π± Mobile Responsive - Works great on phone, tablet, and desktop
- Next.js 15 - React framework with App Router
- SQLite (better-sqlite3) - Local database, no cloud required
- Tailwind CSS - Utility-first styling
- TypeScript - Type safety
- Lucide React - Beautiful icons
- Node.js 22+
- npm or pnpm
# Install dependencies
npm install
# Run development server
npm run dev
# Open http://localhost:3100The app will automatically:
- Create the SQLite database (
data/relationships.db) - Initialize the schema
- Seed with sample contacts
npm run build
npm start# Install Cloudflare Tunnel
brew install cloudflared
# Login
cloudflared tunnel login
# Create tunnel
cloudflared tunnel create relationships
# Route domain
cloudflared tunnel route dns relationships relationships.yourdomain.com
# Run tunnel (in a separate terminal)
cloudflared tunnel run relationships --url http://localhost:3100Now access from anywhere at https://relationships.yourdomain.com
# Install Tailscale
brew install tailscale
# Start Tailscale
tailscale up
# Access from any device on your Tailscale network
# using your machine's Tailscale IP + :3100ngrok http 3100- Click "Add Contact" button
- Fill in basic info (name required)
- Add tags like "friend", "running", "tech"
- Set contact frequency (how often you want to stay in touch)
- Add gift ideas for easy reference
- Go to any contact detail page
- Click "Log Interaction"
- Select type (call, message, meetup, email)
- Add summary and notes
- Contact's "last contacted" date updates automatically
- Healthy (75-100%) - Within target contact frequency
- Needs Attention (50-75%) - Approaching target frequency
- Neglected (<50%) - Past due for contact
Formula: 100 - ((days since last contact / target frequency) * 100)
If you want to test a Chrome extension that imports LinkedIn contacts into the CRM:
- Create
.env.localwith your extension ID:
CORS_ALLOWED_EXTENSION_IDS=ogodllnlbnmkhmaccmnoepajfapennja- Restart the app with
npm run dev - Have the extension
POSTtohttp://localhost:3100/api/import/linkedin
For the unpacked extension in this repo, load [browser-extension/README.md](/Users/fernandoamaral/Dev/Personal CRM/browser-extension/README.md) and use the bundled stable extension ID above.
Example payload:
{
"fullName": "Ada Lovelace",
"headline": "Staff Engineer at Analytical Engines",
"company": "Analytical Engines",
"location": "London",
"linkedinUrl": "https://www.linkedin.com/in/ada-lovelace/",
"photoUrl": "https://example.com/ada.jpg",
"tags": ["linkedin", "engineering"],
"notes": "Imported from LinkedIn profile"
}The endpoint will:
- map the payload into a CRM contact
- tag the contact with
linkedin - store LinkedIn metadata in
custom_fields - skip creating a duplicate if the email or LinkedIn profile URL already exists
Data is stored in: data/relationships.db
Backup: Simply copy this file to back up all your data.
Edit package.json:
"dev": "next dev -p 3200",
"start": "next start -p 3200"Edit lib/db.ts to change the database location.
- 100% local - No cloud sync, no telemetry
- Your data stays on your machine
- SQLite database is just a file you control
- No authentication needed (single-user app)
# Install dependencies
npm install
# Run dev server with hot reload
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Type check
npm run lintβββ app/
β βββ page.tsx # Dashboard
β βββ contacts/
β β βββ page.tsx # Contact list
β β βββ new/page.tsx # Add contact form
β β βββ [id]/
β β βββ page.tsx # Contact detail
β β βββ edit/page.tsx # Edit contact form
β βββ api/
β β βββ contacts/ # CRUD endpoints
β β βββ interactions/ # Log interactions
β β βββ stats/ # Dashboard stats
β βββ layout.tsx # Root layout
βββ components/ui/ # Reusable UI components
βββ lib/
β βββ db.ts # SQLite client + schema
β βββ utils.ts # Helper functions
βββ data/
βββ relationships.db # SQLite database
If you see "database is locked", close all terminals/processes running the app.
Change the port in package.json or kill the process using port 3100:
lsof -ti:3100 | xargs killrm -rf node_modules package-lock.json
npm installThis is a personal project, but feel free to fork and customize for your needs!
MIT
Built by Legolas (OpenClaw agent) for Miguel Amaral