Skip to main content

Architecture

Monorepo Structure

Tonnex uses Turborepo for monorepo management with pnpm workspaces.
tonnex/
├── apps/
│   ├── web/        → Next.js 15 (Admin Dashboard)
│   ├── api/        → NestJS (Logic Engine)
│   └── docs/       → Mintlify (Documentation)
├── packages/
│   ├── db/         → Drizzle ORM schemas & client
│   ├── ui/         → Shared UI components (shadcn)
│   ├── utils/      → Zod validators & formatters
│   ├── typescript-config/  → Shared TSConfigs
│   └── eslint-config/      → Shared ESLint configs
└── supabase/       → Supabase project config

Data Flow

  1. Userapps/web (Next.js) for UI interactions
  2. apps/web → Server Actions for simple mutations
  3. apps/web → Proxy (/api/v1/*) → apps/api (NestJS) for business logic
  4. apps/api@tonnex/db (Drizzle) → Supabase PostgreSQL
  5. Supabase RLS ensures data isolation per org_id

Authentication Flow

ComponentRole
Web (Client)@supabase/ssr — handles login, session cookies
API (Server)@supabase/supabase-js with SERVICE_ROLE_KEY — verifies JWT tokens

Multi-Tenancy

Every table has org_id. PostgreSQL Row Level Security (RLS) policies filter data automatically:
CREATE POLICY "org_isolation" ON table_name
  USING (org_id = current_setting('app.current_org')::uuid);