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
- Pelanggan — Booking cepat dari HP & tahu kapan gilirannya tanpa menunggu di tempat
- Kapster — Lihat jadwal hari ini & tandai layanan selesai
- Kasir/Pemilik — Kelola slot, kapster, dan lihat laporan harian
User Stories
- must-haveSebagai pelanggan, saya ingin memilih layanan, kapster, dan jam kosong dari HP, agar saya tidak perlu antre di tempat.
- must-haveSebagai pelanggan, saya ingin melihat nomor antrean & estimasi giliran, agar saya bisa datang tepat waktu.
- must-haveSebagai kapster, saya ingin melihat daftar booking hari ini di layar, agar saya tahu pelanggan berikutnya.
- should-haveSebagai kasir, saya ingin menambah/menonaktifkan slot & kapster, agar jadwal sesuai kondisi hari itu.
- should-haveSebagai pemilik, saya ingin melihat laporan jam ramai & layanan per kapster, agar saya bisa atur shift & promo.
User Flow
- Pelanggan membuka halaman booking cabang dari HP.
- Pilih layanan, lalu kapster (atau 'siapa saja').
- Pilih slot jam yang masih kosong.
- Isi nama & nomor HP, lalu konfirmasi booking.
- Terima nomor antrean + link halaman status.
- Datang sesuai estimasi; kapster menandai 'Mulai' lalu 'Selesai'.
Features
Booking publik
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
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
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
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
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
- Pelanggan submit booking → API validasi slot & generate nomor antrean.
- Booking tersimpan di tabel bookings → Realtime broadcast ke channel cabang.
- Dashboard staf & halaman status pelanggan update otomatis tanpa refresh.
- Kapster menandai selesai → status berubah → antrean berikutnya maju.
Database Schema
Ini struktur data aplikasimu. Kamu tidak perlu paham semuanya — AI yang akan membuatnya. Kolom created_at/updated_at ditambahkan otomatis tiap tabel.
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)
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
Peran (RBAC)
Enum
Environment Variables
Library Inti
Tasks (siap kirim ke AI agent)
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.
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.
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.
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.
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.
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.
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.
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.