EN|ES
← projects/
pargo.nest.tsMVP in demos

Pargo

Multi-tenant SaaS POS for restaurants and hotels on Colombia's Caribbean coast

company:
Personal project
period:
Jul 2026 — ongoing
  • NestJS 12
  • Fastify
  • TypeScript
  • PostgreSQL (RLS)
  • Valkey
  • React
  • TanStack Query
  • Next.js
  • Turborepo + pnpm
  • Zod
  • OpenTelemetry
  • Docker
  • Testcontainers
  • Playwright
  • Anthropic / OpenAI / Gemini

// problem

Restaurants on Colombia's Caribbean coast deal with frequent internet outages, mandatory electronic invoicing and generic POS systems that neither deduct inventory nor reconcile the cash drawer. The reference projects I analyzed had serious flaws: the client set the totals, anyone could sign up as admin and payment webhooks weren't idempotent.

// my role

I design and build it end to end: technical plan, 11 ADRs, multi-tenant PostgreSQL data model, NestJS API, POS and back office in React, public site in Next.js, multi-provider AI package, hardened Docker infrastructure and a local verification pipeline that runs on every push. It is my personal project and I built it with AI-assisted development: the AI speeds up the implementation, while the architecture, the data model and every technical decision are mine, documented and justified in the ADRs.

// architecture

POSPWA · signed offline
BackofficeReact · TanStack Query
QR menu / webNext.js
APINestJS 12 · Fastify
public-apiread only
Workerinvoices · AI · email
Valkeyrate limit · sessions
PostgreSQLRLS multi-tenant
Factus (DIAN)e-invoicing
Multi-provider AIreviews · reputation

Modular monolith: the same codebase deployed as three processes with different database permissions. Electronic invoicing currently runs against a simulated provider while Factus is integrated.

// technical decisions

Fail-closed multi-tenancy with Row Level Security

Every table has RLS ENABLE + FORCE and composite foreign keys (tenant_id, id); database roles are not superusers and cannot bypass RLS, and the API refuses to start if its role could. Without a business context a query returns nothing, and there are A↔B isolation tests for reading, updating, deleting, inserting and referencing.

Offline POS with a lease and signed events

While online, the POS requests a 24-hour lease with a snapshot of the catalog and a sales cap. Offline, each sale is an event signed with the device's non-exportable ECDSA key and stored encrypted in IndexedDB. On sync, the server verifies the signature and recalculates prices from the stored snapshot, never from what the tablet sends; suspicious cases are flagged for manager review instead of losing money that was actually collected.

Inventory as a ledger with recipes and average cost

Each sale deducts ingredients according to the recipe of the variant and its modifiers (a large snapper with patacón doesn't use the same as a medium one with coconut rice). Purchases, waste, adjustments and physical counts are movements in a per-location ledger, so stock can always be rebuilt and audited.

Multi-provider AI with a deterministic score

Review analysis returns structured outputs validated with Zod on Anthropic, OpenAI or Gemini. The reputation score is computed deterministically from stored data, not estimated by the model; review replies always require human approval, each business has a budget and there is an evaluation suite against prompt injection.

AI-assisted development, human-owned decisions

I used AI as a pair programmer to build faster as a single developer, but every decision starts from a real constraint and is recorded in an ADR: a modular monolith because one person can deploy and operate it, with module boundaries that allow splitting it later; RLS so that tenant isolation is enforced by the database rather than depending on every query remembering a filter; an offline POS because internet outages on the coast must not stop sales; and an inventory ledger so stock can be audited. No change gets in without tests against real PostgreSQL, which is how I verify that the generated code does what was decided.

// impact

Automated tests
751

+ 8 Playwright E2E against the real stack

Documented decisions
11 ADRs
Selling without internet
24 h

signed lease with a sales cap

Processes
3

api · public-api · worker

// screenshots

POS: floor plan by zones with occupied tables
POS: floor plan by zones with occupied tables
Order: configuring the snapper (size and side)
Order: configuring the snapper (size and side)
Kitchen screen with real-time tickets
Kitchen screen with real-time tickets
Checkout: splitting the bill between diners
Checkout: splitting the bill between diners
Cash closing: Z report that balances after the blind count
Cash closing: Z report that balances after the blind count
Accepted electronic invoice
Accepted electronic invoice
Fried red snapper recipe per variant
Fried red snapper recipe per variant
Back office: daily summary and inventory alerts
Back office: daily summary and inventory alerts
Public digital menu opened by scanning the QR

Personal project in a private repository, built with AI-assisted development. Screenshots come from the demo restaurant, with fictitious data.