Lewati ke konten
Contoh hasil — dibuat dengan Skematik

AntreBaik — Booking & Antrean Barbershop

Aplikasi web untuk barbershop kecil agar pelanggan bisa booking slot dari HP dan melihat antrean real-time, sementara kapster & kasir mengelola jadwal dari satu dashboard. Mengurangi antre menumpuk di jam sibuk.

Problem

Barbershop tanpa sistem booking mengandalkan antre datang langsung. Di jam ramai pelanggan menunggu lama lalu kabur, sedangkan di jam sepi kapster menganggur. Pemilik tidak punya data jam ramai maupun performa tiap kapster.

Goals

  • Pelanggan bisa booking slot < 30 detik tanpa install aplikasi
  • Pelanggan tahu estimasi giliran secara real-time
  • Kurangi walkout (pelanggan kabur karena antre) minimal 40% dalam 2 bulan
  • Pemilik dapat laporan jam ramai & jumlah layanan per kapster

Non-Goals

  • Pembayaran online (fase 1 tetap bayar di kasir)
  • Aplikasi native iOS/Android (cukup web mobile dulu)
  • Program membership/poin loyalitas

Target Users

  • PelangganBooking cepat dari HP & tahu kapan gilirannya tanpa menunggu di tempat
  • KapsterLihat jadwal hari ini & tandai layanan selesai
  • Kasir/PemilikKelola slot, kapster, dan lihat laporan harian

User Stories

  • must-have
    Sebagai pelanggan, saya ingin memilih layanan, kapster, dan jam kosong dari HP, agar saya tidak perlu antre di tempat.
  • must-have
    Sebagai pelanggan, saya ingin melihat nomor antrean & estimasi giliran, agar saya bisa datang tepat waktu.
  • must-have
    Sebagai kapster, saya ingin melihat daftar booking hari ini di layar, agar saya tahu pelanggan berikutnya.
  • should-have
    Sebagai kasir, saya ingin menambah/menonaktifkan slot & kapster, agar jadwal sesuai kondisi hari itu.
  • should-have
    Sebagai pemilik, saya ingin melihat laporan jam ramai & layanan per kapster, agar saya bisa atur shift & promo.

User Flow

  1. Pelanggan membuka halaman booking cabang dari HP.
  2. Pilih layanan, lalu kapster (atau 'siapa saja').
  3. Pilih slot jam yang masih kosong.
  4. Isi nama & nomor HP, lalu konfirmasi booking.
  5. Terima nomor antrean + link halaman status.
  6. Datang sesuai estimasi; kapster menandai 'Mulai' lalu 'Selesai'.

Features

Booking publik

must-have

Halaman tanpa login: pilih cabang → layanan → kapster (opsional) → slot jam → isi nama & no. HP → konfirmasi.

  • Slot yang sudah penuh tidak bisa dipilih
  • Booking menghasilkan nomor antrean unik per hari
  • Konfirmasi tampil dengan ringkasan & link status antrean

Status antrean real-time

must-have

Halaman status per booking menampilkan posisi antrean & estimasi menit, diperbarui otomatis.

  • Posisi & estimasi diperbarui tanpa refresh manual
  • Status berubah otomatis saat kapster menandai selesai

Dashboard kapster & kasir

must-have

Login staf: daftar booking hari ini per kapster, tombol 'Mulai' & 'Selesai', tambah walk-in.

  • Hanya staf terautentikasi yang bisa akses
  • Menandai selesai memajukan antrean berikutnya
  • Walk-in masuk ke antrean yang sama

Laporan harian

should-have

Ringkasan jumlah layanan, jam tersibuk, dan layanan per kapster untuk rentang tanggal.

  • Bisa filter per tanggal & per kapster
  • Menampilkan total layanan dan grafik jam ramai

Tech Stack

Frontend: Next.js (App Router) + Tailwind CSS
Backend: Next.js Route Handlers + Server Actions
Database: PostgreSQL (Supabase) + Drizzle ORM
Hosting: Vercel + Supabase

Real-time via Supabase Realtime channel per cabang. Notifikasi WhatsApp opsional lewat API pihak ketiga di fase berikutnya.

Architecture

