Skip to content

martinduncanson/voy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VoyAI (MVP)  – A Sirvoy-Inspired, AI-Bootstrapped PMS

TL;DR
VoyAI is a fully-functioning, cloud-native PMS prototype that proves how modern AI-assisted development can compress months of work into a few hours. It couples a Node + Express + Prisma service layer with a Vite/React UI, packaged for friction-free deployment via Docker Compose or a traditional NGINX → PM2 stack.


1 Core Concept

The primary goal of VoyAI is to provide an all-in-one solution for small to medium-sized hospitality businesses (e.g., boutique hotels, B&Bs, vacation rentals). The system is designed to streamline operations, from booking and reservation management to housekeeping and guest communication, with a forward-thinking approach that includes AI-powered enhancements.

This MVP is built to be:

  • Functional: A working demo with core PMS features.

  • Scalable: An architecture that can grow with business needs.

  • Modern: Leveraging best practices in web development for performance and maintainability.

  • AI-aided extensions – dynamic pricing, auto-comms, housekeeping scheduling.

  • Dev-velocity showcase – the entire MVP (code you are reading) was scaffolded by SuperGrok and Gemini using a small PRD and text prompt citing Sirvoy features pasted from the wesbite, to illustrate how quickly a serious competitor could be boostrapped and materialised. Total build time including PRD and prompt to final git was around 2 hours.


2 Why This Tech Stack?

The technologies for VoyAI were chosen to deliver stability and scale on low-cost lightweight hardware, while giving performance at high concurrency.

### Backend: Node.js, Express.js & Prisma

  • Node.js & Express.js: Node.js's asynchronous, non-blocking I/O model is a perfect fit for a PMS. It can efficiently handle thousands of concurrent connections from users, booking channels, and API requests without getting bogged down. This is crucial for real-time features like calendar updates and channel synchronization. Express.js provides a minimalist and flexible framework for building the robust REST API that powers the application.

  • Prisma (ORM): Prisma is a next-generation ORM that revolutionizes database interactions.

    • Type Safety: It auto-generates a type-safe client from your schema.prisma file. This means your database queries are validated at compile time, catching errors before they ever reach production.
    • Simplified Queries: Its intuitive API makes complex queries (like joins and transactions) simple and readable, significantly reducing boilerplate code.
    • Migration Management: prisma migrate provides a powerful, declarative system for evolving your database schema safely and keeping it in sync with your models. This is a massive improvement over manually writing and managing SQL migration scripts.

### Frontend: React (with Vite) & Material-UI

  • React: Its component-based architecture allows for the creation of a complex, reusable, and easily maintainable user interface.
  • Vite: Provides a lightning-fast development experience with near-instant Hot Module Replacement (HMR) and optimized build tooling.
  • React Query: Simplifies data fetching, caching, and state synchronization, eliminating the need for complex global state management for server-side data.
  • Material-UI (MUI): A comprehensive library of UI components that allows for rapid development of a professional and visually appealing dashboard.

Architectural Advantages Over PHP

While PHP is a capable language, this Node.js/React architecture offers several distinct advantages over a traditional monolithic PHP application (e.g., a LAMP stack):

  • Decoupled (Headless) Architecture: The backend is a standalone REST API. The React frontend is just one client that consumes it. This separation of concerns means you can easily build other clients (like a native mobile app for iOS/Android) on top of the same API without rewriting any backend logic.

  • Superior Real-Time Capabilities: Node.js, combined with Socket.IO, is built for real-time communication. Features like instant notifications for new bookings or live chat with guests are far more complex to implement efficiently in a traditional PHP environment.

  • Full-Stack Type Safety: With TypeScript or JSDoc in the backend and TypeScript/PropTypes in the frontend, combined with Prisma's type-safe client, you can achieve end-to-end type safety. This drastically reduces runtime errors and makes the codebase more robust and refactor-friendly.

  • Scalability and Performance: The event-driven, non-blocking nature of Node.js is designed for I/O-heavy applications like a PMS, which constantly queries the database and external services. This can lead to better performance and resource utilization under heavy load compared to PHP's synchronous request/response model.


Ultra-lightweight Hardware Requirements

