Hospitality · PMS

KoroCRM

Multi-tenant CRM and Property Management System in production for Chivasom (Thailand) and Zulal (Qatar), two flagship luxury wellness resorts. NestJS + Nuxt 3 + MSSQL with decorator-enforced per-tenant isolation; ongoing platform engagement since November 2025.

Tech Stack:NestJSNuxt 3Vue 3Vuetify 3MSSQLTypeScript

The Problem

Luxury wellness resorts coordinate housekeeping, maintenance, lost-and-found, and concierge across spa, treatment, and back-of-house — often in multiple languages. Guest journeys are structured differently from a typical hotel stay, so generic “hotel software” rarely fits.

Off-the-shelf PMS products such as Opera or Mews cover broad hospitality operations. They are not tuned for high-touch wellness properties where treatment timing, inspections, and concierge routing sit at the centre of daily work.

Korotek needed one codebase serving multiple branded resorts with hard tenant boundaries: a Chivasom record must never appear under a Zulal context. The platform also had to evolve at the pace operations teams request features — not on an annual vendor release cycle.

The brief covered a full operational suite: Housekeeping, Inspections, Maintenance, Lost & Found, and Concierge. Every module had to be multi-tenant, auditable, and localised for the markets Chivasom and Zulal serve.

The Solution

Apex36 builds and maintains KoroCRM for Korotek on a continuous monthly engagement since November 2025. The product is also tracked internally as GXM360.

Backend: NestJS 10, Sequelize, Microsoft SQL Server, TypeScript. Frontend: Nuxt 3, Vue 3, Vuetify 3. Authentication uses JWT; authorisation uses CASL with permission decorators such as RequirePermissions on every controller.

Tenant isolation is enforced at the ORM layer. Custom TenantScoped and TenantIds NestJS decorators attach TenantId filtering to Sequelize queries. Context travels on x-tenant-id and x-tenant-scope headers, so a tenant-scoped query never reaches the database without a scope.

Five modules ship today: Housekeeping, Inspections, Maintenance, Lost & Found, and Concierge. English, Thai, Arabic, and French are in production — matching Chivasom, Zulal, and French-speaking guests.

An internal mssql-mcp-server (Model Context Protocol) speeds day-to-day MSSQL work during development. Repository rules in CLAUDE.md and AGENTS.md keep multi-tenant safety and permissions consistent as the team ships features.

Features

Five operational modules

Housekeeping, Inspections, Maintenance, Lost & Found, and Concierge. Each module is first-class in the product, with workflows aimed at luxury wellness operations rather than generic hotel patterns.

Decorator-based multi-tenancy

TenantScoped and TenantIds NestJS decorators enforce isolation at the Sequelize ORM layer. Requests carry x-tenant-id or x-tenant-scope; queries include a TenantId filter before MSSQL.

JWT + CASL authorisation

JWT for auth; CASL for fine-grained permissions (e.g. RequirePermissions on create/update paths). Capabilities are enforced at the controller before business logic runs.

English / Thai / Arabic / French i18n

Production support for English, Thai, Arabic, and French — for Chivasom, Zulal, and shared guest languages. Strings and payloads are localised across API and Nuxt UI.

Concierge + operator training

Concierge includes a training package: seven or more walkthrough videos plus DOCX transcripts for resort staff, so roll-out does not depend on ad-hoc explanations.

Internal mssql-mcp-server dev tool

Internal MCP server built to accelerate MSSQL querying during development.

Results / Impact

Chivasom & Zulal live

two luxury wellness resorts running on the same multi-tenant codebase.

5 operational modules

spanning housekeeping, inspections, maintenance, lost & found, concierge.

Per-tenant isolation via decorators

at the ORM layer, clean separation across branded properties.

FAQ

Isolation uses two custom NestJS decorators — TenantScoped and TenantIds — wired into Sequelize so every query that touches tenant data includes TenantId before MSSQL.

Tenant context comes from x-tenant-id or x-tenant-scope headers. A scoped model cannot be queried without tenant context. Review follows CLAUDE.md conventions so a Chivasom row cannot surface under Zulal regardless of who wrote the handler.

Chivasom (Hua Hin, Thailand) and Zulal (Qatar) run on the same multi-tenant deployment. Both are flagship wellness destinations in their regions.

Production languages: English, Thai, Arabic, and French. Staff and guests see the interface in the language that matches their property and role.

Backend: NestJS 10, Sequelize, MSSQL, TypeScript. JWT auth and CASL permissions on endpoints. Frontend: Nuxt 3, Vue 3, Vuetify 3 with script setup and composables.

The codebase is also known internally as GXM360. Multi-tenancy is enforced in Nest decorators tied to Sequelize, not as an afterthought in middleware.

Apex36, on a monthly engagement with Korotek running since November 2025.

Scope includes backend architecture, all five operational modules, the Nuxt frontend, en/th/ar/fr localisation, CLAUDE.md and AGENTS.md conventions, and the internal mssql-mcp-server tooling for faster database work.

Ready to build something impactful?

Let's discuss your project and how we can help you ship faster and smarter.

Book a Free Strategy Call