Aplikasi web full-stack di atas Next.js. Frontend & API menyatu (Route Handlers + Server Actions), data di PostgreSQL (Supabase), dan status antrean real-time lewat Supabase Realtime per cabang.

Web App (Next.js)

Halaman booking publik, status antrean, dan dashboard staf.

API Layer (Route Handlers)

Validasi booking, hitung slot, ubah status antrean.

PostgreSQL (Supabase)

Simpan cabang, layanan, kapster, dan booking.

Supabase Realtime

Broadcast perubahan status booking ke pelanggan & dashboard.

Alur data

  1. Pelanggan submit booking → API validasi slot & generate nomor antrean.
  2. Booking tersimpan di tabel bookings → Realtime broadcast ke channel cabang.
  3. Dashboard staf & halaman status pelanggan update otomatis tanpa refresh.
  4. Kapster menandai selesai → status berubah → antrean berikutnya maju.
Memuat diagram…

Database Schema

Ini struktur data aplikasimu. Kamu tidak perlu paham semuanya — AI yang akan membuatnya. Kolom created_at/updated_at ditambahkan otomatis tiap tabel.

branchesData cabang barbershop.
iduuidPK
nametext
open_hoursjsonbjam operasional per hari
servicesLayanan yang ditawarkan tiap cabang.
iduuidPK
branch_iduuidFK → branches.id
nametext
duration_minintegerdurasi menit
priceintegerrupiah
barbersKapster per cabang.
iduuidPK
branch_iduuidFK → branches.id
nametext
activebooleandefault true
bookingssoft deleteBooking & antrean pelanggan.
iduuid
branch_iduuid
service_iduuid
barber_iduuid
customer_nametext
customer_phonetext
slot_starttimestamp
queue_nointegernomor antrean harian
statusenum:BookingStatus

Relasi

  • services.branch_id → branches.id (many-to-one)
  • barbers.branch_id → branches.id (many-to-one)
  • bookings.branch_id → branches.id (many-to-one)
  • bookings.service_id → services.id (many-to-one)
  • bookings.barber_id → barbers.id (many-to-one, nullable)
Memuat diagram…

Struktur Folder

Struktur ini dikunci agar AI agent membangun dengan susunan file yang sama.

  • src/app/ — halaman Next.js (booking publik, status, dashboard)
  • src/app/api/ — route handlers (booking, slot, auth, laporan)
  • src/lib/db/ — skema Drizzle & koneksi
  • src/lib/services/ — logika bisnis (ketersediaan slot, antrean)
  • src/components/ — komponen UI reusable

API Endpoints

GET
/api/branches/:id/slotsSlot kosong per layanan/tanggal
POST
/api/bookingsBuat booking + nomor antrean
GET
/api/bookingsDaftar booking hari ini (dashboard)paginatedauth: CASHIER/BARBER
PATCH
/api/bookings/:id/statusUbah status (mulai/selesai)auth: CASHIER/BARBER
GET
/api/reports/dailyLaporan harian teragregasiauth: CASHIER

Peran (RBAC)

CASHIER
Kasir/pemilik· kelola slot & kapster, lihat semua booking, lihat laporan
BARBER
Kapster· lihat booking sendiri, ubah status booking

Enum

BookingStatusbooked · in_progress · done · no_show

Environment Variables

DATABASE_URLbackendwajibKoneksi PostgreSQL (Supabase)
JWT_SECRETbackendwajibRahasia sesi staf
NEXT_PUBLIC_SUPABASE_URLfrontendwajib
NEXT_PUBLIC_SUPABASE_ANON_KEYfrontendwajib

Library Inti

next · shareddrizzle-orm · backendzod · shared@supabase/supabase-js · shared

Tasks (siap kirim ke AI agent)

T1
Setup proyek & skema database· M

Inisialisasi Next.js, Tailwind, Drizzle, dan koneksi Supabase. Buat tabel cabang, layanan, kapster, booking.

Lihat isi perintah
Buat proyek Next.js (App Router, TypeScript, Tailwind). Tambahkan Drizzle ORM dengan PostgreSQL (Supabase). Definisikan skema untuk tabel: branches(id, name), services(id, branch_id, name, duration_min, price), barbers(id, branch_id, name, active), bookings(id, branch_id, service_id, barber_id nullable, customer_name, customer_phone, slot_start, queue_no, status enum['booked','in_progress','done','no_show'], created_at). Sertakan migration dan file koneksi db.
T2
Halaman booking publik· L· Butuh dulu: T1

Form multi-langkah: layanan → kapster → slot → data pelanggan → konfirmasi.

Lihat isi perintah
Bangun halaman publik /book/[branch] dengan alur: (1) pilih layanan, (2) pilih kapster atau 'siapa saja', (3) pilih slot jam berdasarkan durasi layanan & slot yang belum penuh, (4) isi nama + no HP, (5) konfirmasi. Simpan booking via server action, generate queue_no harian berurutan, redirect ke /status/[bookingId]. Nonaktifkan slot penuh.
T3
Ketersediaan slot· M· Butuh dulu: T1

Hitung slot kosong dari jam operasional, durasi layanan, dan booking existing.

Lihat isi perintah
Tulis fungsi getAvailableSlots(branchId, serviceId, date) yang menghasilkan daftar slot mulai berdasarkan jam operasional cabang, durasi layanan, dan booking yang sudah ada per kapster. Kembalikan slot yang masih punya kapster tersedia. Sertakan unit test untuk kasus penuh & sebagian.
T4
Halaman status antrean· M· Butuh dulu: T2

Tampilkan posisi antrean & estimasi menit untuk satu booking.

Lihat isi perintah
Buat halaman /status/[bookingId] yang menampilkan nomor antrean, posisi saat ini (berapa orang di depan pada kapster yang sama/hari yang sama), dan estimasi menit = jumlah di depan × durasi rata-rata. Tampilkan status booking. Siapkan agar mudah di-upgrade ke real-time di task berikutnya.
T5
Autentikasi staf· M· Butuh dulu: T1

Login sederhana untuk kapster & kasir dengan peran.

Lihat isi perintah
Tambahkan autentikasi staf (email+password) dengan peran 'barber' dan 'cashier' memakai Supabase Auth atau Better Auth. Lindungi route /dashboard sehingga hanya staf yang bisa akses. Kasir dapat akses penuh; kapster hanya melihat booking miliknya.
T6
Dashboard staf· L· Butuh dulu: T5

Daftar booking hari ini, tombol Mulai/Selesai, tambah walk-in.

Lihat isi perintah
Bangun /dashboard: daftar booking hari ini dikelompokkan per kapster, dengan tombol 'Mulai' (status→in_progress) dan 'Selesai' (status→done, majukan antrean). Sediakan form 'Tambah walk-in' yang membuat booking langsung ke antrean. Kasir bisa menonaktifkan kapster/slot untuk hari itu.
T7
Real-time update· M· Butuh dulu: T4, T6

Antrean & dashboard update otomatis via Supabase Realtime.

Lihat isi perintah
Integrasikan Supabase Realtime: subscribe perubahan tabel bookings per branch_id. Perbarui halaman /status/[bookingId] dan /dashboard tanpa refresh saat ada perubahan status. Pastikan unsubscribe saat unmount.
T8
Laporan harian· M· Butuh dulu: T6

Ringkasan layanan, jam ramai, dan per kapster.

Lihat isi perintah
Buat halaman /dashboard/laporan dengan filter rentang tanggal & kapster. Tampilkan total layanan selesai, grafik batang jumlah layanan per jam (jam ramai), dan tabel layanan per kapster. Query agregasi di sisi server.

Risks

  • Pelanggan booking lalu tidak datang (no-show) — perlu aturan & penanda no-show
  • Estimasi giliran meleset saat layanan lebih lama dari durasi standar
  • Koneksi internet di lokasi lemah — dashboard harus tetap berfungsi saat sinkron ulang

Open Questions

  • Apakah perlu batasan booking maksimal per no. HP per hari untuk cegah spam?
  • Apakah kapster boleh menolak/menukar booking yang masuk ke dirinya?
  • Notifikasi WhatsApp: fase 1 atau fase 2?

Bikin PRD seperti ini untuk idemu

Ceritakan idemu, AI menuliskan PRD terstruktur + task siap-tempel ke Cursor & Claude Code. Gratis untuk mulai.

Skematik · ide → PRD → task siap AI agent
Contoh PRD — Skematik