Skip to main content

Adding a New Module

Follow the V-Model workflow for implementing any feature in Tonnex.

Step 1: Define Validators

Create Zod schemas in packages/utils/src/validators/<module>.ts:
Export from packages/utils/src/validators/index.ts and packages/utils/src/index.ts.

Step 2: Define Database Schema

Create the Drizzle schema in packages/db/src/schema/<module>.ts:
Then export from packages/db/src/schema/index.ts and run:

Step 3: Add Resource Type for Scoping (if applicable)

If this module’s data should be filterable by location/warehouse, add the resource type to resourceTypeEnum in packages/db/src/schema/rbac.ts:
Then regenerate and migrate.

Step 4: Create API Module

Create the NestJS module in apps/api/src/<module>/:

Module — Import RbacModule

Controller — Add RBAC Guards

Service — Add Scope Filtering

Step 5: Register in App Module

Add to apps/api/src/app.module.ts:

Step 6: Create Frontend Pages

In apps/web/app/(dashboard)/vehicles/page.tsx, use DiceUI Data Table for the list view.

Step 7: Update Documentation

Create a guide at apps/docs/guides/<module>.mdx with:
  • Architecture diagram
  • Schema reference
  • API endpoint table
  • Usage examples
Every table MUST include org_id for RLS. Tables without org_id will not be protected by Row Level Security.
Every controller MUST use @UseGuards(SupabaseGuard, RbacGuard) and every method MUST have @RequirePermission.
NEVER create per-module junction tables for scoping. ALWAYS use the resource_scopes table via ScopeService.