On a single 8-core / 32 GB VPS (priced at $252/m from Digital Ocean) you can safely serve ≈ 70 k – 135 k concurrent guests, depending on how chatty the front-end is, while keeping p99 API latency < 150 ms.

  • Back-of-envelope capacity translation: We need to map “req/s” → “concurrent guests”. For a typical booking widget: Live page pings availability every 10 s → 0.1 req/s/user (heavy, DB-hit). UI also holds a WebSocket but that is idle CPU-wise.

  • 13 500 req/s ÷ 0.1 req/s/user ≈ 135 000 simultaneous guest users. Add maybe 1 000 staff dashboards (heavier, ~1 req/s) and you are still under 80 % CPU.

  • If you instead poll every 5 s (0.2 req/s/user) the same box sustains ≈ 67 500 guests.

Why this holds together

Node throughput numbers:

  • Public benchmarks place an Express + Postgres hit at 2 400 – 2 800 req/s per vCPU on c6g instances.
  • We used the conservative 2 600 figure and still shaved 35 % off for head-room.

Memory footprint

PostgreSQL: https://aws.amazon.com/blogs/database/analyze-your-postgresql-memory/ measures 1.5–14 MB per backend; we pool 80 connections (10 per worker) ⇒ ≤ 1 GB. Shared buffers at 25 % RAM (8 GB) gives excellent hit ratios for a dataset of ±10 M reservations. Node workers: 8 × (60 MB idle + 80 MB live heap) ≈ 1 GB. WebSocket objects: ≈ 2 KB each ⇒ 200 k users ≈ 400 MB JS side + ~800 MB kernel.

Single-box trade-offs

Pros: zero network hops, simplest ops. Cons: you share CPU cache between Postgres and Node. Under Black-Friday-style spikes, DB checkpoints can jitter API latency. Vertical scaling up to 16 cores is painless, but beyond that, read-replica or pgBouncer split becomes cheaper.

Why these numbers are credible

CPU evidence – An Express process with DB writes managed ≈ 2 600 req/s on a single-core t2.small in public testing; a pure in-memory route cleared ≈ 7 300 req/s. Memory per Postgres connection – AWS engineers measured 1.5–14.5 MB real-world overhead per backend Socket overhead – Node keeps per-socket state in JS objects; typical resident footprint is ≈ 2 KB (buffers + handle metadata) – tiny compared with V8 heap.

Head-room & scaling out

Horizontal Node scaling – Because Prisma uses a connection pool per process, simply adding more API instances (or Kubernetes pods) scales CPU without exploding DB connections—just cap each pool at 10–12.

  • pgBouncer – If you ever need <200 ms query spikes for BI dashboards, stick pgBouncer in transaction mode; Postgres now holds ~1 GB RAM no matter how many Node workers you add.

  • Read replicas – 25 k properties × multi-year reservations history can outgrow SSD cache. A single async replica offloads reports with no write penalty.

  • Beyond 50 k guests – Tests show Express is CPU-bound long before it’s memory-bound, so the upgrade path is linear: +1 core ≈ +2 500 req/s.

With this sizing in place you can confidently add features without immediately racing for bigger metal—and that’s the real strength of the Node + Prisma stack.


## Key Features

  • Centralized Dashboard: At-a-glance view of key metrics like occupancy, revenue, and recent reservations.
  • Property & Room Management: Full CRUD functionality for creating and managing properties and their associated rooms.
  • Reservation Management: A comprehensive system for viewing, creating, and updating bookings.
  • Simulated Channel Manager: A background cron job (node-cron) simulates fetching bookings from external channels like Booking.com and Airbnb every 5 minutes, with real-time updates pushed to the UI via WebSockets.
  • AI-Enhanced Features (Proof of Concept):
    • Smart Pricing Suggestions: An API endpoint that uses a simple model to suggest rate adjustments.
    • Automated Housekeeping: Automatically creates cleaning tasks when a reservation is added.
  • JWT Authentication: Secure, stateless authentication protecting all backend routes.

