Connect your database

Go to supabase.com, create a free project, open SQL Editor → New query, paste and run:

CREATE TABLE IF NOT EXISTS public.bookings ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, customer_name text NOT NULL, phone text, date date NOT NULL, time_slot text NOT NULL, duration integer NOT NULL DEFAULT 1, court text NOT NULL, fee integer NOT NULL DEFAULT 0, payment_method text DEFAULT 'Cash', discount_note text DEFAULT '', group_id text DEFAULT '', created_at timestamptz DEFAULT now() ); ALTER TABLE public.bookings ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS "allow_all" ON public.bookings; CREATE POLICY "allow_all" ON public.bookings FOR ALL USING (true) WITH CHECK (true);

If you already have the table, run these to add the new columns:

ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS duration integer NOT NULL DEFAULT 1; ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS payment_method text DEFAULT 'Cash'; ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS discount_note text DEFAULT ''; ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS group_id text DEFAULT ''; ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS created_by text DEFAULT '';

Then run this to create the auth support tables:

CREATE TABLE IF NOT EXISTS public.profiles ( id uuid REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY, email text, full_name text, role text DEFAULT 'staff', created_at timestamptz DEFAULT now() ); ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; CREATE POLICY "profiles_all" ON public.profiles FOR ALL USING (true) WITH CHECK (true); CREATE TABLE IF NOT EXISTS public.app_settings ( key text PRIMARY KEY, value text NOT NULL, updated_at timestamptz DEFAULT now() ); ALTER TABLE public.app_settings ENABLE ROW LEVEL SECURITY; CREATE POLICY "settings_all" ON public.app_settings FOR ALL USING (true) WITH CHECK (true); -- Seed default pricing (edit anytime in the Settings tab) INSERT INTO public.app_settings (key,value) VALUES ('price_day','550'), ('price_eve','700'), ('pay_gcash_num','0917 321 ****'), ('pay_gcash_name','Pickle at The Kiln'), ('pay_gotyme_num','****2253'), ('pay_gotyme_name','Pickle at The Kiln') ON CONFLICT (key) DO NOTHING; CREATE TABLE IF NOT EXISTS public.booking_requests ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, customer_name text NOT NULL, phone text, date date NOT NULL, start_hour integer NOT NULL, end_hour integer NOT NULL, courts text[] NOT NULL, status text DEFAULT 'pending', hold_expires_at timestamptz, payment_method text DEFAULT '', receipt_url text DEFAULT '', receipt_note text DEFAULT '', fee integer NOT NULL DEFAULT 0, created_at timestamptz DEFAULT now() ); ALTER TABLE public.booking_requests ENABLE ROW LEVEL SECURITY; CREATE POLICY "requests_all" ON public.booking_requests FOR ALL USING (true) WITH CHECK (true); -- Storage bucket for receipts (run in Supabase Storage settings) -- Create a public bucket named: receipts

If you already have booking_requests, add the new columns:

ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS hold_expires_at timestamptz; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS payment_method text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS receipt_url text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS receipt_note text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS fee integer NOT NULL DEFAULT 0; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS booking_ref text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS receipt_hash text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS recurring_group text DEFAULT ''; ALTER TABLE public.booking_requests ADD COLUMN IF NOT EXISTS consent_given_at timestamptz;

For the Waitlist feature, also run:

CREATE TABLE IF NOT EXISTS public.waitlists ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, customer_name text NOT NULL, phone text, date date NOT NULL, start_hour integer NOT NULL, end_hour integer NOT NULL, courts text[] NOT NULL, note text DEFAULT '', status text DEFAULT 'pending', notified_at timestamptz, created_at timestamptz DEFAULT now() ); ALTER TABLE public.waitlists ENABLE ROW LEVEL SECURITY; CREATE POLICY "waitlists_all" ON public.waitlists FOR ALL USING (true) WITH CHECK (true);

Then go to Project Settings → API and paste below.

Operator dashboard

Dark
Light

Configure database connection

📥 Reports
Today's bookings
Checked in today
Revenue collected
Outstanding unpaid
Add booking
🚨 Conflict radar
Your selection
Already booked
⚠ Conflict
Blocked
Court status — now
Loading…
Today's schedule
CustomerTimeCourtPaymentFeeStatus
All bookings
to
CustomerPhoneDateStartEndCourtHrsPaymentFeePaidNoteCreated
All customers
to
NamePhoneVisitsTotal hrsTotal spentLast visit
Share availability with customers

