isidora

Pethox

Multi-tenant SaaS for pet care businesses

Personal project · 2026 · Full-stack
TypeScript
NestJS
Drizzle ORM
PostgreSQL
Better Auth
React
Vite
TanStack Query
Tailwind CSS
Radix UI
Railway
Neon
Docker
GitHub Actions
Kennel operations

Boarding kennels and daycare facilities run their whole operation from one workspace — clients, pets, spaces, bookings, pricing, invoicing, and team — with self-serve sign-up and a dashboard covering occupancy, arrivals, departures, and unpaid invoices.

Schema per tenant

Isolated every customer with a schema-per-tenant strategy on a single PostgreSQL instance: a tenant schema provisioned automatically at sign-up, requests scoped to it from the authenticated session, and shared concerns (accounts, sessions, tenant registry) kept in a separate public schema.

API

Built the API in NestJS with CQRS per feature, typed SQL and migrations through Drizzle ORM (separate histories for the public schema and the tenant template), and sessions via Better Auth extended to carry tenant and employee identity.

Stay lifecycle

Modeled the full stay lifecycle with business-rule validation (capacity, weight fit, overlap prevention, usage-mode fit) and a pricing catalog whose conditional rules snapshot onto a booking at creation, so past invoices never change when pricing changes later.

Frontend

Shipped the frontend in React 19 and TypeScript on Vite with TanStack Query for server state, Tailwind and Radix primitives, English/Spanish i18n, light/dark theming, and fine-grained per-employee permissions enforced at the API layer.

Deployment & CI

Deployed both apps independently on Railway with Neon Postgres, with GitHub Actions CI running build, lint, formatting, unit tests, and end-to-end tests against a real Postgres via Testcontainers.

Pethox

Run your pet care business with clarity

Geist
Variable sans
Mint#8DD8CA
Mist#D3F3EC
Lagoon#5CAEB2
Chrome#061512
BrowserReact SPARAILWAYphm-webReact + Vite · static buildphm-backendNestJS · CQRS · REST /apiHTTPS · cookie authtenant-scoped queriesNeon PostgreSQLone instance · schema per tenantpublictenant_atenant_b