This app uses Supabase (free) to store everything in real time.
Create a free project at supabase.com, then run this SQL in the SQL Editor:
create table if not exists ptc_settings (app_id text not null, key text not null, value text, primary key (app_id, key));
create table if not exists ptc_subjects (id uuid default gen_random_uuid() primary key, app_id text not null, name text not null, sort_order int default 0);
create table if not exists ptc_teachers (id uuid default gen_random_uuid() primary key, app_id text not null, name text not null, subject_id uuid references ptc_subjects(id) on delete cascade, classes text[] not null default '{}', shared_code text default null);
create table if not exists ptc_bookings (
id uuid default gen_random_uuid() primary key,
app_id text not null,
parent_name text not null, child_name text not null, email text not null,
year_group text not null, class text not null,
subject text not null, teacher_id uuid, teacher_name text not null, shared_code text default null,
time_slot text not null, slot_key text unique not null,
booked_at timestamptz default now()
);
create table if not exists ptc_shared_teachers (
id uuid default gen_random_uuid() primary key,
name text not null,
notes text,
forms text[] not null default '{}',
created_at timestamptz default now()
);
grant all on ptc_shared_teachers to anon, authenticated;
create table if not exists ptc_breaks (
id uuid default gen_random_uuid() primary key,
app_id text not null,
teacher_id uuid references ptc_teachers(id) on delete cascade,
teacher_name text not null,
time_slot text not null,
unique(app_id, teacher_id, time_slot)
);
create table if not exists ptc_shared_teachers (
id uuid default gen_random_uuid() primary key,
name text not null,
notes text default null,
created_at timestamptz default now()
);
grant all on ptc_settings to anon, authenticated;
grant all on ptc_shared_teachers to anon, authenticated;
grant all on ptc_subjects to anon, authenticated;
grant all on ptc_teachers to anon, authenticated;
grant all on ptc_bookings to anon, authenticated;
grant all on ptc_breaks to anon, authenticated;
Stored only in this browser's localStorage. Completely free.