Javis OS
Javis OS is an Agentic AI that assists entrepreneurs in business tasks, helping them grow their work.
AI translation
NextCRM is an open source CRM build on top of NextJS.
BusinessTypeScript · MDXGitHub @pdovhomiljaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
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.
Taken from the repository README
Loading the full README.
Read the full README ↗You can try it here demo.nextcrm.io, login via Google account or create new user and password.
Complete invoicing system built into NextCRM — create, issue, pay, duplicate, and cancel invoices with multi-currency support, tax rates, and PDF generation.
INV-2026-0001)next-intlDRAFT → ISSUED → PAID / PARTIALLY_PAID / CANCELLED with permission guards (only drafts are editable)/api/invoices/[id]/pdf/admin/invoicesAll 5 CRM entity detail pages (Accounts, Contacts, Leads, Opportunities, Contracts) now have an Activities tab with a live paginated feed of interactions:
createdAt + id for stable orderingcrm_ActivityLinks (e.g. a call can reference both a Contact and an Opportunity)Every CRM entity (Accounts, Contacts, Leads, Opportunities, Contracts) now tracks its full change history:
AuditTimeline + AuditEntry componentsdeletedAt column preserves data while hiding it from normal queries/admin/audit-log shows a global filterable table of every change across all entities, with restore support for soft-deleted recordsdiffObjects utility computes before/after diffs and stores structured JSON in the audit recordBackground target enrichment (queued, bulk and MCP) now runs inside an E2B cloud sandbox — a full Linux environment with a real browser (Chrome). Contact enrichment and interactive target enrichment still use Firecrawl + OpenAI:
browser_open, browser_snapshot, browser_click, browser_extract, web_searchcrm_Target_Contact records automaticallyEnrichment API keys (OpenAI, Firecrawl, Anthropic) are resolved through a 3-tier priority system, so enrichment works without those keys in .env. Other AI features (record embeddings, document enrichment) read OPENAI_API_KEY from the environment only, and E2B needs E2B_API_KEY in the environment:
ENV variable → Admin system-wide → User profile
(highest) (lowest)
/admin/llm-keys) — set system-wide keys for OpenAI, Firecrawl, Anthropic, and Groq. Keys are encrypted at rest (AES-256-GCM)./profile?tab=llms) — users configure their own keys as a fallback.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.
Every tool with its input fields, generated from the code: MCP tools reference.
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 (streamable HTTP — recommended):
{
"mcpServers": {
"nextcrm": {
"type": "http",
"url": "https://your-nextcrm.com/api/mcp/mcp",
"headers": { "Authorization": "Bearer nxtc__your_token_here" }
}
}
}
The server supports both MCP transports defined by mcp-handler:
/api/mcp/mcp — single POST endpoint, current MCP spec default/api/mcp/sse — GET stream paired with POSTs to /api/mcp/message (client auto-discovers the message endpoint)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.
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.
text-embedding-3-small for vector embeddings; GPT for project management assistantmcp-handler (Vercel MCP adapter), Bearer token auth, streamable HTTP (/api/mcp/mcp) + legacy SSE (/api/mcp/sse, needs REDIS_URL) transportsany types — ongoing cleanupWe use resend.com + react.email as primary email sender and email templates.
NextCRM supports Mailtrap as an alternative email provider to Resend, for both production sending and safe dev/staging testing through a single API.
Sending emails (production):
.env.local: MAILTRAP_API_KEY=Testing emails (dev/staging, optional):
Use a Mailtrap Sandbox inbox instead of a production domain during development, so test emails (OTP, invoices, notifications) never reach real inboxes.
We use Tremor charts as a tool for creating charts in NextCRM
Youtube Channel Invoice module (video)
Read the docs at docs.nextcrm.app: user guide, admin guide and developer guide. Source lives in apps/docs.
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
Linux / macOS:
cp .env.example .env
cp .env.local.example .env.local
Windows (PowerShell):
Copy-Item .env.example .env
Copy-Item .env.local.example .env.local
Windows (Command Prompt):
copy .env.example .env
copy .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
- MinIO / S3 (
MINIO_*) - for storing files- openAI - for embeddings and project management assistant (embeddings need
OPENAI_API_KEYin the environment; enrichment can use an admin-panel key instead)- Firecrawl - for contact/target enrichment (optional — can be set via admin panel instead)
- Resend (
RESEND_API_KEY,EMAIL_FROM) and optional SMTP (EMAIL_HOST, …) for emails- Inngest - for background jobs (
INNGEST_DEV=1with the local dev server frompnpm inngest:up)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 -d
Windows:
cpandnanoare not available on Windows. UseCopy-Item(PowerShell) orcopy(Command Prompt) to copy the file, and edit it withnotepad:Copy-Item .env.docker .env notepad .env # set ADMIN_EMAIL to a real email you own
Open 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_EMAILto an address you control AND provide aRESEND_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 | 127.0.0.1:9000 |
inngest | Background job runner (self-hosted, signed requests) | internal only |
The app is published on port 3000. MinIO's S3 port is published on 127.0.0.1:9000 because browsers upload and download files directly from MinIO; on a server, give MinIO its own domain and set MINIO_PUBLIC_URL to it. Postgres and Inngest stay on the internal Docker network. 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 -d
Windows (PowerShell):
Copy-Item .env.docker .env
notepad .env # set ADMIN_EMAIL, internal service passwords, and any optional API keys
docker compose up -d
[!WARNING] The bundled Postgres and MinIO containers ship with a placeholder password (
changeme) so the stack works on first run. Postgres is not exposed to the host and MinIO only on127.0.0.1, so this is safe for local experimentation. For any deployment beyond your laptop, set strong values forPOSTGRES_PASSWORDandMINIO_ROOT_PASSWORDin your.envfile before starting the stack.
On a server, also set the two public URLs:
APP_URL=https://crm.example.com # what people open; used for auth and links
MINIO_PUBLIC_URL=https://files.example.com # what browsers use to reach MinIO
Secrets. BETTER_AUTH_SECRET, EMAIL_ENCRYPTION_KEY, INNGEST_SIGNING_KEY and INNGEST_EVENT_KEY are generated on first start and stored in the app_data volume, so they survive restarts and upgrades. You can set them in .env instead; a value in the environment always wins. Never change them once set: a new BETTER_AUTH_SECRET logs everyone out, a new EMAIL_ENCRYPTION_KEY makes stored mailbox passwords and API keys unreadable.
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. API keys left empty can also be entered in the admin panel; an environment value always wins over the admin panel:
# 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
[email protected] # verified Resend sender for login codes
FIRECRAWL_API_KEY=fc-... # enables contact enrichment
.env is in .gitignore, so your secrets never get committed.
Data persists across restarts in four named volumes:
postgres_data — your databaseminio_data — uploaded filesapp_data — generated secrets (/app/data/secrets); back it up with the databaseinngest_data — background job state (queued runs, schedules)docker compose down # stops services, keeps data
docker compose down -v # stops services AND wipes all data
git pull
docker compose up -d --build
The 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.
Upgrading an instance installed before document files became private? Run the one-time bucket policy step in docs/deployment/private-document-files.md.
This setup works with self-hosting platforms:
/docker-compose-coolify.yml, set your env vars in Coolify's UI (required ones are listed at the top of that file). Assign your domain to the app service (port 3000) and a second domain to minio (port 9000), then set APP_URL and MINIO_PUBLIC_URL to them.docker-compose.yml into a stack, add env vars in the UIIn all cases, env vars set through the platform UI override the defaults 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 and EMAIL_FROM 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 ends with the email; value is the OTP code followed by : and the attempt count, e.g. 606331:0.)
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.
Made with contrib.rocks.
Licensed under the MIT license.