Multi-tenant CRM backend (ClientDesk) with a Next.js dashboard powered by Node.js, TypeScript, Express, Prisma, and Material UI.
- Multi-tenant CRM: companies isolate users, leads, and clients while preserving lead-to-client origins.
- CRUD endpoints for companies, users, leads, and clients plus credential verification for login.
- Request validation with Zod and typed
ApplicationErrorresponses for predictable HTTP status codes. - Password hashing with Argon2id and PostgreSQL persistence through Prisma.
- OpenAPI 3.0 documentation generated by swagger-jsdoc and served at
/api/docs. - Next.js dashboard with global search, charts, notifications, and lead-to-client conversion flows.
- Node.js and TypeScript with Express 5
- Prisma ORM targeting PostgreSQL
- Zod schema validation
- Swagger JSDoc + Swagger UI Express
- Argon2 for secure password hashing
- dotenv + CORS configuration for environment and origin control
- Next.js 15 (App Router) with React 19 and TypeScript
- Material UI 7 (Emotion) with light/dark theme toggling
- Chart.js + react-chartjs-2 for dashboard visuals
- Axios for HTTP requests
- Zod for client-side validation
- Lucide React icons and context-based state (auth, CRM data, notifications, search)
This repository hosts both the backend API (in the api/ folder) and the Next.js frontend (in the frontend/ folder). You can run them independently or in parallel.
- Node.js 18 or newer
- npm
- A PostgreSQL instance
- Clone the repository and install backend dependencies:
git clone https://github.com/JoaoArnaud/advanced-crm-api.git cd advanced-crm-api/api npm install - Create an
.envfile insideapi/and configure your database and server:DATABASE_URL="postgresql://postgres:postgres@localhost:5432/advanced_crm" PORT=3333 # defaults to 3000 if unset; 3333 matches the Swagger server and frontend fallback CORS_ORIGIN=http://localhost:3000
- Apply the Prisma schema and generate the client:
npm run prisma:migrate # prisma migrate deploy over existing migrations npm run prisma:generate - Install frontend dependencies:
cd ../frontend npm install
- Start the backend (from
api/):npm run dev # tsx watch on the API (PORT from .env or 3000) npm run build npm run start # runs dist/index.js
- Start the frontend (from
frontend/):npm run dev # Next.js dev server on http://localhost:3000 npm run build npm run start
Swagger UI becomes available at http://localhost:<PORT>/api/docs (spec at /api/docs.json). The dashboard consumes the API under <API_BASE>/api (falls back to http://localhost:3333/api when NEXT_PUBLIC_API_BASE_URL is unset).
frontend/
src/
app/ # App Router routes (auth landing, dashboard, settings)
components/ # Layout, dialogs, charts, dashboard widgets, UI helpers
contexts/ # Auth, CRM data, notifications, and search providers
hooks/ # Route protection and shared hooks
services/ # Axios client and resource-specific wrappers
types/ # Shared API/domain TypeScript definitions
Create frontend/.env.local (or export the variable) to point the UI to the backend:
NEXT_PUBLIC_API_BASE_URL=http://localhost:3333/api is appended automatically; if you leave it unset, the app falls back to http://localhost:3333/api.
cd frontend
npm install # install dependencies
npm run dev # start Next.js dev server (http://localhost:3000)
npm run build # production build
npm run start # serve the production build
npm run lint # lint TypeScript/React files- Auth (/): register/login tabs with Zod validation, snackbars for feedback, and redirects after success; registration requires an existing company UUID.
- Home (/home): protected dashboard with metric cards (totals, conversion rate, 30-day deltas), pipeline progress by lead status, recent activities, top clients, and charts (
LeadStatusDonutChart,LeadClientMonthlyChart). Leads and clients tables support search, CRUD dialogs, and lead-to-client conversion (creates the client withleadOriginIdand removes the lead). - Settings (/settings): protected page that loads the authenticated user, allows updating only the name, and shows e-mail/company ID as read-only fields.
- AuthContext: persists the authenticated user in
localStorage, exposes register/login/logout/refresh/update helpers, and hydrates the session on load. - CRMDataContext: fetches leads/clients for the user’s company and provides create/update/delete plus conversion helpers with inline error surfacing.
- NotificationContext: stores recent lead/client events and unread counts; rendered by
NotificationMenu. - SearchContext: keeps a shared search query (used by
SearchBar) to filter leads and clients. - Route Protection:
useProtectedRouteredirects anonymous visitors back to/. - Services: axios instance resolves the API base URL and centralizes calls under
src/services/.
LayoutProvidersapplies MUI theming, responsive typography, and a persistent light/dark toggle stored inlocalStorage.DashboardLayoutoffers a responsive sidebar, global search, notifications, and user menu across protected pages.- Dialog components (
LeadDialog,ClientDialog,ConfirmDialog) encapsulate form validation, and charts use Chart.js wrappers. - Global tokens in
globals.csskeep colors consistent between light and dark modes.
- Prisma models live in
api/prisma/schema.prismaand target a PostgreSQL datasource configured viaDATABASE_URL. - Entities:
Company: parent record for the multi-tenant structure.User: belongs to a company, storespasswordHash, and defaults to roleUSER.Leads: prospects tied to a company withLeadStatus(HOT,WARM,COLD), plus optionalcnpj/cpf.Clients: customers tied to a company, optionally linked to a lead origin (leadOriginId).
- Run Prisma tooling from
api/:npm run prisma:generate npm run prisma:migrate # applies existing migrations npm run prisma:studio src/scripts/seedAll.tsexists as a stub; no seed data is applied by default.
Every route is prefixed with /api (see api/src/index.ts). The key resources are:
| Resource | Base Path | Notes |
|---|---|---|
| Users | /users |
Includes authentication via /users/login (returns the user without tokens). |
| Companies | /companies |
Full CRUD with UUID identifiers. |
| Leads | /companies/{companyId}/leads |
Scoped to a company; uses integer lead IDs. |
| Clients | /companies/{companyId}/clients |
Scoped to a company; can be linked to a lead origin. |
Detailed request/response shapes and status codes are documented in Swagger UI and enforced via Zod validators under api/src/validators.
- Zod schemas guard bodies and params; failures raise
ValidationErrorwith400responses. - Domain errors (
ConflictError,NotFoundError,AuthenticationError) extendApplicationErrorto keep status codes consistent. - Unknown exceptions are logged and returned as
500errors.
api/
src/
controllers/ # Express route handlers coordinating validation and services
services/ # Business logic layers integrating with Prisma
routes/ # Resource routing mounted under /api
validators/ # Zod schemas for bodies and params
errors/ # Custom error hierarchy for predictable HTTP responses
docs/ # Swagger specification builder
db/ # Prisma client bootstrap
security/ # Password hashing helpers
scripts/ # Seed stub for deployment environments
prisma/
schema.prisma # Database schema and generator configuration
frontend/
src/
app/ # Next.js routes (App Router)
components/ # Shared UI components, dialogs, layout, charts
contexts/ # React context providers (auth, CRM data, notifications, search)
hooks/ # Custom hooks (route protection, etc.)
services/ # Axios instances and resource-specific calls
types/ # Shared data contracts between frontend modules
api/npm run dev: start the API withtsx watch.api/npm run build: compile TypeScript sources todist/.api/npm run start: run the compiled API with Node.js.api/npm run prisma:generate: generate the Prisma client.api/npm run prisma:migrate: apply migrations withprisma migrate deploy.api/npm run prisma:studio: open Prisma Studio.api/npm run seed: run the seed stub (no-op by default).api/npm run render:build: install, generate Prisma client, and build (Render deployment helper).frontend/npm run dev: start the Next.js dev server.frontend/npm run build: create a production build.frontend/npm run start: serve the production build.frontend/npm run lint: lint TypeScript/React files.
- Fork the repository and create a feature branch.
- Keep commits focused and document any behavioral changes.
- Open a pull request describing the motivation and how you validated the change.