Pick a month or week — customers see availability only, no names.

Court schedule
What customers will see

Month view — full month grid, each day as a column, each time slot as a row, Open / Booked per court.
Week view — 7-day grid starting from the selected date, same layout. Good for sharing a specific week.

Block off courts

Mark courts as unavailable for maintenance, cleaning, or a private reservation. It will show as blocked on the customer calendar.

Current block-offs
Showing upcoming only
Court Date Time Reason Created
Monthly occupancy heatmap
Less
More
💰 Collected
Past · Paid
⚠ Accrued
Past · Unpaid
📅 Upcoming
Future bookings
Period:
Total bookings
Revenue
Avg booking value
Occupancy rate
of available slots
Unique customers
Total court-hours
Cancellations
Top payment method
Revenue by day of week
Court utilization % of slots booked
Peak hours bookings per slot
Revenue per court
Top 10 customers
Monthly revenue trend
Slots to promote lowest booked time slots
New vs returning customers
Revenue trend last 6 months · paid
Customer booking history
Share this link so customers can look up their own bookings by phone number.
Booking requests
Review and approve customer requests
Customer booking link
No requests yet.
Waitlist
Customers waiting for a slot to open up
No waitlist entries.
Add staff account
Staff accounts
Loading…
Settings
Manage pricing and payment details.
Court pricing
Set the hourly rate for day slots (before 4 PM) and evening slots (4 PM onwards). Changes apply immediately to all new fee calculations.
Rate preview — per court
Time
Rate/hr
2 hrs
Payment details
Shown to customers on the payment page. Update if your account details change.
Promo codes
Create discount codes customers can enter at checkout. Supports % or fixed ₱ discounts.
New code
No promo codes yet.
SMS Notifications
Automatically send SMS to customers when you approve or decline a booking request via Semaphore.
SMS sending
Turn on only when Semaphore sender is approved
Placeholders: {name} {court} {date} {time} {ref}
Placeholders: {name} {date} {time}
Sent when a customer's 1-hour hold expires without payment. Placeholders: {name} {date} {time} {court}
🔔 Telegram Notifications
Get instant Telegram alerts when a new booking request arrives. Works with personal chats or group chats — free, no credits needed.
Telegram alerts
Notifies your group on every new booking request
Get this from @BotFather on Telegram
Negative number = group chat · Positive number = personal chat
Blackout dates
Close the entire venue for a day. Customers won't be able to book on these dates.
No blackout dates.
Backfill booking references
Assign a TK-XXXX reference number to all existing bookings that don't have one yet. Safe to run multiple times.
🚫 Blacklist
Block customers from making public bookings. Staff will also be warned when adding them manually.
No blacklisted customers.
Booking window
Limit how far in advance customers can book. Useful when you only want to open bookings month by month.
days from today
Book a court
Pick your slot, pay, upload receipt — done. Your slot is held for 1 hour after you submit.
Step 1 — Your details
Philippine mobile number (09XX or +639XX)
Court rates
☀ 8AM–4PM /hr 🌙 4PM–12AM /hr

Step 3 — Pay to confirm

Slot held for you
Pay and upload receipt before timer expires
60:00
Courts
Date & Time
Total₱0
Booking ref
Choose payment method:
Scan QR or transfer
Scan QR or transfer
Payment QR Code
Pickle at The Kiln
Transfer fees may apply
Upload your payment receipt:
📄
Tap to upload receipt
Photo or screenshot of your GCash / GoTyme transfer
Receipt preview
Receipt
QR Code
Tap anywhere to close
Court availability
Availability shown per court per hour. Contact us on Instagram (@thekiln.cebu) to reserve your slot. No personal information is displayed.
Open
Held
Booked
Want to book a court?
Send us a request and we'll confirm within a few hours. No payment needed upfront.
Book Now →
Pay via GCash or GoTyme · Slot held 1 hour
Or DM us on @thekiln.cebu

TheKiln. — Cebu | Availability updates in real time

📥 Download report

Quick select:

⏳ Join the waitlist

That slot is fully booked. Add yourself to the waitlist — we'll reach out if a spot opens up.

Pickleball Court · Cebu
Booking
Customer
Phone
Date
Time
Court(s)
Duration
Payment
Total
?
Visits
Hours
Total spent
No-shows
Notes
Booking history

Edit customer

Past bookings

Manage booking

Reschedule to