Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM, PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source files covering clients, berths, interests/pipeline, documents/EOI, expenses/invoices, email, notifications, dashboard, admin, and client portal. CI/CD via Gitea Actions with Docker builds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
54 KiB
Port Nimara CRM — UI Page Map & Navigation Structure
Compiled: 2026-03-11
Framework: Next.js 15 App Router
Component Library: shadcn/ui + Tailwind CSS
Routing: File-based via src/app/ directory
Navigation Architecture
Global Shell (persistent on all authenticated pages)
┌─────────────────────────────────────────────────────────────┐
│ [Logo/Port Name] [Port Switcher ▾] [⌘K Search] [🔔 3] [👤 Matt ▾] │
├──────────┬──────────────────────────────────────────────────┤
│ Sidebar │ │
│ │ Page Content │
│ Dashboard│ │
│ Clients │ │
│ Interests│ │
│ Berths │ │
│ Expenses │ │
│ Invoices │ │
│ Files │ │
│ Email │ │
│ Reminders│ │
│ ──────── │ │
│ Admin ▾ │ │
│ │ │
│ [Collapse│ │
│ Toggle] │ │
└──────────┴──────────────────────────────────────────────────┘
Top bar components:
- Port name + logo (from port settings branding)
- Port switcher dropdown (hidden entirely in single-port mode; visible only when 2+ active ports exist and user has access to multiple ports)
- Global search trigger (Cmd+K / Ctrl+K → modal)
- Notification bell with unread count badge → dropdown panel
- User avatar + name → dropdown: Profile, Dark Mode toggle, Scratchpad, Logout
Sidebar:
- Collapsible (persisted in user prefs via Zustand)
- Collapsed state shows icons only with tooltips
- Active page highlighted
- Admin section expandable submenu (only visible to users with any admin permission)
- Mobile: hamburger icon → slide-out drawer
Route Map
Auth Pages (unauthenticated — no shell)
| Route | Page | Description |
|---|---|---|
/login |
Login | Email + password form, "Forgot password?" link, CRM-styled (maritime branding, port logo) |
/auth/set-password |
Set Password | Token-validated form: new password + confirm. Used for first-time login after admin creates account. |
/auth/reset-password |
Reset Password | Token-validated form: new password + confirm. Used from "forgot password" email link. |
Layout: Centered card on full-screen branded background. No sidebar, no top bar.
User Settings (accessible from user avatar menu)
| Route | Page | Description |
|---|---|---|
/settings/profile |
My Profile | Edit own name, avatar, timezone, preferred language |
/settings/notifications |
Notification Preferences | Per-notification-type delivery channel toggles |
/settings/notifications — Notification Preferences
- Table: Notification type (rows) × delivery channel (columns: In-App, Email)
- Notification types: Reminder due, reminder overdue, new website registration, EOI signature event, new email received, duplicate client alert, invoice overdue, waiting list notification, system alert, follow-up auto-created, tenure expiring
- Per-type toggles: In-app (always on, read-only), Email (toggle on/off)
- Save button applies changes
Dashboard
| Route | Page | Description |
|---|---|---|
/ |
Dashboard | Home screen — port-scoped overview |
Page contents:
- Pipeline funnel widget — interest count and weighted value per pipeline stage (bar or funnel chart). Click a stage → navigates to
/interests?stage={stage} - Berth occupancy widget — available / under offer / sold breakdown (donut chart). Click a status → navigates to
/berths?status={status} - Revenue forecast widget — weighted pipeline value with best/likely/worst scenarios, trend line over time
- Expense summary widget — month-over-month spend by category (bar chart)
- Recent activity feed — last 10 actions across all entities (from audit log). Each entry links to the relevant record.
- Upcoming reminders & events — unified list of next 5 CRM reminders + upcoming Google Calendar events (next 7 days). CRM reminders show linked entity; Calendar events show a Google Calendar badge. Link to
/remindersfor full view. - Overdue items panel — unsigned EOIs, overdue invoices, overdue reminders, expiring tenures. Each item links to its record.
- Timeline strip — upcoming key dates: reminder due dates, tenure expirations, invoice due dates, Google Calendar events (horizontal scrollable timeline at top or bottom)
Permission: reports.view_dashboard (all roles by default)
Client Management
| Route | Page | Description |
|---|---|---|
/clients |
Client List | Paginated table of all clients |
/clients/new |
Create Client | New client form |
/clients/[id] |
Client Detail | Full client record with tabbed sections |
/clients/[id]/edit |
Edit Client | Edit client fields (could also be inline on detail) |
/clients — Client List
- Table columns: Name, company, nationality, source, tags, # interests, last activity, created date
- Filters: Search (name/email/phone), nationality, source, tags, archived (toggle), date range
- Sort: Name, created date, last activity
- Saved views: Dropdown of saved filter configurations, "Save current view" button, "Manage Views" link → modal: rename, delete, share/unshare saved views
- Bulk actions toolbar (appears when rows selected): Bulk tag, bulk export (CSV/PDF), bulk archive
- Actions per row: View, Edit, Archive
- "+ New Client" button →
/clients/new
/clients/new — Create Client
- Sections:
- Basic info: Full name, company/entity (optional), nationality
- Contact info: Add multiple contacts (channel + value + label), at least one required
- Vessel details: Yacht name, length, width, draft (dual unit input), berth size desired
- Proxy/representative: Toggle, proxy type, actual owner name, relationship notes
- Communication preferences: Preferred method, language, timezone
- Source: Website / manual / referral / broker (+ referrer link)
- Tags: Tag selector (multi-select from existing tags or create new)
- On submit: Duplicate detection runs (same email → auto-merge, fuzzy match → alert modal)
- Cancel → back to
/clients
/clients/[id] — Client Detail
- Header area: Client name, company, tags, status badges, quick actions (Edit, Archive, Export PDF, Merge)
- Tabs:
| Tab | Contents |
|---|---|
| Overview | Core fields (name, company, nationality, vessel, proxy info, communication prefs, source), contact cards |
| Relationships | Visual/list view of related clients. Relationship types: referred by, broker for, family member, same vessel, custom. Add/remove relationships. Shows referral networks and broker portfolios. |
| Interests | List of all interests for this client. Single interest → inline expanded. Multiple → accordion or sub-table. Each links to /interests/[id]. "+ New Interest" button. |
| Activity | Chronological timeline feed (from audit log). Filterable by event type. |
| Notes | Timestamped notes thread. New note input with @mention support. Edit (within 15 min) / locked indicator. |
| Files | Client-scoped file browser (MinIO). Upload button, folder tree, file cards with preview/download. |
| Emails | Email threads linked to this client (from IMAP sync). Compose new button. |
| Documents | EOIs, contracts, NDAs linked through interests. Status indicators (pending, signed, completed). |
| Invoices | Invoices billed to this client. Status badges. Link to invoice detail. |
| Audit Trail | Raw audit log entries for this client and all related entities. Filterable by action type, date range. |
Interest Management
| Route | Page | Description |
|---|---|---|
/interests |
Interest List | Table + pipeline (Kanban) views |
/interests/new |
Create Interest | New interest form (often initiated from a client) |
/interests/[id] |
Interest Detail | Full interest record |
/interests — Interest List
- View toggle: Table view ↔ Pipeline (Kanban) view
- Table view:
- Columns: Client name, berth (if linked), pipeline stage, lead category, EOI status, last activity, date created
- Filters: Stage, berth, client, lead category, source, tags, date range, assigned salesperson
- Sort: Date created, last activity, stage, client name
- Pipeline (Kanban) view:
- 8 columns (one per pipeline stage): Open → Details Sent → In Communication → Visited → Signed EOI and NDA → 10% Deposit → Contract → Completed
- Cards show: client name, berth, days in stage, next action indicator
- Drag-and-drop between stages (confirmation dialog for significant changes)
- Filters same as table view (applied to both views)
- Saved views, bulk actions same pattern as clients
/interests/new — Create Interest
- Fields:
- Client selector (search/select existing or "+ New Client" inline)
- Berth link (optional — search/select berth)
- Initial pipeline stage (default: Open)
- Lead category
- Source
- Notes (initial note)
- Tags
/interests/[id] — Interest Detail
- Header: Client name → link to client, berth → link to berth (if linked), pipeline stage badge (with manual override dropdown), lead category, EOI status badge
- Quick actions: Generate EOI, Link Berth, Change Stage, Export PDF, Archive
- Sections / Tabs:
| Tab | Contents |
|---|---|
| Overview | Pipeline stage (with stage history), berth details (inline if linked), vessel info (from client), milestone dates (first contact, EOI sent, signed, deposit, contract, completed), lead category, source |
| EOI & Documents | EOI section: generate button (if prerequisites met), signing status per signer, signing URLs, reminder controls. Documents list: all docs on this interest (EOI, contracts, NDAs) with status. Upload manual doc button. |
| Recommendations | Berth recommendation panel: vessel dimensions summary, "Run Recommendation" button → ranked berth list with match scores. Assign berth from recommendation. |
| Waiting List | If berth is linked and client is on waiting list: position, priority, notification pref. If berth has a waiting list: show queue. |
| Notes | Interest-specific notes thread (separate from client notes). Same @mention / edit window behavior. |
| Activity | Interest-specific timeline (subset of client timeline filtered to this interest). |
| Audit Trail | Audit log for this interest record. |
Berth Management
| Route | Page | Description |
|---|---|---|
/berths |
Berth Explorer | Three-panel layout: map + list + detail |
/berths/new |
Create Berth | New berth form (admin/super admin) |
/berths/[id] |
Berth Detail | Full berth specs (also shown in right panel of explorer) |
/berths/compare |
Berth Comparison | Side-by-side comparison of 2-3 berths |
/berths/calendar |
CUT FROM V1 — Gantt-style tenure timeline deferred to post-V1 |
/berths — Berth Explorer (Three-Panel Layout)
┌──────────────────────────────────────────────────────┐
│ [Interactive Berth Map] [Collapse Map ▲]│
│ SVG map color-coded: green=available, orange=under │
│ offer, red=sold. Click berth → selects in list. │
├─────────────────┬────────────────────────────────────┤
│ Smart List │ Detail Panel │
│ ───────────── │ ─────────────── │
│ Grouped by │ Full berth specs │
│ status: │ (collapsible sections): │
│ Under Offer │ - Dimensions │
│ Available │ - Infrastructure │
│ Sold │ - Commercial │
│ │ - Linked interests │
│ Filter: area, │ - Waiting list │
│ size, price │ - Maintenance log │
│ │ - Files / Gallery │
│ [+ New Berth] │ - Tenure info │
│ │ [Edit] [Compare] [Export PDF] │
└─────────────────┴────────────────────────────────────┘
- Map panel: Toggleable (collapse to maximize list/detail). SVG with berth outlines colored by status. Hover shows tooltip (mooring #, area, status, size). Click selects berth.
- List panel: Grouped by status (Under Offer first, then Available, then Sold). Each item: mooring number, area, nominal size, price. Search/filter by area, size range, price range, status.
- Detail panel: Full spec sheet. Collapsible sections for each data group. Action buttons: Edit, Compare (adds to comparison), Export PDF, View on map.
- Waiting List section: Ordered queue of clients with position, priority (normal/high), date added, notification preference. Actions: reorder, change priority, update notification pref, remove entry. "Add to waiting list" button (client selector).
- Maintenance Log section: Chronological log of maintenance/repair/inspection entries. Each entry: date, description, cost, category (routine/repair/inspection/upgrade), photos (thumbnail gallery), responsible party. "+ Add Entry" form with photo upload. Edit/delete existing entries.
/berths/compare — Berth Comparison
- Select 2-3 berths (from berth list or via URL params)
- Side-by-side table: rows are spec fields, columns are berths
- Highlights differences
- Export as PDF button (branded with port logo/colors)
/berths/calendar — Availability Calendar — CUT FROM V1
Deferred to post-V1. Tenure data and expiry checks remain active (see BR-003 tenure expiry,
tenure-expiry-checkbackground job). Only the Gantt-style visualization UI is deferred.
- Gantt-style horizontal timeline
- Rows = berths, bars = tenure periods
- Color: active tenure (blue), expiring soon (amber), expired (red), available (green)
- Configurable time range (3 months, 6 months, 1 year, 5 years)
- Click a tenure bar → links to interest or client detail
- Flags upcoming expirations (configurable warning threshold, set in port settings)
- Legend: color key for tenure status types
- Warning threshold control: dropdown to set how far in advance expirations are flagged (1/3/6/12 months)
Expenses
| Route | Page | Description |
|---|---|---|
/expenses |
Expense List | Paginated table of all expenses |
/expenses/new |
Create Expense | New expense form with receipt upload |
/expenses/[id] |
Expense Detail | Full expense record with receipt images |
/scan |
Receipt Scanner (PWA) | Standalone PWA — camera → AI extraction → save expense. Also accessible via /expenses/scan redirect. |
/expenses — Expense List
- Table columns: Date, establishment, amount (original currency + USD), category, payer, payment status, receipt indicator
- Filters: Date range, payer, category, payment status, currency, amount range
- Sort: Date, amount, establishment
- Export controls: CSV export, PDF export (with receipts), parent company export (EUR + 5% fee)
- Bulk actions: Bulk export, bulk payment status update, create invoice from selected
/expenses/new — Create Expense
- Fields: Establishment name, amount, currency (dropdown), date/time, category, payer, description, payment method, payment status
- Receipt upload: Drag-and-drop or camera capture, multiple images allowed
- "Scan Receipt" button → redirects to
/scan(standalone PWA receipt scanner)
/scan — Receipt Scanner (Standalone PWA)
- Standalone PWA:
manifest.jsonwithdisplay: "standalone", custom icon ("Port Nimara Scanner"). Addable to Apple home screen / Android — opens without browser chrome. - Service worker: Caches UI shell for instant load. Offline: photos queued in IndexedDB, uploaded on reconnect.
- Easy URL:
crm.portnimara.dev/scan— short and bookmarkable./expenses/scanredirects here. - Minimal UI: No sidebar or navigation chrome. Camera viewfinder (or file upload for desktop) → Capture → AI processing spinner → Review extracted data (establishment, amount, currency, date, items) → Edit/correct → Save as expense → "Scan Another" or "Back to CRM"
- Multi-currency indicator: Shows detected currency + USD conversion at current rate
- Auth: Session-based. If not logged in, shows minimal login form then returns to scanner.
Invoices
| Route | Page | Description |
|---|---|---|
/invoices |
Invoice List | Paginated table of all invoices |
/invoices/new |
Create Invoice | Invoice builder (select expenses, configure billing) |
/invoices/[id] |
Invoice Detail | Full invoice with line items, payment tracking |
/invoices — Invoice List
- Table columns: Invoice # (INV-YYYYMM-###), client/company, total, currency, status (draft/sent/paid/overdue/cancelled), due date, created date
- Filters: Status, client, date range, amount range, currency
- Status badges color-coded: Draft (gray), Sent (blue), Paid (green), Overdue (red), Cancelled (strikethrough)
/invoices/new — Create Invoice
- Step 1: Select billing target (client or company, billing email, billing address)
- Step 2: Add line items — inline editable table: description, quantity, unit price, amount (auto-calculated). "Add Row" button for manual items. "Import from Expenses" button → modal showing un-invoiced expenses with checkboxes, select → auto-creates line items.
- Step 3: Configure: payment terms (Immediate/Net 10/15/30/45/60), currency, discount (% or fixed), additional fees, notes
- Preview: Live invoice preview as you configure
- Save as draft or Save & Send
/invoices/[id] — Invoice Detail
- Header: Invoice #, status badge, client/company, total, due date
- Line items table: Description, quantity, unit price, amount
- Totals section: Subtotal, discount, fees, total
- Payment tracking: Status, payment date, method, reference, notes. "Record Payment" button.
- Actions: Send (email PDF), Download PDF, Edit (if draft), Mark as Paid, Cancel
- Linked expenses: List of expenses included in this invoice
File Management
| Route | Page | Description |
|---|---|---|
/files |
File Browser | MinIO-backed file explorer organized by client |
/files — File Browser
- Left panel: Folder tree (clients as top-level folders, sub-folders: eoi, contracts, images, receipts, correspondence, misc)
- Right panel: File grid/list for selected folder
- File cards: Thumbnail (images/PDFs), filename, size, uploaded date, uploaded by
- Actions per file: Preview (inline modal for images/PDFs), Download, Rename, Delete (confirmation), Move
- Upload: Drag-and-drop zone + click upload. Context-aware (if in a client's eoi folder, auto-categorizes)
- Folder management: Create folder, rename folder, delete folder (with contents warning)
- Search: Search files by name within current context
Email System
| Route | Page | Description |
|---|---|---|
/email |
Email Inbox | Connected email threads (if mailbox configured) |
/email/settings |
Email Settings | IMAP/SMTP configuration |
/email — Email Inbox
- If no mailbox configured: Prompt to set up in
/email/settings. Show system-sent emails log instead. - If configured:
- Left panel: Thread list (newest first), search, filter by linked client
- Right panel: Thread detail (conversation view, newest at bottom)
- Compose button → TipTap rich text editor modal (recipients, subject, body, merge fields, attachments from MinIO)
- Threads auto-linked to clients by email address matching
- Unlinked threads shown in a separate "Unlinked" section
/email/settings — Email Settings
- Provider presets: Google Workspace, Outlook, Custom
- SMTP configuration: host, port, username, password (encrypted), TLS toggle
- IMAP configuration: host, port, username, password (encrypted), TLS toggle
- Test connection button
- Sync frequency setting
Reminders
| Route | Page | Description |
|---|---|---|
/reminders |
Reminders & Upcoming | Unified list of CRM reminders + Google Calendar events |
/reminders — Reminders & Upcoming
- Unified list view: CRM reminders and Google Calendar events interleaved chronologically
- Toggle: My Reminders ↔ All Reminders (requires
reminders.view_all) - CRM reminders: Title, linked entity (client/interest/berth), priority (color-coded), due date, assigned to, status badge
- Google Calendar events: Title, time, location (if any), calendar badge icon to distinguish from CRM reminders
- Filters: Source (CRM only / Calendar only / Both), status (pending/snoozed/completed/dismissed), priority, assignee, entity type, due date range, overdue toggle
- Sort: Due date (default), priority, created date
- Toggle: My Reminders ↔ All Reminders (requires
- Quick create: "+ New Reminder" → inline form or modal (title, note, due date/time, priority, assignee, linked entity, "Add to Google Calendar" toggle)
- Reminder detail: Click reminder → slide-out panel with full fields, edit capability, snooze/complete/dismiss buttons
- Snooze options: 1 hour, 4 hours, tomorrow morning, next week, custom date/time
- Calendar connection banner: If Google Calendar not connected, show a subtle banner: "Connect Google Calendar to see your events alongside reminders" → link to
/settings/calendar - Google Calendar event detail: Click calendar event → read-only panel showing event details, link to open in Google Calendar
User Settings — Calendar
| Route | Page | Description |
|---|---|---|
/settings/calendar |
Calendar Settings | Google Calendar connection and configuration |
/settings/calendar — Calendar Settings
- Connection status: Connected / Not connected, with Google account email displayed
- Connect button: Initiates Google OAuth flow → redirects to Google consent screen → returns with token
- Calendar selector: Dropdown listing all user's Google Calendars (fetched via
calendarList.list). User picks which calendar to sync with (e.g., "Business", "CRM", "Primary"). - Sync toggle: Enable/disable background sync
- Last synced: Timestamp of most recent sync
- Manual sync: "Sync now" button to trigger immediate pull
- Disconnect: Button to revoke connection and clear cached events
Admin Panel
| Route | Page | Description |
|---|---|---|
/admin |
Admin Overview | Admin landing with section links |
/admin/users |
User Management | User list + create/edit |
/admin/users/new |
Create User | New user form |
/admin/users/[id] |
User Detail | User profile, assigned ports/roles, activity |
/admin/roles |
Role Management | Role list + builder |
/admin/roles/new |
Create Role | Role builder with permission toggles |
/admin/roles/[id] |
Edit Role | Edit existing role permissions |
/admin/ports |
Port Management | Port list + settings |
/admin/ports/new |
Create Port | New port setup (or onboarding wizard) |
/admin/ports/[id] |
Port Settings | Per-port configuration |
/admin/audit |
Audit Log | System-wide audit log viewer |
/admin/settings |
System Settings | Global system configuration |
/admin/webhooks |
Webhook Management | Webhook CRUD + delivery logs |
/admin/webhooks/new |
Create Webhook | New webhook configuration |
/admin/webhooks/[id] |
Webhook Detail | Edit webhook + view delivery history |
/admin/reports |
Scheduled Reports | Report schedule management |
/admin/reports/new |
Create Report Schedule | Configure new scheduled report |
/admin/custom-fields |
Custom Fields | Custom field definitions per entity type |
/admin/templates |
Document Templates | Template CRUD with TipTap rich text editor |
/admin/templates/new |
Create Template | New template with merge field insertion |
/admin/templates/[id] |
Edit Template | Edit existing template |
/admin/forms |
Form Management | Data collection form builder + submissions |
/admin/forms/new |
Create Form | Build a pre-filled data collection form |
/admin/forms/[id] |
Form Detail | Edit form + view submissions |
/admin/import |
Data Import | CSV/Excel import center + import history |
/admin/monitoring |
System Health | Service health dashboard + BullMQ job monitor |
/admin/backup |
Backup & Restore | Database backup management |
/admin/tags |
Tag Management | Manage tags across entity types |
/admin/onboarding |
Port Onboarding Wizard | Step-by-step new port setup |
/admin/users — User Management
- Table: Name, email, status (active/inactive), last login, ports assigned, roles
- Actions: Create, edit, deactivate/reactivate, reset password
- User detail page (
/admin/users/[id]):- Full profile: name, email, status, created date, last login
- Port assignments: table of assigned ports with role per port, add/remove assignments
- Active sessions: list of current sessions (device/browser, IP, last active). "Revoke" button per session, "Revoke All Sessions" button.
- Activity history: last N actions from audit log filterable by date range
/admin/roles — Role Management
- Role list: Name, description, system role flag, # users assigned
- Role builder:
- Permission grid: categories on the left (clients, interests, berths, etc.), permission flags as toggles
- Visual grouping by domain
- "Clone from" dropdown to start from an existing role
- Preview: "What can this role do?" summary
/admin/ports — Port Management
- Port list: Name, slug, status (active/inactive), # users, # berths
- Port settings:
- Basic: Name, slug, timezone, default currency
- Branding: Logo upload, primary/secondary color pickers → stored in port settings
- Operational: Follow-up reminder schedules, alert thresholds, EOI reminder settings
- Role overrides: Per-port permission tweaks for global roles
/admin/audit — Audit Log
- Filterable table: Timestamp, user, action (create/update/delete/archive/restore/merge), entity type, entity ID, field changed, old value → new value
- Filters: User, entity type, action type, date range, entity ID
- Export: CSV
- Revert button (super admin only) on individual entries
/admin/settings — System Settings
- Sections:
- Berth Status Rules: Table of trigger→mode→target status rules. Each row: Trigger description (read-only), Mode dropdown (auto/suggest/off), Target Status dropdown (available/under_offer/sold). "Reset to Defaults" button. Per-port if multi-port.
- Email: Poste.io SMTP config, test send
- Documenso: API URL, API key, test connection
- MinIO: Endpoint, access key, secret key, bucket, test connection
- Currency: Primary currency, exchange rate refresh interval, Frankfurter API status, current rates table (auto-updated + manual override per pair), "Refresh Now" button
- Backup: Schedule (cron), retention days, last backup status
- Security: Session timeout, login rate limits, password requirements
- Expiration alerts: Default warning threshold for tenure expirations (months before)
/admin/webhooks — Webhook Management
- Webhook list: Name, target URL, events subscribed, enabled/disabled toggle, last delivery status
- Create/edit: Target URL, secret key (for HMAC signing), event selector (checkboxes), enable/disable
- "Test Webhook" button: Sends a test payload to the target URL, shows response status/body inline
- Delivery log per webhook: Timestamp, event type, response status, response time, payload preview, retry count
/admin/reports — Scheduled Reports
- Report list: Name, type, frequency, recipients, last sent, next send, enabled toggle
- Create/edit: Report type (dropdown), frequency (daily/weekly/monthly/cron), enable/disable
- Recipient selector: Multi-select from CRM users + free-text entry for external email addresses. Shows recipient list with remove buttons.
/admin/custom-fields — Custom Fields
- Per entity type tabs: Clients, Interests, Berths, Expenses
- Field list: Name, type (text/number/date/boolean/select), required flag, sort order
- Create field: Name, type, options (for select type), required, default value
/admin/templates — Document Templates
- Template list: Name, type (welcome letter, handover checklist, etc.), last modified, active toggle
- Template editor:
- Rich text editor (TipTap — confirmed, with table + merge field extensions)
- Merge field insertion toolbar: dropdown showing available fields organized by entity (client.full_name, berth.mooring_number, etc.), click to insert
{{token}} - Preview with sample data
- Save / activate / deactivate
/admin/forms — Form Management
- Form list: Name, linked entity type, status (active/inactive), submissions count, last submitted, created date
- Create/edit form:
- Form name, description
- Entity type: client data collection, interest data collection, general intake
- Field selector: choose which CRM fields appear on the form, set which are pre-filled vs. editable
- Branding preview: shows form as client will see it (port logo/colors)
- Generate link: creates per-client secure token URL
- Submissions view per form: Table of submissions with date, client, status (pending review / applied / rejected). Click submission → diff view showing what data the client provided vs. current CRM data. "Apply" button to merge submitted data into CRM records.
/admin/tags — Tag Management
- Entity type tabs: Clients, Interests, Berths (each port has its own tag set)
- Tag list per type: Tag name, color swatch, usage count (how many records tagged)
- Create tag: Name input + color picker
- Edit tag: Rename, change color
- Delete tag: Confirmation with cascade warning ("This tag is used on X records. Removing it will untag all of them.")
- Drag to reorder (sort order for display in tag selectors)
/admin/import — Data Import
- Import wizard:
- Step 1: Select entity type (clients, interests, berths, expenses)
- Step 2: Upload CSV/Excel file
- Step 3: Column mapping (source columns → CRM fields, auto-mapped where names match)
- Step 4: Validation preview (valid rows, error rows, duplicate alerts)
- Step 5: Import + progress bar
- Import history: Past imports with record counts, errors, date, user
/admin/monitoring — System Health
- Service health cards: PostgreSQL, Redis, MinIO, Documenso, Poste.io, Socket.io — each with green/yellow/red indicator, last check time, response time
- BullMQ dashboard: Queue cards (one per queue: email, documents, reminders, calendar-sync, backups, etc.) showing pending/active/completed/failed counts. Click queue → drill-down job list with: job ID, status, data preview, created/processed timestamps. Actions per job: retry, remove. Dead letter queue section with bulk retry/clear.
- Alert configuration: Per-category alert rules (service down, job failure, backup failure, disk space, unusual activity). Each rule: threshold (e.g., >5 failures), time window (e.g., in 10 minutes), notification targets (super admin email + in-app). Enable/disable per rule.
- System info: Disk usage, memory, uptime (non-sensitive info only)
/admin/backup — Backup & Restore
- Backup list: Date, size, type (scheduled/manual), status
- Manual backup trigger button
- Download backup button per entry
- Restore: Upload backup → preview (record counts) → confirm → restore (super admin only)
- Retention settings: Keep last N days
Global Overlays & Modals
These UI elements appear on top of any page:
| Component | Trigger | Description |
|---|---|---|
| Global Search Modal | Cmd+K / Ctrl+K or search icon | Full-screen modal: search input, results grouped by entity type (clients, berths, interests, invoices, expenses, documents), recent searches. Enter or click → navigates to record. |
| Notification Panel | Bell icon click | Slide-out right panel or dropdown: notification list ordered by recency. Each: icon, title, description, timestamp, read/unread dot, click → navigates to record. "Mark all as read" button. |
| Scratchpad | User menu → Scratchpad | Slide-out panel: personal notes area. Persisted per user. Notes can be dragged to a client record (opens a "move to client" modal). |
| Confirmation Dialog | Any destructive action | Modal: "Are you sure?" with context (what's being deleted/archived). Confirm / Cancel. |
| Quick Note Modal | "Add Note" button on any entity | Modal: text area with @mention support, entity context pre-filled. Save → adds to entity's notes. |
| Duplicate Alert Modal | On client creation (fuzzy match detected) | Modal: shows potential duplicate(s) side-by-side. Options: "Merge with existing", "Create anyway", "Cancel". |
| Merge Preview Modal | From client detail → Merge action | Modal: two records side-by-side, field-by-field selection of which values to keep, preview of merged result. Confirm → merge. |
| EOI Generation Wizard | "Generate EOI" button on interest | Multi-step modal: Step 1 verify client data → Step 2 verify berth data → Step 3 select signers → Step 4 confirm → generate. |
| Berth Recommendation Panel | "Run Recommendation" on interest | Panel/modal: shows vessel dimensions, ranked berth results with match scores and reasons. "Assign" button per result. |
| Bulk Operation Progress | After triggering bulk action | Toast/modal: progress bar, record count, success/error count. Stays until dismissed or auto-closes on completion. |
Client Portal (Separate Auth Context)
| Route | Page | Description |
|---|---|---|
/portal/login |
Portal Login | Client authentication (separate from CRM auth) |
/portal |
Portal Dashboard | Client's berths, pending documents, invoices |
/portal/documents |
My Documents | Documents awaiting signature, signed documents |
/portal/documents/[id]/sign |
Sign Document | Embedded Documenso signing view |
/portal/invoices |
My Invoices | Invoice history with status |
/portal/files |
My Files | Files shared by salesperson, upload area |
/portal/forms/[token] |
Data Collection Form | Pre-filled form for client to complete |
Layout: Simplified layout — no sidebar, just a top bar with portal logo and client name. Clean, focused UI for non-CRM users.
Public Pages (No Authentication)
| Route | Page | Description |
|---|---|---|
/api/public/berths |
— | JSON API endpoint (no UI) |
/api/public/berths/:id |
— | JSON API endpoint (no UI) |
/api/public/interests |
— | JSON API endpoint (POST, no UI) |
/api/public/forms/:token |
Public Form | Pre-filled data collection form (branded, minimal layout) |
/api-docs |
API Documentation | OpenAPI/Swagger UI for the public API |
Page Count Summary
| Section | Page Count |
|---|---|
| Auth pages | 3 |
| User settings | 2 |
| Dashboard | 1 |
| Client management | 4 |
| Interest management | 3 |
| Berth management | 5 |
| Expenses | 4 |
| Invoices | 3 |
| File management | 1 |
| 2 | |
| Reminders | 1 |
| Calendar Settings | 1 |
| Admin panel | 27 (includes forms, tags detail) |
| Global overlays/modals | 10 components |
| Client portal | 7 |
| Public pages | 2 (with UI) |
| TOTAL | ~66 pages + 10 overlay components |
Responsive Breakpoints
| Breakpoint | Layout Adaptation |
|---|---|
| Desktop (≥1280px) | Full three-panel layouts (berths), sidebar expanded, all columns visible |
| Tablet (768–1279px) | Sidebar collapsed to icons, detail panels become full-page navigation, berth map toggles to separate tab, table columns reduced |
| Mobile (< 768px) | Sidebar → hamburger slide-out drawer, all views single-column, receipt scanner optimized for camera, touch-friendly tap targets (min 44px), swipe gestures for pipeline cards |
Navigation Flow Diagram
Login ──→ Dashboard
│
┌─────────┼──────────┬──────────┬──────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
Clients Interests Berths Expenses Invoices Reminders
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
Detail Detail Explorer Detail Detail Upcoming List
│ │ │ │
│ ┌───┘ │ │
│ ▼ │ │
│ EOI/Signing │ │
│ Recommendations │ │
│ ▼ │
│ Compare/Calendar │
│ │
└──── Files ◄─── linked ───────┘
│
▼
Email
│
┌────────┘
▼
Admin Panel ──→ Users / Roles / Ports / Audit / Settings
Webhooks / Reports / Custom Fields / Templates
Import / Monitoring / Backup / Tags / Onboarding
Cross-linking patterns:
- Client detail → links to interests, files, emails, invoices, documents
- Interest detail → links to client, berth, EOI documents, recommendations
- Berth detail → links to interests, waiting list entries (which link to clients)
- Expense detail → links to invoice (if invoiced), receipt files
- Invoice detail → links to client, linked expenses
- Activity timelines → every entry links to the relevant record
- Notification items → each links to the triggering record
- Dashboard widgets → each links to the relevant list/filter view
State Management Summary
| State Type | Technology | Scope |
|---|---|---|
| Server state (entities, lists) | TanStack Query | Cache + refetch on focus/stale |
| UI state (sidebar, modals, view prefs) | Zustand store | Per-session, persisted subset to localStorage |
| Form state | React Hook Form + Zod | Per-form, validated on submit |
| Real-time updates | Socket.io events → TanStack Query invalidation | Port-scoped rooms |
| URL state (filters, pagination, view mode) | URL search params (nuqs or manual) | Shareable/bookmarkable |
Real-time update flow:
- User A creates a client → API saves → Socket.io emits
client:createdto port room - User B's browser receives event → TanStack Query cache invalidated for client list
- User B's client list auto-refetches → new client appears without page refresh
- If User B is on the dashboard → activity feed also refreshes
Appendix: Route-to-Feature Spec Cross-Reference
| Feature Spec Section | Primary Routes |
|---|---|
| 1. Client Management | /clients, /clients/new, /clients/[id] |
| 2. Interest Management | /interests, /interests/new, /interests/[id] |
| 3. Berth Management | /berths, /berths/compare (/berths/calendar |
| 4.1–4.5 EOI & Signing | /interests/[id] (EOI tab), EOI Generation modal |
| 4.5 Data Collection Forms | /admin/forms, /admin/forms/new, /admin/forms/[id], /api/public/forms/:token |
| 4.6 Document Templates | /admin/templates, /admin/templates/new, /admin/templates/[id] |
| 4.7 Record PDF Export | Export buttons on /clients/[id], /berths/[id], /interests/[id] |
| 5. Expenses & Invoicing | /expenses, /expenses/new, /expenses/scan, /invoices, /invoices/new, /invoices/[id] |
| 6. File Management | /files, file tabs on client detail |
| 7. Email System | /email, /email/settings |
| 8. Dashboard & Analytics | / |
| 9. Reminders & Calendar | /reminders, /settings/calendar |
| 10. Notification Center | Notification bell overlay |
| 11.1 Global Search | Cmd+K overlay |
| 11.2 Saved Filters | Filter controls on all list pages |
| 11.3 Bulk Operations | Bulk action toolbar on all list pages |
| 12. Admin Panel | /admin/* (all sub-routes) |
| 13. Audit System | /admin/audit, audit trail tabs on entity detail pages |
| 14. Multi-Port Tenancy | Port switcher in top bar |
| 15. Auth & Authorization | /login, /auth/*, middleware (invisible) |
| 16. Public API | /api/public/*, /api-docs |
| 17.1 Berth Spec Import | /admin/import (berth-specific flow) |
| 17.2 Receipt Scanner (PWA) | /scan (standalone PWA, also /expenses/scan redirect) |
| 17.3 Recommendation Engine | /interests/[id] (Recommendations tab) |
| 17.4 S3 File Migration | One-time admin script (no permanent UI — progress in /admin/monitoring) |
| 18. Data Import/Export | /admin/import, export buttons on all list pages |
| 19. Webhooks | /admin/webhooks, /admin/webhooks/new, /admin/webhooks/[id] |
| 20. Scheduled Reports | /admin/reports, /admin/reports/new |
| 21. System Monitoring | /admin/monitoring, /admin/backup |
| 22. Client Portal | /portal/* |
| 23.1 Mobile Responsive | Responsive breakpoints (all pages) |
| 23.2 Dark Mode | User menu toggle (all pages) |
| 23.3 Quick Notes | Scratchpad overlay |
| 10.2 Notification Preferences | /settings/notifications |
| 23.4 Tags | /admin/tags, tag components on entity forms/detail |
| 23.5 Archiving | Archive actions on all entity detail/list pages |
| 23.6 Multi-Currency | Currency display on berth detail, expense forms |
| 23.7 Audit Export | Export button in /admin/audit or dedicated modal |