1
Create a Supabase Project
Go to supabase.com, create a free account, and start a new project. Name it QVM Report Vault. Note your Project URL and anon public key from Settings → API.
2
Create the Reports Table
In the Supabase SQL Editor, run this script:
CREATE TABLE reports (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
report_number text NOT NULL UNIQUE,
subject_address text NOT NULL,
generated_date date NOT NULL,
qvm_version text,
pdf_storage_path text,
assigned_user_email text NOT NULL,
uploaded_by text,
created_at timestamptz DEFAULT now(),
downloaded_at timestamptz,
status text DEFAULT 'active'
CHECK (status IN ('active','archived','deleted'))
);
CREATE TABLE audit_log (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
event_type text NOT NULL,
report_id uuid REFERENCES reports(id),
actor_email text,
details text,
created_at timestamptz DEFAULT now()
);
3
Enable Row Level Security
ALTER TABLE reports ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Admin full access" ON reports
FOR ALL USING (auth.jwt() ->> 'email' = 'YOUR_ADMIN_EMAIL@gmail.com');
CREATE POLICY "Users see own reports" ON reports
FOR SELECT USING (
assigned_user_email = auth.jwt() ->> 'email'
AND status = 'active'
);
CREATE POLICY "Admin audit access" ON audit_log
FOR ALL USING (auth.jwt() ->> 'email' = 'YOUR_ADMIN_EMAIL@gmail.com');
4
Create Storage Bucket
In Supabase → Storage, create a bucket named qvm_reports. Set it to Private (no public access). Then run storage policies:
CREATE POLICY "Admin upload" ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'qvm_reports'
AND auth.jwt() ->> 'email' = 'YOUR_ADMIN_EMAIL@gmail.com'
);
CREATE POLICY "Admin read storage" ON storage.objects
FOR SELECT USING (
bucket_id = 'qvm_reports'
AND auth.jwt() ->> 'email' = 'YOUR_ADMIN_EMAIL@gmail.com'
);
⚠ For report user downloads, generate short-lived signed URLs (60–300 seconds) server-side or via Supabase Edge Functions so no user can guess or share a permanent URL to another user's PDF.
5
Create User Accounts
In Supabase → Authentication → Users, click Invite User and enter each email. Supabase sends a setup email. Users confirm and set their password. The admin account should be your personal QVM email. Report users get only their work email account.
6
Connect This File to Supabase
At the top of this HTML file, find the SUPABASE CONFIG section and replace the placeholder values:
const SUPABASE_URL = 'https://xxxxxxxxxxxx.supabase.co';
const SUPABASE_ANON = 'eyJhbGciOiJIUzI1NiIsInR5c...';
const ADMIN_EMAIL = 'your_admin@email.com';
Then host this file on any static host (Netlify, Vercel, or even a local machine with a simple HTTP server). Supabase handles all backend logic.
7
Folder Convention
Upload PDFs to the path: reports/YYYY/QVM-YYYY-000001.pdf
Example: reports/2026/QVM-2026-000042.pdf
The app auto-constructs this path from the report number and generated date you enter.