Levelz NYC
Appointment and membership platform for autobody shops: one codebase, many tenants, zero scheduling chaos.
The Problem
Independent autobody shops in NYC manage appointments through Instagram DMs, Google Sheets, and manual phone calls. There is no affordable multi-location SaaS that handles memberships, scheduling, and payments in one place. Enterprise options like ShopMonkey cost $300+/month and are overkill for a 2-location shop.
My Role
Full-stack developer. Designed the multi-tenant data model, built the booking engine, integrated Stripe subscriptions and webhooks, and implemented SMS reminders via Twilio. Also responsible for the admin dashboard and tenant onboarding flow.
Core Features
Multi-Tenant Architecture
Row-level security in PostgreSQL isolates each shop's data within a shared schema. A single deployment serves multiple locations, each with their own subdomain, branding, service catalog, and staff roles.
Stripe Subscription Billing
Clients purchase service packages (single visit, maintenance plan, unlimited monthly) via Stripe Checkout. Webhooks sync subscription and invoice state to the database in real time, with no manual reconciliation.
Bay & Appointment Scheduling
Shops configure available service bays, technician assignments, and job durations. The engine schedules appointments per bay, prevents double-booking, enforces capacity, and handles waitlists.
SMS Appointment Reminders
Twilio sends automated reminders 24h and 1h before each appointment. Shops configure reminder copy per service type. Cancellation links in SMS reduce no-shows and free up bay time.
Staff & Admin Dashboard
Shop managers see daily bay schedules, client check-in lists, revenue dashboards, and service renewal forecasts. Role-based access controls separate front-desk staff from managers and technicians.
Tech Stack
Architecture Overview
Next.js frontend with a Node.js/Express API layer. Prisma ORM manages the PostgreSQL schema with row-level security policies on every tenant-scoped table. Tenant context is resolved from the subdomain at middleware level and injected into every database query. Stripe webhooks land on a dedicated endpoint that uses idempotency keys to safely handle retries. Twilio job scheduling runs via a Redis-backed BullMQ queue. Reminders are enqueued at booking time and dequeued by a worker 24h/1h before the appointment. The entire stack runs on Docker Compose in production.
Impact
Reduced booking admin time for pilot shops from 2+ hours/day to under 20 minutes. Automated SMS reminders cut no-show rate by approximately 40% in the first month. Stripe integration eliminated manual cash reconciliation for service payments.
What I Learned
Multi-tenancy is deceptively complex to get right in PostgreSQL. Learned how to use `SET app.current_tenant_id` and RLS policies to enforce isolation at the database level rather than relying on application-layer WHERE clauses. Stripe webhook idempotency handling was also a hard-won lesson: duplicate delivery of the same webhook event can create double charges without proper deduplication.