NextCRM is an open-source CRM built with Next.js 16, React 19, TypeScript, PostgreSQL (Prisma 7), and shadcn/ui. Features CRM, project management, document storage, email client, AI-powered features, vector search, and MCP server for AI agent access.
Introduction · What's New · Tech Stack + Features · Roadmap · Installation · Repo activity · License · Discord
You can try it here demo.nextcrm.io, login via Google account or create new user and password.
All 5 CRM entity detail pages (Accounts, Contacts, Leads, Opportunities, Contracts) now have an Activities tab with a live paginated feed of interactions:
- Activity types — Notes, Calls, Emails, Meetings, Tasks
- Create / edit / delete — inline Sheet form on every CRM entity detail page
- Paginated feed — compound cursor pagination with
createdAt + idfor stable ordering - Linked records — activities attach to multiple entities via
crm_ActivityLinks(e.g. a call can reference both a Contact and an Opportunity) - Real-time revalidation — server actions revalidate the correct path after every mutation
Every CRM entity (Accounts, Contacts, Leads, Opportunities, Contracts) now tracks its full change history:
- History tab — per-entity timeline of all field changes, shown on every detail page with
AuditTimeline+AuditEntrycomponents - Soft delete — records are never hard-deleted;
deletedAtcolumn preserves data while hiding it from normal queries - Admin audit log —
/admin/audit-logshows a global filterable table of every change across all entities, with restore support for soft-deleted records - Diff engine —
diffObjectsutility computes before/after diffs and stores structured JSON in the audit record
Target and Contact enrichment now runs inside an E2B cloud sandbox — a full Linux environment with a real browser (Chrome) — replacing the previous Firecrawl API path:
- Real-browser research — the agent navigates JS-heavy sites, LinkedIn public profiles, and paginated results that a simple API call cannot reach
- LLM tool-use loop — Claude Sonnet 4.6 drives the research with tools:
browser_open,browser_snapshot,browser_click,browser_extract,web_search - C-level contact discovery — given only a company name, the agent finds all discoverable C-level contacts and creates
crm_Target_Contactrecords automatically - Context-aware strategy — agent skips research it doesn't need (e.g. already has a website → skips domain discovery)
- Confidence scoring — fields below 0.6 confidence are discarded; only empty target fields are overwritten
- 5-minute timeout per target — partial results are applied even if the agent times out
- Fan-out — after company enrichment, each discovered contact is enriched independently via a separate Inngest job
API keys are managed through a 3-tier priority system so the app runs without any keys in .env:
ENV variable → Admin system-wide → User profile
(highest) (lowest)
- Admin panel (
/admin/llm-keys) — set system-wide keys for OpenAI, Firecrawl, Anthropic, and Groq. Keys are encrypted at rest (AES-256-GCM). - Profile settings (
/profile?tab=llms) — users configure their own keys as a fallback. - Graceful degradation — enrichment buttons show an informative dialog when no key is available at any tier.
Migration note: The old
openAi_keystable is replaced by the newApiKeystable. Runpnpm prisma migrate deployto apply the migration.
NextCRM now ships with a built-in Model Context Protocol server, letting AI agents (Claude, Cursor, custom agents) read and write CRM data directly.
127 tools across 15 modules:
| Module | Tools | Operations |
|---|---|---|
| Accounts | 6 | list, get, search, create, update, delete |
| Contacts | 6 | list, get, search, create, update, delete |
| Leads | 6 | list, get, search, create, update, delete |
| Opportunities | 6 | list, get, search, create, update, delete |
| Targets | 6 | list, get, search, create, update, delete |
| Products | 5 | list, get, create, update, delete |
| Contracts | 5 | list, get, create, update, delete |
| Activities | 5 | list, get, create, update, delete |
| Documents | 8 | list, get, create, upload, download, link, unlink, delete |
| Target Lists | 7 | list, get, create, update, delete, add members, remove members |
| Enrichment | 4 | enrich contact, enrich target, bulk contact, bulk target |
| Email Accounts | 1 | list |
| Campaigns | 18 | full lifecycle: CRUD, send, pause, resume, templates, steps, stats |
| Projects | 18 | boards, sections, tasks, comments, documents, watch |
| Reports | 2 | list, run |
Authentication: Generate Bearer tokens (nxtc__...) from your profile page. Tokens are SHA-256 hashed — the raw value is shown only once and never stored.
Connect your MCP client:
{
"mcpServers": {
"nextcrm": {
"url": "https://your-nextcrm.com/api/mcp/sse",
"headers": { "Authorization": "Bearer nxtc__your_token_here" }
}
}
}Both SSE (/api/mcp/sse) and HTTP (/api/mcp/http) transports are supported.
Claude Code Skill: Download the SKILL.md from your Developer profile tab for a ready-to-use Claude Code skill with full tool documentation.
CRM records (Accounts, Contacts, Leads, Opportunities) are automatically embedded using OpenAI text-embedding-3-small via Inngest background jobs.
- Unified search — combines keyword (full-text) + semantic (pgvector cosine similarity) results in a single grouped UI
- Find Similar — every CRM detail page has a "Find Similar" button that surfaces semantically related records across the same module
- Backfill — Inngest function to embed all existing records on demand
- Auto-embed — new and updated records are embedded automatically
Powered by pgvector (PostgreSQL extension) with HNSW indexes for fast approximate nearest-neighbor search.
New Targets module for managing sales targets and target lists — full CRUD, detail view, list management, and MCP tools included.
Global search across all CRM entities from a single search bar — grouped results by entity type, loading skeleton, collapsible sections, and combined keyword + semantic scoring.
- Next.js 16 – React framework for building performant apps with the best developer experience (App Router)
- Better Auth 1.5.x – TypeScript-first authentication framework with email OTP, OAuth (Google), admin plugin, and session management
- Prisma 7.5 – TypeScript-first ORM for PostgreSQL
- React Email 2.x – Versatile email framework for efficient and flexible email development
- PostgreSQL 17+ – Powerful open-source relational database with pgvector extension for AI embeddings
- Resend – A powerful email framework for streamlined email development together with react.email
- UploadThing + S3-compatible storage (DigitalOcean Spaces) – for document file storage
- Inngest – Background job queue for async embedding and AI workflows
- OpenAI API –
text-embedding-3-smallfor vector embeddings; GPT for project management assistant - Anthropic API – Claude Sonnet 4.6 drives the E2B enrichment agent tool-use loop
- Vercel AI SDK 6.x – Unified AI interface
- pgvector – PostgreSQL vector extension for similarity search (HNSW indexes)
- E2B – Cloud sandboxes with real Chrome browser for AI-driven web research and contact enrichment
- MCP Server – 127 tools across 15 modules via
@vercel/mcp-adapter, Bearer token auth, SSE + HTTP transports
- SWR – React Hooks library for remote data fetching
- Axios – Promise based HTTP client for the browser and node.js
- Server Actions – for server side data fetching and mutations
- TanStack React Table – for data tables and server/client side data fetching
- Tailwind CSS v4 – Utility-first CSS framework for rapid UI development
- shadcn/ui – Re-usable components built using Radix UI and Tailwind CSS
- Tremor – A platform for creating charts
- Lucide React – Beautiful and consistent open-source icons
- next-intl – Internationalization for Next.js — English, Czech, German, Ukrainian
- ✅ Docker version — complete bundle to run NextCRM on-premise
- ✅ Upgrade to Next.js 16 — running on Next.js 16 with React 19
- ✅ i18n / localization — 4 languages (English, Czech, German, Ukrainian)
- ✅ Email client — IMAP/SMTP email client built in
- ✅ PostgreSQL migration — migrated from MongoDB to PostgreSQL 17+
- ✅ pgvector embeddings — automatic semantic embeddings via Inngest + OpenAI
- ✅ Vector similarity search — "Find Similar" on all CRM entity detail pages
- ✅ Unified search — keyword + semantic search across all CRM modules
- ✅ CRM Targets module — sales target and target list management
- ✅ MCP server — 25 CRM tools for AI agent access via Bearer token auth
- ✅ AI enrichment — E2B sandboxed agent (real browser + Claude Sonnet) for target/contact enrichment; C-level contact discovery; 3-tier API key management (ENV → admin → user)
- ✅ Audit log & history — soft delete + full field-level change trail on all CRM entities; global admin audit log page
- ✅ CRM Activities — notes, calls, emails, meetings, tasks linked to any CRM entity; paginated feed on all detail pages
- 🔄 More AI powered features — daily summary of tasks and projects
- 📋 Email campaigns management — integration with MailChimp and Listmonk
- 📋 Testing expansion — Jest + Playwright coverage (contributions welcome!)
- 🔄 Fix all TypeScript
anytypes — ongoing cleanup
We use resend.com + react.email as primary email sender and email templates.
We use Tremor charts as a tool for creating charts in NextCRM
Youtube Channel
Invoice module (video)
Available soon at: http://docs.nextcrm.io
Show instructions
-
Clone the repository:
git clone https://github.com/pdovhomilja/nextcrm-app.git cd nextcrm-app -
Install the preset:
pnpm install
-
Copy the environment variables to .env
cp .env.example .env
cp .env.local.example .env.local
.env
- You will need a PostgreSQL connection string for Prisma ORM
- Example:
DATABASE_URL="postgresql://user:pass@localhost:5432/nextcrm?schema=public" - Requires PostgreSQL 17+ with the pgvector extension enabled
.env.local
- BETTER_AUTH_SECRET - for auth
- uploadthings - for storing files
- openAI - for embeddings and project management assistant (optional — can be set via admin panel instead)
- Firecrawl - for contact/target enrichment (optional — can be set via admin panel instead)
- SMTP and IMAP for emails
- Inngest - for background embedding jobs
EMAIL_ENCRYPTION_KEY- required for encrypting API keys stored in the database
-
Init Prisma
pnpm prisma generate pnpm prisma migrate deploy
-
Import initial data from initial-data folder
pnpm prisma db seed
-
Run app on local
pnpm run dev
The fastest way to run NextCRM is with Docker Compose. The provided docker-compose.yml bundles everything you need: the app, PostgreSQL (with pgvector), MinIO for file storage, and Inngest for background jobs. No manual setup of databases, buckets, or migrations — it all happens automatically on first start.
git clone https://github.com/pdovhomilja/nextcrm-app.git
cd nextcrm-app
cp .env.docker .env
nano .env # set ADMIN_EMAIL to a real email you own
docker compose up -dOpen http://localhost:3000 — the app is ready, the schema is migrated, and the seeded admin user matches the ADMIN_EMAIL you set.
Important
NextCRM uses passwordless Email OTP for login. You MUST set ADMIN_EMAIL to an address you control AND provide a RESEND_API_KEY (or another email provider) so OTP codes can actually be delivered. Without an email provider, you can still log in by reading the OTP straight from the database — convenient for first-time testing, not for production.
| Service | Purpose | Exposed |
|---|---|---|
app |
NextCRM (Next.js standalone build) | localhost:3000 |
postgres |
PostgreSQL 17 with pgvector | internal only |
minio |
S3-compatible object storage | internal only |
inngest |
Background job runner | internal only |
Only port 3000 is exposed to the host. Everything else stays on the internal Docker network — secure by default. Uncomment the relevant ports: blocks in docker-compose.yml if you need direct access (e.g. for psql or the MinIO console).
You never edit Dockerfile or docker-compose.yml to add your secrets. Instead, create a .env file in the project root — Docker Compose reads it automatically and injects the values into the container.
cp .env.docker .env
nano .env # set ADMIN_EMAIL, internal service passwords, and any optional API keys
docker compose up -dWarning
The bundled Postgres and MinIO containers ship with a placeholder password (changeme) so the stack works on first run. The internal services are not exposed to the host network — only the app on port 3000 is reachable — so this is safe for local experimentation. For any deployment beyond your laptop, set strong values for POSTGRES_PASSWORD and MINIO_ROOT_PASSWORD in your .env file before starting the stack.
The .env.docker file lists every supported variable with comments. Beyond the internal service passwords, you only need to add values for optional external integrations you want to enable:
# Example .env
OPENAI_API_KEY=sk-your-real-key # enables AI features
GOOGLE_ID=...apps.googleusercontent.com # enables Google OAuth
GOOGLE_SECRET=GOCSPX-...
RESEND_API_KEY=re_... # enables transactional email
FIRECRAWL_API_KEY=fc-... # enables contact enrichment.env is in .gitignore, so your secrets never get committed.
Database and uploaded files persist across restarts via two named volumes:
postgres_data— your databaseminio_data— uploaded files
docker compose down # stops services, keeps data
docker compose down -v # stops services AND wipes all datagit pull
docker compose up -d --buildThe entrypoint runs prisma migrate deploy on every start, so new schema changes are applied automatically. The seed only runs on first install (when no users exist), so your data is safe across upgrades.
This setup works out of the box with self-hosting platforms:
- Coolify — point it at this repo, choose "Docker Compose" build pack, set your env vars in Coolify's UI
- Portainer / Dockge — paste
docker-compose.ymlinto a stack, add env vars in the UI
In all cases, env vars set through the platform UI override the placeholders in docker-compose.yml the same way a .env file does locally.
After first start, the seeded admin account uses whatever you set in ADMIN_EMAIL. Since login is passwordless Email OTP, there are two paths:
With email provider configured (recommended)
Set RESEND_API_KEY (or another supported provider) in .env, then enter your ADMIN_EMAIL on the sign-in page and check your inbox for the OTP.
Without email provider (first-run testing)
Read the OTP directly from the database:
docker compose exec postgres psql -U nextcrm -d nextcrm \
-c 'SELECT identifier, value, "expiresAt" FROM "Verification" ORDER BY "createdAt" DESC LIMIT 1;'(identifier is the email, value is the OTP code.)
Use that OTP on the sign-in page. After login, configure an email provider from the Admin panel so future logins work normally.
We are open to the NextCRM community contributions. Every contribution is welcome.
- Open an issue if you find a bug or have a suggestion for improvements.
Made with contrib.rocks.
Licensed under the MIT license.


