Skip to content
← Back to Projects

ISO Studio Booking Platform

Apr 2026 - Present·Product Engineer - Solo Full-Stack
Nuxt 4VueSupabasePostgreSQLTailwind CSSVitestPWA

Overview

ISO Studio (isostudio.pl) is a live booking platform for an independent beauty studio in Warsaw, serving two audiences from one codebase: a public, multilingual client side where customers browse masters and services and book, reschedule, or cancel via passwordless email login; and a mobile-first admin panel where the owner manages masters, services, schedules, walk-ins, and clients. I owned it end-to-end - Postgres schema and stored procedures, the Nuxt 4 SSR app, every server API handler, slot-availability and concurrency logic, four-language i18n, transactional email and Telegram notifications, a scheduled reminder pipeline, PWA, and a multi-tier test suite.

Key Features

Race-Proof Slot Booking

Problem

A single-chair studio means a time slot can belong to only one client - but multiple clients, and admin walk-ins, can hit the same slot at the same moment. An application-level "is it free?" check has a race window that double-books.

Solution

Pushed the integrity guarantee down into Postgres: the bookings table carries a GiST exclusion constraint that rejects any overlapping confirmed booking, and every write goes through a SECURITY DEFINER stored procedure that validates ban status, availability, and scheduling windows, then catches the exclusion violation and returns a clean SLOT_TAKEN error.

Result

Double-booking is impossible by construction, not by convention. Integration tests fire two concurrent requests at the same slot and assert exactly one succeeds while the other is rejected with a 409.

Checkout Slot Holds with TTL

Problem

Even with conflict rejection at write time, a user filling in the confirmation step could still lose their slot to someone faster - a frustrating failure at the very last step.

Solution

Added a 7-minute advisory hold keyed to an httpOnly cookie token. The hold endpoint garbage-collects expired holds, re-checks bookings and other active holds before reserving, and resolves races through a unique constraint. Held slots are merged into the availability computation, so they disappear from everyone else's view for the duration.

Result

Users get a soft reservation while they check out, and concurrent attempts on a single slot resolve deterministically. Behavior is pinned by dedicated integration tests.

Mutually-Exclusive Admin & Client Sessions

Problem

One Supabase auth system backs both a public client area and a privileged admin panel. An admin logging in through the client flow - or the reverse - creates a confusing and potentially unsafe cross-scope session.

Solution

Factored session scoping into a pure, dependency-free policy function that returns allow / redirect / logout decisions, applied by a global route middleware on every navigation across locale-prefixed routes. Admin identity is RBAC-driven via a roles table, with an env-var break-glass fallback so an empty table can never lock everyone out.

Result

Admin and client sessions cannot coexist, enforced uniformly across the app. The policy is unit-tested in isolation from the framework.

DST-Correct Scheduling & Price Snapshotting

Problem

A Warsaw studio crosses daylight-saving boundaries, so "available slots for this day" must be computed against the real local day, not a naive UTC offset. And because service prices change over time, a past booking's price must never shift retroactively.

Solution

Anchored all slot math to Europe/Warsaw with date-fns-tz, deriving true local-day bounds that absorb the DST shift, then stepping a granularity grid filtered against bookings, holds, notice windows, and per-master buffers. Each booking snapshots the service name, price, and duration at creation, and money is stored as integer grosz throughout to avoid float drift.

Result

Correctness is pinned by a dedicated DST integration test plus unit tests for the time, slot, and pricing helpers.