Layer Stack Why it beats the obvious PHP/LAMP alternative
Runtime Node 20 + Express 4 Single-threaded, non-blocking I/O is ideal for channel-sync polling, WebSockets, and heavy JSON workloads. A PHP FPM process would block per request without ReactPHP-style hacks.
ORM/Data Prisma 5 Type-safe queries, migrations-as-code, and a fluent API. Prisma shields you from SQL-string injection bugs and makes refactors painless—something PDO in PHP simply can’t match.
Database PostgreSQL 14 ACID compliance, native JSONB columns (great for OTA payloads), and powerful upserts.
Real-time Socket.io 4 Drop-in push updates (e.g., channel-sync events) without polling tricks. With PHP you’d need Ratchet or RoadRunner externally.
Background jobs Node-Cron Share code with the HTTP layer. In PHP you’d run separate cron + CLI scripts, duplicating business logic.
Auth JWT (stateless) Easily shared between Node API and React SPA; no server-side session storage.
Front-end React 18 + Vite 5 + MUI 5 Instant HMR, modern JSX, typed hooks; effortlessly consumes the JSON API. Classic PHP templating can’t match the developer UX or component reuse.
Tests Jest + Supertest (API), Cypress 12 (E2E) End-to-end confidence with minimal boilerplate.
Packaging Docker (multi-service Compose) One-command parity between local dev, CI runners, and prod VPS; eradicate “works on my machine”.

Additional Strengths over a Typical PHP Monolith

  • Isomorphic code reuse – validation helpers and DTOs can be shared across server & client.
  • Native ES Modules – clean import syntax throughout the repo.
  • First-class package manager – >2 million NPM modules vs disparate PHP Composer repos.
  • Better concurrency model – Node’s event loop + clustering scales horizontally without PHP-FPM pool juggling.
  • Simpler DevOps – A single Dockerfile builds both API & UI; a docker-compose up -d spins the full stack.

3 High-Level Architecture

┌──────────┐     REST/WS     ┌───────────────┐
│ React UI │◄──────────────►│  Node API     │
│  (Vite)  │                │ Express + JWT │
└──────────┘                ├───────────────┤
                            │Prisma (ORM)   │
                            └───────────────┘
                                   ▲
                                   │
                         ┌──────────────────┐
                         │ PostgreSQL 14    │
                         └──────────────────┘
  • Realtime push – Socket.io notifies the dashboard whenever channelService.syncChannels() runs (via a 5-minute cron).
  • AI services/api/ai/* routes expose TensorFlow-JS powered smart-pricing and an email auto-comms stub.

4 Repository Layout

├── Dockerfile              # Defines the environment for the backend service
├── docker-compose.yml      # Orchestrates the multi-container setup (db, backend, frontend)
├── README.md
├── SETUP.md
├── backend/
│   ├── prisma/
│   │   └── schema.prisma   # Single source of truth for the database schema
│   ├── routes/             # API route definitions (auth, properties, etc.)
│   ├── services/           # Business logic (channel sync, payments)
│   ├── index.js            # Main Express server entry point
│   ├── .env.example        # Environment variable template
│   └── package.json
└── frontend/
├── src/
│   ├── pages/          # Top-level page components (Dashboard, Login, etc.)
│   ├── components/     # Reusable UI components (if any)
│   ├── api.js          # Pre-configured Axios instance for API calls
│   ├── store.js        # Redux store setup (for client-side state)
│   └── App.jsx         # Main React application component with routing
├── vite.config.js
└── package.json

5 Running Locally

Full “click-next, next, finish” deployment lives inside SETUP.md. For a five-second taste:

# 1. Clone & seed DB
cp backend/.env.example backend/.env      # edit DATABASE_URL & JWT_SECRET
docker-compose up -d db
npx prisma migrate dev --schema backend/prisma/schema.prisma

# 2. Start API
npm --prefix backend install
npm --prefix backend start

# 3. Start Front-end
npm --prefix frontend install
npm --prefix frontend run dev

Visit http://localhost:3000, register an admin account, and you’re in.


6 Contributing & Next Steps

  • Security hardening – Helmet CSP, rate limits already scaffolded; add 2FA.
  • Real OTA connectors – Replace the mocked Booking.com/Airbnb services with signed API calls.
  • CI/CD – GitHub Actions job can build and push the Docker images to GHCR, then SSH-deploy to your VPS.
  • TypeScript migration – Prisma types shine even brighter when the rest of the codebase is typed.

PRs welcome!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors