Demo

App rescue: fix what was built in a hurry

A barbershop booking site, built fast with React, a small server and SQLite. It looked fine and had six bugs that cost money. For each one: a test that fails, the fix, the test passing.

The barbershop, its customers and the costs below are made up. The tests, the fixes and the run in the video are real.

47-second recording, no sound. One customer, old site then fixed.

The six bugs

Costs are rough guesses.

BugWhat it costsThe fix
Two people could book the same chair
Both got a text. One turns up to a taken chair.
A lost customer and a bad review.The database allows one booking per slot.
Anyone could read every customer's name and phone
The staff key shipped inside the site's own JavaScript.
The worst one: a data leak.A staff password checked on the server.
The day opened at 2:00 AM online
The server runs in UTC. Afternoons never showed.
Half the day's bookings.Hours in the salon's own time zone.
Anyone could cancel anyone's booking
Cancel only needed the booking number.
Empty chairs, no warning.A private cancel code per booking.
The Book button was off the screen on phones
Widths fixed for a laptop.
Most people book on a phone.A layout that wraps and stacks.
It said "booked" when nothing was saved
A phone typed "(555) 014-2231" was refused, quietly.
People turn up with no booking.Check the answer, show the error.

Before and after

The booking page on a 390 px phone.

Before: on a phone the slots and the Book button run off the right edge
Before
After: on a phone everything fits and the Book button is full width
After

The same day on a laptop, server in UTC.

Before: the day's slots run from 2:00 AM to 9:30 AM
Before
After: the day's slots run from 9:00 AM to 4:30 PM, salon time
After

Someone else took the slot while the form was open.

Before: the page says You're booked, but nothing was saved
Before
After: the page says sorry, someone just booked that time, please pick another
After

The tests

Written before the fixes, run on both copies. Before: 0 of 6 pass. After: 6 of 6.

TestBeforeAfter
Same slot, same momentfail
responses 200 and 200; bookings saved for that slot: 2
pass
responses 200 and 409; bookings saved for that slot: 1
Staff list stays privatefail
the staff list opened with "demo-admin-key-not-real", a string read from the site's JavaScript
pass
29 tries with every key-like string in 1 bundle(s), and none: all refused
Opens 9:00 AM salon timefail
first slot 2:00 AM, last 9:30 AM, on 2026-10-14 in salon time (want 9:00 AM to 4:30 PM on 2026-10-14)
pass
first slot 9:00 AM, last 4:30 PM, on 2026-10-14 in salon time (want 9:00 AM to 4:30 PM on 2026-10-14)
Can't cancel othersfail
Jen tried to cancel Tom's booking (id 4): 200; Tom's booking is gone
pass
Jen tried to cancel Tom's booking (id 3): 404; Tom's booking is still there
Fits a 390 px phonefail
page 784 px wide on a 390 px screen; Book button's right edge at 697 px
pass
page 390 px wide on a 390 px screen; Book button's right edge at 374 px
Honest formfail
"(555) 014-2231": page said "booked", bookings saved 0; a slot taken while the form was open: page said "booked", no error shown
pass
"(555) 014-2231": page said "booked", bookings saved 1; a slot taken while the form was open: page said not booked and showed an error

What changed

161 lines added, 70 removed, 5 files. Same screens and API.

FileAddedRemoved
server.js+45-11
slots.js+20-6
src/App.jsx+49-34
src/Admin.jsx+37-12
src/style.css+10-7