SmartPRO Docs · Internal 🔒 ← Back to SmartPRO

Stack

Layer Technology
Frontend React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui
Backend Node.js, Express, tRPC
Database TiDB (MySQL-compatible), Drizzle ORM
Email Resend (transactional), custom HTML templates
Auth Session-based, workspace-scoped RBAC
Infra Docker Compose (MySQL + Node Alpine)
Calendar Cal.com (webhooks for demo booking)

Module map

client/src/
├── pages/           ← one file per route
├── components/      ← shared UI components
├── features/        ← self-contained feature modules (controlTower, etc.)
└── lib/             ← utilities (i18n, formatting, auth)

server/
├── routers/         ← tRPC procedure routers (one per domain)
├── jobs/            ← scheduled background jobs
├── modules/         ← complex domain modules (recruitment, etc.)
├── _core/           ← Express app init, middleware, job scheduler
├── email.ts         ← all transactional email templates
└── demoWebhooks.ts  ← Cal.com webhook handler

RBAC model

Roles (in ascending permission order):

Company roles (on company_members):

Role Access
company_member Own / department / team data per visibility scope
hr_admin HR data within the company (employees, attendance, documents)
finance_admin Billing, payroll, WPS within the company
reviewer Compliance read-only
external_auditor Read-only; blocked from all mutations
client Client/buyer portal access
company_admin Full company access

Platform roles (global, on platform_user_roles): platform_admin, super_admin — cross-company + platform ops.

Mutations gate on requireWorkspaceMutation / requireHrOrAdmin — never bare requireWorkspaceMembership for writes.

Workspace model

Each company has one workspace. Users belong to a workspace via company_members. The companies.subscription_status column (legacy) and company_subscriptions table must stay in sync — see Migration Apply SOP.

Internationalisation

The platform is bilingual: English (en-OM) and Arabic (ar-OM), with RTL layout for Arabic. Locale files live in client/src/locales/. All numeric formatting uses Western digits (nu-latn) even in Arabic locale, per fmtLocale.ts convention.

Brand

Primary: forest green #006948 — defined in client/src/index.css as CSS custom properties. Email templates mirror the hex values directly (emails can't read CSS vars). The SmartProBrand component is the only approved way to render the logo in React — never hand-roll an SP badge.