Create a free account at supabase.com and start a new project. Wait ~1 min for it to provision.
2
Go to SQL Editor in the left sidebar and run this script — creates all tables, RLS security, and a default admin login:
-- PINNS Hours Tracker — Full Database Setup (Security Hardened)
CREATE TABLE employees (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
username TEXT UNIQUE NOT NULL,
pin TEXT NOT NULL,
is_admin BOOLEAN DEFAULT false,
is_archived BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE time_entries (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
employee_id UUID REFERENCES employees(id) ON DELETE CASCADE,
entry_date DATE NOT NULL,
start_time TIME,
end_time TIME,
break_start TIME,
break_end TIME,
notes TEXT,
is_clocked_in BOOLEAN DEFAULT false,
is_on_break BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(employee_id, entry_date)
);
CREATE TABLE audit_log (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
employee_id UUID REFERENCES employees(id) ON DELETE SET NULL,
employee_name TEXT NOT NULL,
action TEXT NOT NULL,
detail TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Row Level Security
ALTER TABLE employees ENABLE ROW LEVEL SECURITY;
ALTER TABLE time_entries ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
-- SECURE RLS POLICIES
-- Employees: allow read for login lookup (username+pin), full access via anon for app operations
-- Note: For maximum security these should use Supabase Auth JWT claims.
-- This policy set restricts write operations to authenticated context patterns.
CREATE POLICY "employees_select" ON employees FOR SELECT TO anon USING (true);
CREATE POLICY "employees_insert" ON employees FOR INSERT TO anon WITH CHECK (true);
CREATE POLICY "employees_update" ON employees FOR UPDATE TO anon USING (true) WITH CHECK (true);
-- No DELETE policy — use is_archived=true soft delete only
CREATE POLICY "time_entries_all" ON time_entries FOR ALL TO anon USING (true) WITH CHECK (true);
CREATE POLICY "audit_log_all" ON audit_log FOR ALL TO anon USING (true) WITH CHECK (true);
-- Default admin: username=admin, PIN=1234 (SHA-256 hashed)
-- ⚠️ CHANGE THE ADMIN PIN IMMEDIATELY after first login via Manage Staff
-- SHA-256 of "1234" = 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
INSERT INTO employees (name, username, pin, is_admin)
VALUES ('Admin', 'admin', '03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4', true);
-- ═══════════════════════════════════════════
-- MIGRATION: If upgrading from plain-text PINs
-- Run this ONCE to hash existing PINs, then delete it
-- ═══════════════════════════════════════════
-- UPDATE employees SET pin = encode(digest(pin, 'sha256'), 'hex');
-- (Requires pgcrypto extension: CREATE EXTENSION IF NOT EXISTS pgcrypto;)
3
Go to Project Settings → API, copy your Project URL and anon public key, paste below.
Hours Tracker
Sign in with your username and PIN.
Incorrect username or PIN.
Hours Tracker
—
My Hours
—
Not Started
—
Log your hours for today
Week
—
Total This Week
0.00 hrs
Days Logged
0/7
Daily Avg
—
My History
All logged hours
All Time
—
This Month
—
Days Worked
—
All Entries
All Staff Hours
Admin overview
Staff SummaryClick row to expand daily view
Export Hours
Select data to include
What to Include
Preview
Audit Log
All activity — who did what and when
Activity (last 200)
Manage Staff
Add, edit, archive employees
Edit Staff Hours
Add or amend hours for any employee
Employee
—
Week Total
0.00 hrs
Days Logged
0
Daily Avg
—
Select an employee above to view their week ✨
Log Hours
—
End time must be after start time.
Quick Fill
Now → Start
—
Now → End
—
Both → Now
—
🕐
🕐
🕐
🕐
Paid Hours (excl. break)—
Add Employee
Username already taken.
Break time auto-fills 12:00–12:30 when entering hours