← All projects Build log

pms_ixa

A property management system for a portfolio of short and long-term rentals: bookings, clients, billing, and the sales channels the stays arrive through.

Status In production
Started May 2026
Stack Node · Vue 3 · SQLite

What it is

Overview

A booking calendar with the operational parts attached: clients and their documents, billing per stay, and a fixed catalogue of sales channels — each one switched on or off, with its own commission rate. Channels are not names somebody typed; each is a driver the application knows, which is what let it later speak those portals' own calendar protocol.

Multi-user from the start, so the interesting problems were never the CRUD ones: who may change what, how you prove afterwards what was changed, and how a release reaches the running instance without a half-applied moment where the shell is new and the API is old.

How it evolved

Arc

May — make it work. The calendar, expandable booking rows edited in place, reusable field components, and a design system pulled out of the scattered SCSS once the shape settled. Two languages by the end of the month.

June — make it trustworthy. Authorization enforced rather than assumed, and an immutable audit log: every accepted change leaves a record nobody can quietly edit.

August — make it hold. Persistence moved from JSON files to embedded SQLite with a one-off conversion, and the server now refuses to boot against a schema it does not recognise. Roles became four, with the permission decided at the route. Deployment stopped being a manual step. Then two-way calendar sync and a public request inbox, which turned a private admin tool into something the outside world talks to — and that, in turn, is why a password stopped being the whole answer.

The arc, in one line: a CRUD app in May, a system with an audit trail, a migration path, a release pipeline and two-factor authentication by September.

Screens

Interface
Calendar — screenshot pending
The booking calendar: stays coloured by channel, today drawn as a box over the whole column.
Metrics — screenshot pending
Occupancy and billing metrics, redesigned in June.

Changelog

Newest first

August 2026

2026-08

Two-step verification Security

A password is no longer the whole answer. Any account can ask for a six-digit code mailed to its own address, opt-in per user from the profile screen. An admin can clear somebody else's when they lose access to the mailbox it goes to.

2026-08

Channels became drivers Feature

A channel stopped being a name somebody typed and became a driver the application knows, carrying its own mark and commission. Direct stays are a channel too — no intermediary, no commission, never deletable.

2026-08

Two-way calendar sync Feature

Reads the channels' calendars and publishes its own, so a stay booked anywhere blocks the dates everywhere. Plus an inbox for requests coming from the public site, and a read-only availability endpoint it may ask about.

2026-08

Four roles, decided at the route Security

Permission checks moved to where the request is handled instead of being spread through the UI. A role is changed, an account is deleted, an address is saved — three different operations that used to be one blurry one.

2026-08

Automated release pipeline Infra

Tests run, the image is built and published, the instance is redeployed, and the pipeline waits for the health check and confirms the deployed version before calling it done. A separate development instance is seeded from real data. The SPA shell is served no-store, so a deploy can never be half-applied in someone's browser.

2026-08

SQLite replaces the JSON files Infra

Embedded SQLite instead of files on disk, with a one-off conversion for existing data and a schema collapsed into a single migration before launch. The server refuses to boot against a schema it does not recognise, rather than corrupting one it half-understands.

2026-08

Hardening pass Security

The login rate limit is keyed on a client IP that cannot be forged. A malformed body answers 400, not 500. Errors reaching the top are logged instead of silently becoming a 500. Two bugs the test suite could not see were found by running against the real container.

June 2026

2026-06

Audit log and enforced authorization Security

Every accepted change writes an immutable record. Authorization stopped being an assumption about who reaches a screen and became a rule the server enforces.

2026-06

Metrics page redesign Feature

Rebuilt so the numbers are read at a glance, and fixed the row clipping and the shrinking date ranges that showed up on narrow displays.

May 2026

2026-05

Two languages and a design system Refactor

English and Spanish through vue-i18n, scattered SCSS centralized into a styles layer, inline SVGs replaced by real assets, and reusable input field subcomponents so editing behaves the same everywhere.

2026-05

The calendar, editable in place Feature

Expandable booking rows edited without leaving the calendar, a client administration screen, per-user self-administration, and the navigation hierarchy the rest of the app still uses.

2026-05

First commit Start

A monorepo, a Node server, a Vue client, and a booking that could be written down.