A relationship-first CRM. The premise: you must know the customer to build the relationship — so the person, not the deal, is the atom, and what you learn about them is structured, private-by-default data rather than a notes blob.
docker compose up -d # Postgres :5452, Redis :6381
pnpm install
cp .env.example apps/web/.env.local # then set DATABASE_URL and AUTH_SECRET
pnpm --filter web db:generate
pnpm --filter web db:migrate
pnpm --filter web db:seed # demo org, 3 workspaces, 3 users
pnpm dev # http://localhost:4030Seeded sign-in: owner@example.com / demopassword123.
Generate AUTH_SECRET with openssl rand -base64 32.
pnpm import:sheet "/path/to/Sales Tracking Sheet.xlsx"Maps every column of both sheets — relationship type, owner, priority, funnel stage,
introducer, decision maker, pain point, proposal, approach, next action, last contact, memo,
and the whole interaction history with its outcomes. Handles Korean and English, Excel serial
dates, and duplicate names. Re-running updates in place rather than duplicating. Pass
--dry-run to see what it would do.
| Area | State |
|---|---|
| Auth, organizations, workspaces, per-workspace access | ✅ |
| Contacts, companies, deals — lists, detail pages, Kanban with stage history | ✅ |
| Editable pipelines and stages per selling motion | ✅ |
| Interaction logging with outcomes, timelines, My Day | ✅ |
| Structured facts with private/team/org visibility | ✅ |
| Warm-intro paths and referral attribution | ✅ |
| Reporting: coverage, win rate, velocity, funnel leaks, slippage | ✅ |
| Relationship health scoring with visible reasoning | ✅ |
| Workflow automation, duplicate detection, data-health dashboard | ✅ |
| Global search and Cmd-K palette | ✅ |
| Notifications, scheduled digests and weekly account memos | ✅ |
| Public API with token auth, partner scorecards | ✅ |
| PIPA/GDPR consent, export and erasure | ✅ |
| Screenshot capture with annotation | ✅ |
| AI assistant | ✅ built — needs a key (below) |
| Email/calendar auto-capture | ✗ needs Google OAuth credentials |
Three features are built and inert until configured. Each reports its own unconfigured state rather than pretending to work.
| Set this | To enable |
|---|---|
ANTHROPIC_API_KEY (or INTERACTOR_CLIENT_ID + INTERACTOR_CLIENT_SECRET) |
The assistant, and prose in reports. Without it the assistant names the missing variable; reports still generate without commentary. |
SLACK_WEBHOOK_URL |
Slack delivery. In-app notifications work regardless. |
| Google OAuth client | Email and calendar auto-capture (not yet built). |
pnpm worker # weekday 17:00 digest, Monday 07:00 memos, daily 08:00 quiet sweepNext.js 15 · React 19 · TypeScript · Prisma + PostgreSQL 16 · NextAuth v5 · Tailwind v4 with
@interactor/tokens · BullMQ + Redis · Vitest · pnpm + Turborepo.
pnpm dev # dev server on :4030
pnpm test # vitest
pnpm typecheck # tsc
pnpm lint # eslint
pnpm build # production build
pnpm tokens:build # regenerate design tokens after editing packages/tokens/src/tokens.tspnpm typecheck && pnpm lint && pnpm test && pnpm build is what CI runs.
The two that matter most: every permission decision goes through
src/lib/authz, and no screen ever invents data — a surface with nothing real to show
says so.
Licensed under the GNU Affero General Public License v3.0.
Contributions are welcome: see CONTRIBUTING.md. To report a security issue, see SECURITY.md.