NextCRM: a self-hosted CRM where the invoicing and the audit trail are part of the repo
NextCRM — Open-source CRM built with Next.js 16, React 19, PostgreSQL, Prisma 7, and shadcn/ui. CRM, projects, invoicing, documents, email client & AI features.
At a glance
- What is it?
- NextCRM is an MIT-licensed CRM built on Next.js 16, React 19, Prisma 7 and PostgreSQL, with invoices, projects, documents, an email client, an MCP server for AI agents and E2B-sandboxed enrichment. The interesting part is not the feature list but the fact that invoicing, soft delete and a per-entity audit timeline ship in the same codebase as the contact tables.
- Who is it for?
- Adopt NextCRM if you are a Next.js team that wants CRM, invoicing and document storage in one PostgreSQL schema you control, and you accept running Postgres with pgvector, MinIO and an Inngest worker alongside the app. Do not adopt it if you need a vendor to answer the phone at 2am, if you cannot run Docker in production, or if you expect the invoice module to satisfy a tax authority without review.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What NextCRM replaces, and for whom
Most open-source CRMs stop at contacts and deals, which leaves the invoice in a separate tool and the change history in a database backup. NextCRM's README describes a single application that covers CRM entities (Accounts, Contacts, Leads, Opportunities, Contracts), project management, invoicing, document storage, an email client and AI features, all on PostgreSQL through Prisma 7. The pitch is consolidation: one schema, one auth layer, one deployment.
The audience is narrow and identifiable. The package.json requires Node >=22.12.0 and pnpm >=10.0.0, and the Dockerfile builds from node:22-alpine. If your team already runs Next.js and is comfortable with Prisma migrations, the stack is familiar. If you are a sales operations team with no engineer, the installation path (Postgres with the pgvector extension, MinIO, an Inngest dev server) is a real obstacle rather than a formality. The README points to demo.nextcrm.io for people who want to look before installing, and that is the honest first step for a non-technical evaluator.
The invoicing module is the part that distinguishes this from a generic CRM clone. According to the README, invoices have line items with quantity, unit price, discount percent and tax rate, a status lifecycle of DRAFT to ISSUED to PAID, PARTIALLY_PAID or CANCELLED, auto-numbered series with configurable prefix and suffix, multi-currency support, PDF generation at /api/invoices/[id]/pdf, and email delivery through Resend. Only drafts are editable, which is the correct constraint and also the one users complain about first.
How the data model, audit trail and AI jobs fit together
The architecture is a Next.js app talking to PostgreSQL, with side services for storage and background work. docker-compose.yml defines four services: postgres on the pgvector/pgvector:pg17 image (the vector extension is there for embeddings), minio for object storage, inngest for background jobs, and the app itself. The Inngest service runs `inngest dev -u http://app:3000/api/inngest`, so the worker polls the app for registered functions rather than the app pushing to it. The compose file notes there is no healthcheck on Inngest because the image ships no HTTP client, and the app depends on it with `service_started` instead.
The audit design is the most consequential decision in the schema. The README states that records are never hard-deleted: a `deletedAt` column hides them from normal queries, and `/admin/audit-log` shows a global filterable table with restore support. A `diffObjects` utility computes before/after diffs and stores structured JSON per change, rendered on each entity detail page through `AuditTimeline` and `AuditEntry` components. That is a genuine operational commitment, not a checkbox. It also means your database grows monotonically, and the README does not describe a retention or archival policy for audit rows.
Activities use a separate link table, `crm_ActivityLinks`, so one call can attach to both a Contact and an Opportunity. The feed uses compound cursor pagination on `createdAt` plus `id`, which is the right call for stable ordering when rows share a timestamp. Mutations go through Next.js server actions with Zod validation rather than API routes, and the invoice module follows the same pattern.
AI enrichment moved from a Firecrawl API path to an E2B cloud sandbox running a real Chrome browser. The README describes an LLM tool-use loop driven by Claude Sonnet 4.6 with tools named `browser_open`, `browser_snapshot`, `browser_click`, `browser_extract` and `web_search`, a five-minute timeout per target, and a confidence threshold of 0.6 below which fields are discarded. Only empty target fields are overwritten. After a company is enriched, each discovered contact is enriched by a separate Inngest job. The e2b.Dockerfile and e2b.toml at the repository root are the sandbox definition, so the agent environment is versioned with the app rather than configured in a vendor dashboard.
Installing NextCRM locally and creating a first invoice
The README's installation section is the source for these steps; the repository scripts confirm them. Start with the environment file, because the Prisma CLI reads `.env` and not `.env.local`. The example file documents the local database URL and warns that the migration scripts refuse to run against anything but localhost.
cp .env.example .env
# DATABASE_URL="postgresql://nextcrm:nextcrm@localhost:5433/nextcrm"Bring up Postgres from the dev compose file, wait for it to accept connections, then apply migrations and seed demo data. The `db:wait` script retries `pg_isready` up to 60 times and exits with an error message pointing at `pnpm db:up` if the container never becomes healthy.
pnpm db:up
pnpm db:wait
pnpm db:migrate
pnpm db:seedThe seed runs only when `SEED_DEMO_DATA=1` is set, which the `db:seed` script does for you. Note that `db:migrate`, `db:seed` and `db:reset` all pass through `pnpm db:guard`, which runs `scripts/assert-local-db.sh`; if you point `DATABASE_URL` at a remote host, those three commands will refuse to execute. That guard is a deliberate safety rail and it will surprise anyone who expects migrations to run against staging from a laptop.
Start the background worker and the app. The Inngest dev server is needed for enrichment and other queued work; the app itself runs on port 3000.
pnpm inngest:up
pnpm devOpen http://localhost:3000, sign in, and create an Account. On the account detail page you should see tabs for Activities and History. The History tab is populated by the audit layer described above, so a field edit should produce a timeline entry with the actor and timestamp. For invoices, the README places admin configuration at `/admin/invoices`, where tax rates, invoice series and currencies are managed before the first invoice is issued. API keys for AI features are optional at install time: the README documents a three-tier priority of environment variable, then admin system-wide key at `/admin/llm-keys`, then user key at `/profile?tab=llms`, with encrypted storage using AES-256-GCM and an informative dialog when no key exists at any tier.
Where NextCRM is the wrong tool
The operational surface is the first limitation. A production deployment needs PostgreSQL with pgvector, an S3-compatible object store (MinIO in the compose file), and an Inngest worker that can reach the app. That is three moving parts beyond the Next.js process, and the compose file itself admits the Inngest container has no working healthcheck. If your platform team cannot run stateful services, a hosted CRM will cost less than the time you spend on this.
The migration story is the second. The README states plainly that the old `openAi_keys` table is replaced by a new `ApiKeys` table and that you must run `pnpm prisma migrate deploy` to apply it. There is a `migrate:mongo-to-postgres` script and a `validate:migration` script in package.json, which tells you the project has already been through one storage migration. Anyone upgrading from an older MongoDB-based deployment should treat that path as the riskiest part of the upgrade, and the README does not document rollback for it.
Invoicing carries a third caveat. The module generates PDFs, applies per-line tax rates and tracks payments, but the README describes configuration, not compliance. There is no statement about e-invoicing formats, jurisdiction-specific numbering rules, or archival requirements. If you invoice in a regulated market, treat the module as a document generator and verify the output against your accountant's requirements before you send anything to a customer.
Finally, the AI enrichment path is a paid dependency by construction. It needs an E2B sandbox and an Anthropic key, and the README sets a five-minute timeout per target with partial results applied on timeout. That means enrichment is best-effort: a slow site produces a partially filled record rather than an error you can retry deterministically.
NextCRM compared with wiring a headless CRM to your own billing stack
The realistic alternative is not another CRM with the same feature list. It is a headless CRM or a plain database for contacts, combined with a dedicated billing service such as a hosted invoicing API, and a separate audit mechanism. The difference is where the coupling lives.
In that split approach, the invoice is a record in the billing provider, and the CRM stores a customer identifier. Upgrades to tax logic happen on the provider's schedule, and you inherit their compliance work. The cost is that a change to how an opportunity relates to an invoice requires work in two systems, and the audit trail is split across both. NextCRM takes the opposite position: the invoice, its line items, its payment history and its audit entries live in tables you can query with one join. That is a real advantage for reporting and for anyone who has tried to reconcile a billing export against a CRM export.
The trade-off is that you own the tax engine. NextCRM gives you configurable tax rates and VAT summary buckets; it does not give you a tax service. Teams that want the provider to be liable for calculation correctness should stay with the split. Teams whose invoicing is simple and whose reporting needs cross the CRM and billing boundary should look hard at the integrated schema, because that is the part that is expensive to retrofit.
Maintenance, releases and what the MIT licence leaves to you
The repository is not archived, and the last push was on 2026-09-11. The release history shows v0.22.0 on 2026-08-10, with v0.21.2 and v0.21.1 earlier in August, and the repository carries release-please-config.json and .release-please-manifest.json, so releases are generated from conventional commits rather than tagged by hand. The CHANGELOG.md at the root is the file to read before an upgrade; the README's migration note about `ApiKeys` is exactly the kind of change that appears there first.
Upgrade cost is dominated by the database, not the JavaScript. The `build` script runs `prisma generate && prisma migrate deploy && next build`, so a deploy applies migrations automatically. That is convenient and also means a failed migration blocks the build rather than surfacing at runtime. The presence of `db:guard` on the local scripts, but not on the build script, is worth noting: the guard protects developer machines, not production.
NextCRM is MIT-licensed, and the LICENSE file is at the repository root. MIT permits commercial use and modification, and it comes with no warranty. The practical implication is that support is whatever the maintainers and the Discord community provide; there is no vendor obligation to fix an invoice bug on your deadline. The AI features introduce a second layer of terms that the repository licence does not cover: E2B, Anthropic, OpenAI, Resend, Firecrawl and Rossum are separate services with their own pricing and data handling. If your CRM data is subject to a data processing agreement, sending contact records into a cloud sandbox for enrichment is a decision your legal team needs to make, not a configuration toggle.
Editorial conclusion
Adopt NextCRM if you are a Next.js team that wants CRM, invoicing and document storage in one PostgreSQL schema you control, and you accept running Postgres with pgvector, MinIO and an Inngest worker alongside the app. Do not adopt it if you need a vendor to answer the phone at 2am, if you cannot run Docker in production, or if you expect the invoice module to satisfy a tax authority without review. Before committing, run the migration against a copy of your own data, check that `pnpm db:guard` accepts your database host, and read prisma/schema.prisma to confirm the soft-delete and audit columns cover the entities you actually store.
Frequently asked questions
What stack does NextCRM require to run?
The README describes Next.js 16, React 19, TypeScript and PostgreSQL through Prisma 7, with shadcn/ui for the interface. package.json requires Node >=22.12.0 and pnpm >=10.0.0, and docker-compose.yml adds MinIO for object storage and an Inngest service for background jobs.
How do I install NextCRM locally?
Copy .env.example to .env, then run pnpm db:up, pnpm db:wait, pnpm db:migrate and pnpm db:seed to start Postgres, wait for it, apply migrations and load demo data. Start the worker with pnpm inngest:up and the app with pnpm dev, then open http://localhost:3000.
Why do NextCRM database commands refuse to run against a remote database?
The db:migrate, db:seed and db:reset scripts call pnpm db:guard, which runs scripts/assert-local-db.sh. The .env.example notes that these commands refuse to run unless DATABASE_URL points at localhost, which prevents accidental migrations against a shared or production database.
Does NextCRM delete CRM records permanently?
The README states that records are never hard-deleted; a deletedAt column hides them from normal queries while preserving the data. The admin audit log at /admin/audit-log includes restore support for soft-deleted records.
Can an AI agent read and write NextCRM data?
Yes. The README describes a built-in Model Context Protocol server exposing 127 tools across 15 modules, with list, get, search, create, update and delete operations for entities such as Accounts, Contacts, Leads and Opportunities. This lets agents like Claude or Cursor work with CRM data directly.
Do I need API keys to run NextCRM?
The README states the app runs without any keys in .env because API keys follow a three-tier priority: environment variable, then admin system-wide keys at /admin/llm-keys, then user keys at /profile?tab=llms. Enrichment buttons show an informative dialog when no key is available at any tier.
Community notes