OpsNexus ERP uses a split frontend/backend architecture:
- Frontend: Next.js App Router (
frontend) - Backend: Hono API server (
backend) - Database: PostgreSQL via Drizzle ORM (
drizzle/schema.ts) - Authentication: Better Auth session cookies
- Realtime events: Supabase broadcast channels
- File uploads: UploadThing + claim file records in Postgres
- Role-based pages:
/admin/*/supervisor/operator/portal
- API client: Axios instance with
withCredentials: true - Auth client: Better Auth React client
- Realtime UI notifications subscribed via Supabase client
- Entry point:
backend/src/server/index.ts - Global middleware:
- CORS
- session extraction (
auth.api.getSession)
- Domain routers:
productsleadsclientsclaimsusersanalyticsoperatorsupervisorportal
Schema source of truth: drizzle/schema.ts.
Core entities:
users: user identities and rolesaccounts,sessions,verifications: Better Auth tablesproducts: catalogleads: pre-sale recordslead_products: products attached to leadsclients: post-conversion client recordsclient_products: sold/assigned products for clientsclaims: post-sale issuesclaim_files: claim attachmentscomments: discussion threads for leads/claims/clients/assignments
Roles:
admin: full operational and user controlsupervisor: team-level visibility and assignmentsoperator: assigned leads/claims and related clientsclient: own portal and own claims
Authorization is enforced server-side using middleware and route-level checks.
- Admin/supervisor/operator creates a lead.
- Products are attached to the lead.
- Lead is converted to client (
/api/leads/:id/convert-to-client). - Client receives portal access and product associations.
- Client submits claim (
/api/claims). - Admin/supervisor assigns claim (
/api/claims/:id/assign). - Team comments, uploads files, and updates status.
DATABASE_URLandAUTH_SECRETare required at runtime.- Session-based auth avoids exposing bearer tokens in frontend code.
- Sensitive credentials should never be committed.
- Operators and clients are further restricted by ownership/assignment checks.