Skip to content
Selected work

// Case study · N°01

CoraVet.

Multi-tenant veterinary SaaS, sole engineer, live in production.

Role
Founder · Full-stack
Year
2025 → now
Status
live
Stack
NestJS 11 · Prisma 7 · PostgreSQL

A multi-tenant veterinary clinic SaaS I designed, built, and operate end-to-end as the sole engineer, from the data model and API through the dashboard, infrastructure, security hardening, observability, and go-to-market. The first live tenant is a real clinic in La Concordia, Ecuador.

CoraVet interface

// Context

The Ecuadorian SMB veterinary market is tech-skeptical, so the product is deliberately positioned as "your own clinic online": each clinic gets a personalized site and URL, not a seat on a shared platform. Regulated electronic invoicing was intentionally left out of scope; it belongs in the clinic's existing accounting tool.

Team

Sole engineer

Status

Live production tenant

Schema

26 Prisma migrations

Hardening

11-layer prod defense

What it is .

Two product surfaces from one codebase: a public marketing site plus per-clinic customer portal (Astro, statically rendered to Cloudflare), and an operational dashboard SPA for vets, managers, and staff (Vite + React 19). Both sit on a NestJS 11 API with a multi-tenant Prisma schema on PostgreSQL (Neon), organized as a pnpm + Turborepo monorepo with shared UI, API-client, and type packages.

Engineering depth .

Security and correctness are designed in, not bolted on.

  • Three stacked NestJS guards: Firebase auth, role, and a legal-acceptance gate that returns a machine-readable 403 the SPA routes on.
  • A Server-Sent Events layer (30+ typed events, per-user/clinic/role scoped) whose 30s heartbeat re-verifies Firebase session revocation in-band, closing stale streams within 30 seconds of deactivating a user.
  • Timezone correctness via a dedicated date-utils module: all datetimes UTC timestamptz, all query boundaries clinic-local; a documented invariant after a near-miss.
  • LOPDP-compliant legal versioning: SHA-256-hashed canonical Markdown, append-only acceptance table, boot-time drift detection, right-to-erasure as anonymization.
  • Server-side image pipeline (Sharp → WebP @ q80) turning multi-MB phone photos into ~80 KB cards, plus client-side pre-compression.

Infrastructure & operations .

A DigitalOcean droplet behind Cloudflare (WAF, Origin Cert, R2), with public SSH eliminated entirely. Both personal and CI/CD access ride a Tailscale private mesh. A multi-stage Alpine Docker image runs non-root with memory/CPU caps; a single GitHub Actions pipeline deploys from git push in under four minutes. Structured Pino logs with request-id propagation and free-tier-safe Sentry give end-to-end traceability.

Beyond the code .

I owned the launch, not just the build: brand and positioning decisions, LOPDP-compliant legal docs, and a 7,400+ entity Ecuador veterinary prospect dataset merged from five public sources (vet directories, Agrocalidad, Google Places, the SRI RUC catastro, OpenStreetMap) with a self-served filtering dashboard. Built with Claude Code as a pair-programming assistant throughout.

Notable decisions.

SSE over WebSockets

Real-time is one-way here. SSE rides standard HTTP/2, plays nicely with Cloudflare and firebase-admin-verified session cookies, and needs no custom auth handshake.

Cloudflare Origin Cert + IP-only firewall over Let’s Encrypt

A 15-year cert with no renewal failure mode, and a Cloudflare-IP-only droplet firewall that makes a leaked origin cert near-irrelevant.