The ORM is Drizzle. The schema lives at apps/backend/src/db/schema.ts,
the client at apps/backend/src/db/index.ts, and committed migrations under
apps/backend/drizzle/.
Clerk is the source of truth for users and organizations. Postgres mirrors only
what domain tables need to reference. Add columns only when something actually
needs them.
Tables
organizations
Mirrors a Clerk org into Postgres so jobs and applications can reference it.
| Column | Type | Notes |
|---|
id | serial PK | |
clerkOrgId | text | Unique; links back to Clerk. |
name | text | |
slug | text | Unique; the {slug}.trexi.ai board subdomain. |
createdAt | timestamptz | |
jobs
| Column | Type | Notes |
|---|
id | serial PK | |
organizationId | int FK | → organizations.id, cascade on delete. |
slug | text | Unique within the org. |
title | text | |
description | text | Defaults to "". |
location | text | Optional. |
employmentType | text | Optional. |
status | enum | draft | open | closed. |
createdAt | timestamptz | |
updatedAt | timestamptz | |
job_applications
| Column | Type | Notes |
|---|
id | serial PK | |
jobId | int FK | → jobs.id, cascade on delete. |
name | text | |
email | text | |
coverLetter | text | Optional. |
resumeUrl | text | Optional. |
status | enum | new | reviewing | rejected | hired. |
createdAt | timestamptz | |
Migration workflow
Edit the schema → pnpm db:generate → review the generated SQL →
pnpm db:migrate. Use pnpm db:push only for throwaway dev iteration.