The Problem
A growing multi-branch salon needs a single web app where customers book stylists and services, and admins manage branches, stylists, services, reviews, and reservations. The core pain point is scheduling: a booking must fail if the chosen stylist already has a client at that time slot.
What This Does
This is a Next.js App Router full-stack app (app/) backed by a PostgreSQL database via Prisma (prisma/). Customers browse branches and services (app/branch/[name]/page.tsx, app/service/[name]/page.tsx), book with stylist and service selection plus conflict detection (components/Booking/booking.tsx), and view past reservations (app/reservation/page.tsx). Admins get a dashboard (app/dashboard/page.tsx) with CRUD routes under app/api/admin/ for branches, services, and stylists, plus deletion of reviews and reservations.
Authentication uses NextAuth (app/api/auth/[...nextauth]/route.ts) with bcrypt-hashed passwords (app/api/signup/route.ts); image uploads go through the Cloudinary API (app/api/signature/route.ts). The README documents a known restriction: admins must reload after any add/edit/delete for the UI to refresh.
How It Is Wired
Execution starts at app/layout.tsx → app/providers.tsx (session provider) → app/page.tsx, which routes to home/booking/dashboard based on auth state. API routes in app/api/ are the only path to the database: each route handler calls Prisma client methods directly, so a typical flow is booking.tsx → app/api/booking/reservations/route.ts → Prisma query → PostgreSQL. That is roughly three hops from UI to database.
components/Toast.tsx is the hub: 17 modules import it, and it imports nothing — churn there is high-blast-radius. components/Loading.tsx has 8 dependents. A 5-module import cycle sits around components/Dashboard/Dashboard.tsx, components/Booking/booking.tsx, and components/Booking/DateAndTime.tsx; anyone refactoring those must break the cycle first. Static analysis found 123 repeated 6-line blocks across 42 files in the admin routes and dashboard forms — extract shared helpers before touching them.
How To Use It
git clone https://github.com/moses-y/SEA-Salon.git
cd SEA-Salon
npm install
npx prisma migrate dev
npm run dev
Configuration lives in .env per .env.example: DATABASE_URL, NEXTAUTH_SECRET, and four Cloudinary variables. The app runs at http://localhost:3000.
Real-World Use
A customer picks a branch, selects a stylist and a time; booking.tsx posts to app/api/booking/reservations/route.ts, which checks for an overlapping reservation before inserting. If the slot is taken, the API returns a conflict and the UI shows it. An admin then updates the stylist's availability via app/api/admin/stylist/assign/route.ts.
Code Health & Issues
Static analysis (not opinion) reports 8 findings: 6 high, 2 medium, 4 kinds. High: the Toast.tsx hub (17 dependents), duplicated 6-line blocks across 42 files, and a 5-module import cycle. Medium: hub-module blast radius and deep nesting (depth 6) in components/Booking/booking.tsx.
SDLC gaps from the file structure: no CI workflow, no test suite, no LICENSE (default all-rights-reserved), and no Dependabot/Renovate. The README also embeds a full .env block with what appear to be live credentials (database URL, NextAuth secret, Cloudinary keys) — rotate those before any external use.
The Bottom Line
A well-scoped, functional Next.js project that demonstrates solid fundamentals: auth, ORM, API routes, and a real booking domain. It is not production-ready — no CI, no tests, no license, and committed credentials — but it is a credible portfolio piece for a hiring audience. Use it as a reference implementation, not as a starting point for a client system.