Overview
RLink uses PostgreSQL (hosted on Neon) with Drizzle ORM for type-safe database operations. The schema is organized into three main domains:
CMS Tables Content, projects, articles, careers
CRM Tables Leads, reservations, inquiries, campaigns
IAM Tables Users, sessions, access control, logs
Schema Files
The database schema is split across two files:
db/schema.ts : Application-specific tables (CMS, CRM, IAM)
db/auth-schema.ts : Better Auth tables (users, sessions, etc.)
Entity Relationship Diagram
CMS Tables
Projects
Stores property development projects.
Column Type Description idUUID Primary key nameVARCHAR Project name slugVARCHAR URL-friendly identifier descriptionTEXT Project description statusENUM active, upcoming, completed, on-holdtypeENUM residential, commercial, mixed-usestageENUM pre-selling, selling, sold-out, under-constructionlocationTEXT Physical address coordinatesJSON Latitude/longitude nearby_landmarksJSON Array of nearby places amenitiesJSON Array of amenity IDs price_rangeJSON { min, max } pricingcover_photoVARCHAR Cover image URL seo_titleVARCHAR SEO meta title seo_descriptionTEXT SEO meta description seo_keywordsTEXT Comma-separated keywords publishedBOOLEAN Visibility status publish_dateTIMESTAMP Publication date created_atTIMESTAMP Creation timestamp updated_atTIMESTAMP Last update timestamp
Enums :
status : 'active' | 'upcoming' | 'completed' | 'on-hold'
type : 'residential' | 'commercial' | 'mixed-use'
stage : 'pre-selling' | 'selling' | 'sold-out' | 'under-construction'
Project Galleries
Photo galleries for projects.
Column Type Description idUUID Primary key project_idUUID Foreign key → projects.id image_urlVARCHAR Image file URL captionTEXT Image caption display_orderINTEGER Sort order house_modelVARCHAR Associated model (optional) created_atTIMESTAMP Upload timestamp
Amenities
Property amenities catalog.
Column Type Description idUUID Primary key nameVARCHAR Amenity name descriptionTEXT Description iconVARCHAR Icon identifier cover_photoVARCHAR Cover image URL categoryVARCHAR Amenity category created_atTIMESTAMP Creation timestamp
Careers
Job postings.
Column Type Description idUUID Primary key titleVARCHAR Job title slugVARCHAR URL-friendly identifier departmentENUM Department (see Departments ) descriptionTEXT Job description (Markdown) requirementsTEXT Job requirements (Markdown) locationVARCHAR Work location employment_typeENUM full-time, part-time, contractsalary_rangeJSON { min, max, currency }publishedBOOLEAN Visibility status publish_dateTIMESTAMP Publication date created_atTIMESTAMP Creation timestamp updated_atTIMESTAMP Last update timestamp
Articles
News articles and announcements.
Column Type Description idUUID Primary key titleVARCHAR Article title slugVARCHAR URL-friendly identifier contentTEXT Article content (Markdown) excerptTEXT Short summary typeENUM news, announcement, blogcover_imageVARCHAR Cover image URL author_idUUID Foreign key → users.id tagsTEXT[] Array of tags publishedBOOLEAN Visibility status publish_dateTIMESTAMP Publication date seo_titleVARCHAR SEO meta title seo_descriptionTEXT SEO meta description created_atTIMESTAMP Creation timestamp updated_atTIMESTAMP Last update timestamp
CRM Tables
Leads
Potential customer leads.
Column Type Description idUUID Primary key first_nameVARCHAR First name last_nameVARCHAR Last name emailVARCHAR Email address phoneVARCHAR Phone number sourceENUM website, referral, event, socialstatusENUM new, contacted, qualified, converted, lostinterestTEXT Areas of interest notesTEXT Internal notes assigned_toUUID Foreign key → users.id created_atTIMESTAMP Lead creation time updated_atTIMESTAMP Last update time
Reservations
Property unit reservations.
Column Type Description idUUID Primary key inventory_idUUID Foreign key → inventory.id project_nameVARCHAR Project reference client_nameVARCHAR Client full name contact_numberVARCHAR Client phone emailVARCHAR Client email reservation_dateTIMESTAMP Reservation timestamp statusENUM pending, confirmed, cancelledpayment_statusENUM unpaid, partial, paidnotesTEXT Additional notes created_byUUID Foreign key → users.id created_atTIMESTAMP Record creation time updated_atTIMESTAMP Last update time
Inventory
Property unit inventory.
Column Type Description idUUID Primary key project_idUUID Foreign key → projects.id inventory_codeVARCHAR Auto-generated code (e.g., “AR-B1-L5”) blockVARCHAR Block number lotVARCHAR Lot number house_modelVARCHAR Model type floor_areaDECIMAL Square meters lot_areaDECIMAL Square meters priceDECIMAL Unit price statusENUM available, reserved, soldsold_toUUID Foreign key → reservations.id (nullable) created_atTIMESTAMP Record creation time updated_atTIMESTAMP Last update time
Inventory Code Format : {ProjectInitials}-{Block}-{Lot}
Example: “AR-B1-L5” for Arcoe Residence, Block 1, Lot 5
Inquiries
Customer inquiry inbox.
Column Type Description idUUID Primary key nameVARCHAR Inquirer name emailVARCHAR Email address phoneVARCHAR Phone number subjectVARCHAR Inquiry subject messageTEXT Inquiry message statusENUM unread, read, responded, closedresponded_byUUID Foreign key → users.id responseTEXT Admin response created_atTIMESTAMP Inquiry timestamp updated_atTIMESTAMP Last update time
Newsletters
Newsletter subscriptions.
Column Type Description idUUID Primary key emailVARCHAR Subscriber email nameVARCHAR Subscriber name (optional) statusENUM subscribed, unsubscribedsubscribed_atTIMESTAMP Subscription timestamp unsubscribed_atTIMESTAMP Unsubscription timestamp
Campaigns
Marketing email campaigns.
Column Type Description idUUID Primary key nameVARCHAR Campaign name subjectVARCHAR Email subject contentTEXT Email content (Markdown) recipientsTEXT[] Array of emails or “all” statusENUM draft, scheduled, sentscheduled_atTIMESTAMP Send time (nullable) sent_atTIMESTAMP Actual send time created_byUUID Foreign key → users.id created_atTIMESTAMP Creation timestamp updated_atTIMESTAMP Last update time
DSL Tracker
Document Status List tracking.
Column Type Description idUUID Primary key client_nameVARCHAR Client name projectVARCHAR Project reference document_typeVARCHAR Type of document statusENUM pending, submitted, approved, rejectedsubmission_dateTIMESTAMP Submission timestamp notesTEXT Tracking notes created_atTIMESTAMP Record creation time updated_atTIMESTAMP Last update time
IAM Tables
Users (Better Auth)
User accounts managed by Better Auth.
Column Type Description idUUID Primary key emailVARCHAR Email address (unique) emailVerifiedBOOLEAN Email verification status nameVARCHAR Display name imageVARCHAR Profile image URL department_idUUID Foreign key → departments.id createdAtTIMESTAMP Account creation time updatedAtTIMESTAMP Last update time
Additional Better Auth tables include sessions, accounts, verifications, and twoFactor. See Better Auth documentation for details.
Departments
Company departments for user organization.
Column Type Description idUUID Primary key nameVARCHAR Department name descriptionTEXT Department description created_atTIMESTAMP Creation timestamp
Standard Departments (based on CHANGELOG):
// Actual departments vary - check db/schema.ts for current enum
departments :
| 'Executive'
| 'Sales'
| 'Marketing'
| 'Operations'
| 'Finance'
| 'IT'
| 'HR'
// ... etc
Module Access
Granular module-level permissions.
Column Type Description idUUID Primary key user_idUUID Foreign key → users.id moduleENUM cms, crm, iam, settingscan_readBOOLEAN Read permission can_writeBOOLEAN Write permission can_deleteBOOLEAN Delete permission created_atTIMESTAMP Creation timestamp updated_atTIMESTAMP Last update time
Activity Logs
Audit trail for user actions.
Column Type Description idUUID Primary key user_idUUID Foreign key → users.id actionVARCHAR Action type (e.g., “create”, “update”, “delete”) moduleVARCHAR Affected module resourceVARCHAR Affected resource type resource_idUUID Affected resource ID changesJSON Before/after snapshot ip_addressVARCHAR Request IP address user_agentTEXT Browser user agent created_atTIMESTAMP Action timestamp
Retention Policy : Logs older than 90 days are automatically deleted via daily cron job.
Relationships
One-to-Many
users → activity_logs: A user creates many activity logs
users → module_access: A user has many module access permissions
projects → project_galleries: A project has many gallery images
projects → inventory: A project contains many units
users → articles: A user authors many articles
Many-to-One
inventory → projects: Many units belong to one project
reservations → inventory: Many reservations link to inventory
users → departments: Many users belong to one department
Optional Relationships
inventory.sold_to → reservations.id: Inventory linked to reservation (nullable)
leads.assigned_to → users.id: Lead assigned to user (nullable)
inquiries.responded_by → users.id: Inquiry handled by user (nullable)
Migrations
Managing Schema Changes
Edit schema files : Modify db/schema.ts or db/auth-schema.ts
Generate migration : npx drizzle-kit generate
Review migration : Check generated SQL in drizzle/ directory
Apply migration : npx drizzle-kit migrate
Migration Files
Located in drizzle/ directory with timestamp prefixes:
drizzle/
├── 0000_initial_schema.sql
├── 0001_add_departments.sql
├── 0002_add_module_access.sql
└── ...
Always review generated migrations before applying to production. Drizzle Kit generates SQL based on schema changes, but complex migrations may require manual adjustments.
Indexes
Common indexes for performance often include:
Email fields (for lookups)
Foreign keys (for joins)
Status fields (for filtering)
Created/updated timestamps (for sorting)
Check db/schema.ts for actual index definitions.
Next Steps
REST API reference Explore database operations via API
Drizzle ORM docs Query API and migration guides