# Port Nimara CRM - Project Progress **Last updated:** 2026-04-22 **Repo:** https://code.letsbe.solutions/letsbe/pn-new-crm **Domain:** pn.letsbe.solutions **Stack:** Next.js 15 + TypeScript + Tailwind + Drizzle ORM + PostgreSQL + Redis + BullMQ + MinIO + Socket.io --- ## Since 2026-03-26 - **Admin surface expanded** — full admin users + roles management, admin ports + system settings management, user settings, expanded audit log, and berth CRUD completions. - **Reminders system** — promoted from "pages only" to full CRUD with background processors. - **Multi-address clients** — new `client_addresses` table with a partial unique index enforcing one primary address per client. - **Inquiry notifications feature (end-to-end)** — public interest form now fires: (a) confirmation email to the inquiring client, (b) in-app notifications to CRM users with `interests.view`, (c) optional email to configured sales recipients. Public schema expanded with first/last name split, address block, and berth mooring lookup. `sendEmail` gained a plain-text fallback. Admin settings UI exposes `inquiry_contact_email` and `inquiry_notification_recipients`. Plan: `docs/superpowers/plans/2026-04-14-inquiry-notifications.md`. - **Build/infra cleanup** — Next.js 15 static-prerender bugs fixed (Suspense boundaries around `useSearchParams` on `/portal/verify` and `/set-password`), `.gitattributes` added to enforce LF in the index across Windows/macOS checkouts, Docker production build fixes, CI trimmed to build+push (deploy job removed). --- ## What's Been Built (Layers 0-4 Complete) ### Layer 0: Foundation (DONE) - [x] Next.js 15 project scaffold with TypeScript strict mode - [x] Tailwind CSS + shadcn/ui component library (full set in `src/components/ui/`) - [x] PostgreSQL via Drizzle ORM - full schema across 12 schema files - `berths.ts`, `clients.ts`, `documents.ts`, `email.ts`, `financial.ts`, `interests.ts`, `operations.ts`, `ports.ts`, `relations.ts`, `system.ts`, `users.ts` + `index.ts` - [x] Better Auth integration with multi-port middleware (`src/middleware.ts`) - [x] Redis connection (`src/lib/redis.ts`) - [x] BullMQ queue system with 8 workers: `document-signing.ts`, `email-sync.ts`, `email.ts`, `import.ts`, `maintenance.ts`, `notifications.ts`, `reports.ts`, `webhooks.ts` - [x] MinIO file storage service (`src/lib/services/storage.ts`, `files.ts`) - [x] Socket.io real-time server (`src/lib/socket/server.ts`, `events.ts`) - [x] Docker setup: `Dockerfile` (multi-stage app), `Dockerfile.worker`, `Dockerfile.dev`, `docker-compose.yml`, `docker-compose.dev.yml`, `docker-compose.prod.yml` - [x] Dashboard layout shell with sidebar, port switcher, navigation (`src/app/(dashboard)/layout.tsx`) - [x] Auth pages: login, reset-password, set-password - [x] Seed script (`src/lib/db/seed.ts`) - [x] ESLint + Prettier + Husky + lint-staged - [x] Health check endpoint (`/api/health`) - [x] Rate limiting (`src/lib/rate-limit.ts`) - [x] Encryption utilities (`src/lib/utils/encryption.ts`) - [x] Zod validators for all entities (17 validator files in `src/lib/validators/`) ### Layer 1: Core CRUD (DONE) - [x] **Client Management** - Full CRUD, contacts, relationships, notes, tags, duplicate detection - Pages: list (`/clients`), detail (`/clients/[clientId]`) - API: full REST at `/api/v1/clients/...` (CRUD, contacts, notes, relationships, tags, restore, export-pdf, options) - Service: `clients.service.ts` - Components: `src/components/clients/` - [x] **Berth Management** - Full CRUD, specs, tags, status management, waiting list, maintenance - Pages: list (`/berths`), detail (`/berths/[berthId]`) - API: full REST at `/api/v1/berths/...` (CRUD, status, tags, waiting-list, maintenance, export-pdf, options) - Service: `berths.service.ts`, `berth-rules-engine.ts` - Components: `src/components/berths/` - [x] **Auth Admin** - User management, role builder, port management - Pages: admin/users, admin/roles, admin/ports, admin/onboarding - API: `/api/v1/admin/users/`, `/api/v1/admin/roles/` ### Layer 2: Business Workflows (DONE) - [x] **Interest/Pipeline Management** - CRUD, pipeline stages, berth linking, recommendations, scoring, timeline - Pages: list (`/interests`), detail (`/interests/[interestId]`) - API: full REST at `/api/v1/interests/...` (CRUD, stage, berth, notes, tags, recommendations, timeline, restore, export-pdf) - Services: `interests.service.ts`, `interest-scoring.service.ts`, `recommendations.ts` - Components: `src/components/interests/` - [x] **Documents & EOI** - Documenso integration, 3-party signing, webhook receiver, document templates - Pages: `/documents` - API: `/api/v1/documents/...`, `/api/v1/document-templates/...`, `/api/webhooks/documenso/` - Services: `documents.service.ts`, `document-templates.service.ts`, `document-templates.ts`, `documenso-client.ts`, `documenso-webhook.ts`, `document-reminders.ts` - Components: `src/components/documents/` - [x] **Expenses & Invoices** - CRUD, receipt scanner (AI), invoice generation, payment tracking, CSV/PDF export - Pages: `/expenses`, `/expenses/[id]`, `/expenses/scan`, `/invoices`, `/invoices/[id]`, `/invoices/new` - API: `/api/v1/expenses/...` (CRUD, scan-receipt, export CSV/PDF/parent-company), `/api/v1/invoices/...` (CRUD, generate-pdf, payment, send) - Services: `expenses.ts`, `invoices.ts`, `expense-export.ts`, `receipt-scanner.ts` - Components: `src/components/expenses/`, `src/components/invoices/` - [x] **File Management** - MinIO integration, folder management, upload/download/preview - API: `/api/v1/files/...` (CRUD, upload, download, preview, folders) - Components: `src/components/files/` - Store: `src/stores/file-browser-store.ts` ### Layer 3: Operations (DONE) - [x] **Email System** - SMTP/IMAP, accounts, thread viewer, composer, AI drafts - Pages: `/email` - API: `/api/v1/email/...` (accounts, sync, threads, compose), `/api/v1/ai/email-draft/...` - Services: `email-accounts.service.ts`, `email-compose.service.ts`, `email-draft.service.ts`, `email-threads.service.ts` - Components: `src/components/email/` - [x] **Notifications** - Notification center, preferences, real-time via Socket.io - Pages: (integrated in layout) - API: `/api/v1/notifications/...` (CRUD, preferences, read-all, unread-count) - Service: `notifications.service.ts` - Components: `src/components/notifications/` - [x] **Reminders** - Full CRUD with background processors (dispatcher, reminder workers) - Pages: `/reminders` - API: `/api/v1/reminders/...` (CRUD, my, overdue, upcoming, complete, dismiss, snooze) - Service: `reminders.service.ts` - [x] **Search** - Global search (inline in topbar), saved views - API: `/api/v1/search/...`, `/api/v1/saved-views/...` - Service: `search.service.ts`, `saved-views.service.ts` - Components: `src/components/search/` - [x] **Dashboard & Analytics** - KPIs, pipeline summary, revenue forecast, activity feed - Pages: `/[portSlug]` (dashboard) - API: `/api/v1/dashboard/...` (kpis, pipeline, forecast, activity) - Service: `dashboard.service.ts` - Components: `src/components/dashboard/` ### Layer 4: Advanced Features (DONE) - [x] **Webhooks** - CRUD, delivery tracking, event mapping, test delivery, secret regeneration - Pages: admin/webhooks - API: `/api/v1/admin/webhooks/...` - Services: `webhooks.service.ts`, `webhook-dispatch.ts`, `webhook-event-map.ts` - [x] **Document Templates** - Template management with versioning, preview, rollback - Pages: admin/templates - API: `/api/v1/admin/templates/...` - Service: `document-templates.service.ts` - [x] **AI Features** - Interest scoring, AI email drafts, receipt scanning - API: `/api/v1/ai/...` - Uses OpenAI SDK - [x] **Custom Fields** - Dynamic custom fields for entities - Pages: admin/custom-fields - API: `/api/v1/admin/custom-fields/...`, `/api/v1/custom-fields/...` - Service: `custom-fields.service.ts` - [x] **Reports** - Report generation with download, scheduled reports - Pages: `/reports`, admin/reports - API: `/api/v1/reports/...` - Services: `reports.service.ts`, `report-generators.ts` - [x] **Admin Tools** - Audit log, backup, import, settings, monitoring, forms, tags - Pages: full admin section - API: `/api/v1/admin/...` (connections, errors, health, queues) - Service: `system-monitoring.service.ts` - [x] **Client Portal** (separate Nuxt app in `client-portal/`) - Pages: portal login, verify, dashboard, documents, interests, invoices - API: `/api/portal/...` (auth, dashboard, documents, interests, invoices) - Service: `portal.service.ts` - [x] **Currency** - Multi-currency with conversion rates - API: `/api/v1/currency/...` - Service: `currency.ts` - [x] **Tags** - Cross-entity tagging system - API: `/api/v1/tags/...` - Service: `tags.service.ts` - [x] **Record Export** - PDF export for clients, berths, interests - Service: `record-export.ts` - [x] **Settings & Feature Flags** - Pages: `/settings` - API: `/api/v1/settings/feature-flag/` ### Testing (Layer 5 - Partially Done) - [x] 25 E2E smoke tests (Playwright) covering all major flows - [x] 5 integration tests (Vitest): CRUD audit, custom fields, pipeline transitions, port scoping, webhook delivery - [x] 15 unit tests (Vitest): validators, encryption, security, audit, interest scoring, query plans, webhook events, etc. - [x] Test helpers and factories (`tests/helpers/factories.ts`) - [x] Playwright config with global setup ### Infrastructure (DONE) - [x] Gitea Actions CI/CD workflow (`.gitea/workflows/build.yml`) - Lint + type-check on PR - Docker build + push to Gitea Container Registry on main - SSH deploy to production server - [x] Production docker-compose (`docker-compose.prod.yml`) using registry images - [x] Nginx config for Docker (`nginx/nginx.conf`) - [x] Nginx config for host/certbot (`nginx/pn.letsbe.solutions.conf`) - [x] Environment variable template (`.env.example`) --- ## Project Stats | Metric | Count | | -------------------- | ----- | | TypeScript/TSX files | 461 | | React components | 133 | | API route handlers | 120+ | | DB schema files | 12 | | Service files | 38 | | Validator files | 17 | | BullMQ workers | 8 | | E2E tests | 25 | | Integration tests | 5 | | Unit tests | 15 | | Pages (dashboard) | 37 | | Pages (portal) | 6 | | Pages (auth) | 3 | --- ## What's Left To Do ### Priority 1: Deployment & Go-Live - [x] Push to Gitea (origin/main at `9d815c4` as of 2026-04-22) - [ ] Verify CI/CD pipeline builds the latest image and pushes to the Gitea container registry - [ ] Set up server: install Docker, nginx, configure DNS for `pn.letsbe.solutions` - [ ] Run `certbot --nginx -d pn.letsbe.solutions` for SSL - [ ] Configure production `.env` on server - [ ] Run database migrations (`drizzle-kit migrate` against prod DB — `0000` + `0001` need to apply) - [ ] Run seed data (`pnpm db:seed`) - [ ] Verify all services start and health check passes ### Priority 2: Testing & Hardening (Layer 5 - Remaining) - [ ] Run full E2E test suite against deployed instance and fix failures - [ ] Run full unit/integration test suite and fix failures - [ ] Security hardening pass (review SECURITY-GUIDELINES.md checklist) - [ ] Performance audit (Core Web Vitals, API response times) - [ ] Load testing with realistic data volumes ### Priority 3: Migration (Layer 6) - [ ] NocoDB data export scripts - [ ] Data transformation/mapping (see `NOCODB-MIGRATION-MAPPING.md`) - [ ] PostgreSQL data import - [ ] MinIO file reorganization - [ ] Smoke test migrated data - [ ] DNS/proxy switchover from old system - [ ] Old system decommission ### Priority 4: Polish & Nice-to-Haves - [ ] Dark mode toggle (infrastructure exists via `next-themes`) - [ ] Mobile responsive polish pass - [ ] Google Calendar integration for reminders - [ ] Bulk operations UI refinement - [ ] Email template system (MJML-based) - [ ] Client portal deployment as separate service or subdomain --- ## Key Architecture Decisions | Decision | Choice | Rationale | | ------------------ | ------------------------- | ------------------------------------------------ | | Framework | Next.js 15 (App Router) | Server Components, streaming, typed routes | | ORM | Drizzle | Type-safe, lightweight, PostgreSQL-native | | Auth | Better Auth | Multi-tenant, role-based, session management | | State | Zustand + React Query | Zustand for UI state, RQ for server state | | Queue | BullMQ + Redis | Background jobs, email sync, reports | | Storage | MinIO | S3-compatible, self-hosted, encrypted | | Real-time | Socket.io + Redis adapter | Notifications, live updates | | UI | shadcn/ui + Tailwind | Accessible, customizable components | | Signing | Documenso | Self-hosted document signing | | AI | OpenAI | Receipt scanning, interest scoring, email drafts | | Container Registry | Gitea built-in | Same host as git, simpler auth | --- ## File Structure Overview ``` src/ app/ (auth)/ # Login, reset-password, set-password (dashboard)/ # Main CRM - all [portSlug] scoped pages (portal)/ # Client-facing portal api/ # All API routes (v1/, portal/, webhooks/, auth/, health/) components/ admin/ # Admin panel components berths/ # Berth management UI clients/ # Client management UI dashboard/ # Dashboard widgets documents/ # Document management UI email/ # Email client UI expenses/ # Expense tracking UI files/ # File browser UI interests/ # Interest/pipeline UI invoices/ # Invoice management UI layout/ # Sidebar, topbar, navigation notifications/ # Notification center portal/ # Client portal components reports/ # Report views search/ # Global search shared/ # Shared components ui/ # shadcn/ui base components hooks/ # React hooks jobs/ # BullMQ job definitions lib/ auth/ # Better Auth config db/ # Drizzle schema, migrations, seed queue/ # Queue definitions, workers services/ # Business logic (38 service files) validators/ # Zod schemas (17 validator files) socket/ # Socket.io config providers/ # React context providers stores/ # Zustand stores types/ # TypeScript type definitions ``` --- ## How to Continue Development ```bash # Clone and install git clone https://code.letsbe.solutions/letsbe/pn-new-crm.git cd pn-new-crm pnpm install # Start dev environment (needs Docker for PostgreSQL + Redis) docker compose -f docker-compose.dev.yml up -d cp .env.example .env # then edit with real values pnpm dev # Run tests pnpm exec vitest run pnpm exec playwright test # Build for production pnpm build # Database operations pnpm db:push # Push schema to database pnpm db:generate # Generate migration files pnpm db:seed # Seed with sample data pnpm db:studio # Open Drizzle Studio GUI ``` --- ## Spec Documents Reference | Doc | Purpose | | ------------------------------------ | ---------------------------------- | | `01-CONSOLIDATED-SYSTEM-SPEC.md` | Full system specification | | `02-FEATURE-INVENTORY.md` | Feature keep/cut/rethink decisions | | `03-ARCHITECTURE-DECISIONS.md` | Architecture exploration | | `04-ARCHITECTURE-COMPARISON.md` | Stack comparison | | `05-FINAL-ARCHITECTURE-DECISIONS.md` | Final architecture choices | | `06-MASTER-FEATURE-SPEC.md` | Detailed feature specifications | | `07-DATABASE-SCHEMA.md` | Database schema design | | `08-API-ENDPOINT-CATALOG.md` | Full API endpoint list | | `09-BUSINESS-RULES.md` | Business logic rules | | `10-AUTH-AND-PERMISSIONS.md` | Auth & permission model | | `11-REALTIME-AND-BACKGROUND-JOBS.md` | Socket.io & BullMQ design | | `12-IMPLEMENTATION-SEQUENCE.md` | Build order & dependencies | | `13-UI-PAGE-MAP.md` | Page layout specifications | | `14-TECHNICAL-DECISIONS.md` | Technical trade-off decisions | | `15-DESIGN-TOKENS.md` | Design system tokens | | `NOCODB-MIGRATION-MAPPING.md` | NocoDB to PostgreSQL mapping | | `SECURITY-GUIDELINES.md` | Security requirements |