3R
Barber
3R Barber transitioned away from paper agendas and chaotic WhatsApp messages. I developed the scheduling app from scratch: clients book without creating an account, barbers view the queue in real time, and the admin monitors revenue per shop. Both locations run on it, in production since July 2026.
2
Shops Served
Product Gallery
Home page featuring the barbershop's two locations and the live queue.
Learn more about the technical architecture
Want to understand how this was built under the hood? Open the technical dive below.
expand_more
Learn more about the technical architecture
Want to understand how this was built under the hood? Open the technical dive below.
Technical Overview
3R Barber is a barbershop with two locations. I built the booking application as a pnpm monorepo — API, frontend, and shared package — running on Cloudflare's free tier with zero monthly infrastructure cost for the client. Clients book without an account: they select location, service, barber (or 'any barber'), and track their status via a unique link. Barbers and admins have dedicated dashboards for queue management, schedule, and reports.
Core Technologies
The Challenge
There is no shortage of off-the-shelf booking systems on the market — the problem is they all charge monthly subscriptions. I needed to deliver public booking, real-time queue management, and metrics dashboards with zero infrastructure cost, while ensuring accurate timezone handling across regions and strictly isolating access by role:
- / Accurately converting BRT operating hours to UTC timestamps when generating booking slots.
- / Supporting 'any barber' appointments, where the first available barber claims the client, without concurrency conflicts.
- / Isolating data by role (client/barber/admin), ensuring barbers can only access their own queue and calendar.
- / Preventing duplicate bookings from form resubmissions (double-clicks, network retries) without requiring client accounts.
The Solution
The API runs on Hono in Cloudflare Workers, with Drizzle on D1 and all mutations validated via Zod. Authentication and RBAC are handled by Better Auth. Every barber route first retrieves the barber record based on the authenticated user — preventing one barber from accessing another's schedule. BRT→UTC conversion is centralized in a backend helper. Duplicate bookings (double-clicks, network retries) are blocked at the application level and reinforced by a unique index in the database.
// Slot generation: BRT hora + 3 = UTC hora
const BRT_TO_UTC_H = 3;
export function getDayBounds(dateBRT: string) {
const [y, m, d] = dateBRT.split("-").map(Number);
const startTs = Date.UTC(y, m - 1, d, BRT_TO_UTC_H, 0) / 1000;
const endTs = startTs + 24 * 60 * 60 - 1;
return { startTs, endTs };
} Infrastructure
Deploy & CI/CD
API on Cloudflare Workers, frontend on Cloudflare Pages, both on the free tier. E2E tests with Playwright cover the full booking flow against an isolated D1 database recreated from scratch on each run.