Face Off Academy
Command Center
Reset Password
Enter your Supabase anon key to verify you own this project, then set a new password.
Face Off
Academy
Command Center
Overview
Athletes
Engagement
Setup
Not connected AUTO
Dashboard
🔗
Profile ↔ Leaderboard Match
—
👥
Duplicate Profiles
—
📱
Duplicate Devices
—
🎬
Athletes with Highlights
—
⟳ Auto-refresh active — data updates every 2 minutes
Total Athletes
—
Registered profiles
◉
States
—
States represented
⬡
Total Reps
—
Across all athletes
▲
Push Devices
—
Ready for notifications
📱
Athletes by State
● Awaiting Data
Connect Supabase to see live data
Top Athletes
● Awaiting Data
# AthleteState Reps Sessions FO% GB Goals Assists
Connect Supabase to load data
Quick Notify
Activity Log
Dashboard initialized
Just now
Drill Session History
Live · drill_sessions
DateRepsDurationState
Loading...
🎬 Highlight Reel
● Live · highlights
Loading highlights...
Athletes
● Live · profiles
#NameEmailPhoneStatePositionPush ConsentJoined
Connect Supabase to see athletes
🔎

No athletes match your search.

Connect Supabase to see leaders
Full Stats Table
● Live · leaderboard
#AthleteState Reps Sessions FO Wins FO Att FO% GB Goals Assists Last Active
Connect Supabase to see stats
Registered Devices
—
Ready for push
Cities
—
Unique cities
States
—
With devices
Push Devices
EmailStateCityRegistered
Connect Supabase to see devices
Bonus Codes
Connect Supabase to see bonus codes
Step 1 · Add Lacrosse Stats Columns
SQL · Run Once
1
Open Supabase SQL Editor
Go to your Supabase project → SQL Editor → New query
2
Run this SQL to add lacrosse stat columns
ALTER TABLE leaderboard ADD COLUMN IF NOT EXISTS fo_wins integer DEFAULT 0, ADD COLUMN IF NOT EXISTS fo_attempts integer DEFAULT 0, ADD COLUMN IF NOT EXISTS ground_balls integer DEFAULT 0, ADD COLUMN IF NOT EXISTS goals integer DEFAULT 0, ADD COLUMN IF NOT EXISTS assists integer DEFAULT 0;
3
Update your Rork app
In your Rork app code, when saving session results, also write the lacrosse stats to these new columns in the leaderboard table. The dashboard will immediately show live stats once data flows in.
Step 2 · Deploy Push Notification Edge Function
Supabase CLI
1
Get your Expo Access Token
Go to expo.dev → Account Settings → Access Tokens → Create token → Copy it
2
Create the Edge Function file
Create a file: supabase/functions/send-push/index.ts with this code:
// supabase/functions/send-push/index.ts import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', } Deno.serve(async (req) => { if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders }) const { title, body, state_filter } = await req.json() const supabase = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! ) // Get push tokens, optionally filtered by state let query = supabase.from('push_devices').select('device_token, user_email') if (state_filter) query = query.eq('state', state_filter) const { data: devices } = await query if (!devices || devices.length === 0) { return new Response(JSON.stringify({ sent: 0 }), { headers: corsHeaders }) } // Send to Expo Push API const messages = devices.map(d => ({ ''; title, body, sound: 'default', data: { source: 'foa-dashboard' } })) const response = await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${Deno.env.get('EXPO_ACCESS_TOKEN')}`, }, body: JSON.stringify(messages) }) const result = await response.json() return new Response( JSON.stringify({ sent: messages.length, result }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ) })
3
Deploy via Supabase Dashboard
Go to Supabase → Edge Functions → Deploy a new function → Paste the code above → Name it send-push
4
Set your secrets
In Supabase → Edge Functions → Secrets, add:
EXPO_ACCESS_TOKEN = your token from Step 1
5
Paste your Function URL below
Once deployed, copy the Edge Function URL and paste it in Supabase Config — then your Send Notification button fires real push notifications.
Step 2a · Create In-App Messages Table
SQL · Run Once
1
Run this in Supabase SQL Editor to enable in-app messaging
CREATE TABLE IF NOT EXISTS in_app_messages ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, type text DEFAULT 'Announcement', title text NOT NULL, body text NOT NULL, target_states text[], action_url text, expires_at date, active boolean DEFAULT true, created_at timestamptz DEFAULT now() ); -- Allow app to read active messages ALTER TABLE in_app_messages ENABLE ROW LEVEL SECURITY; CREATE POLICY "Anyone can read active messages" ON in_app_messages FOR SELECT USING (active = true); CREATE POLICY "Service role can manage messages" ON in_app_messages USING (true) WITH CHECK (true);
Step 2b · Add Database Indexes
SQL · Run Once · Performance
!
Run this once to keep queries fast as you scale
CREATE INDEX IF NOT EXISTS idx_drill_sessions_email ON drill_sessions(user_email); CREATE INDEX IF NOT EXISTS idx_leaderboard_email ON leaderboard(user_email); CREATE INDEX IF NOT EXISTS idx_highlights_email ON highlights(user_email); -- Prevent duplicate device tokens ALTER TABLE push_devices ADD CONSTRAINT push_devices_token_unique UNIQUE (device_token); -- Prevent duplicate bonus codes ALTER TABLE bonus_codes ADD CONSTRAINT bonus_codes_code_unique UNIQUE (code); -- Prevent duplicate profiles per email (add email col first if needed) -- ALTER TABLE profiles ADD COLUMN IF NOT EXISTS email text; -- ALTER TABLE profiles ADD CONSTRAINT profiles_email_unique UNIQUE (email);
Step 2c · Fix RLS on push_devices
Security · Recommended
!
Your push_devices table is currently UNRESTRICTED
Anyone with your anon key can read all device tokens. Run this to lock it down:
-- Enable RLS ALTER TABLE push_devices ENABLE ROW LEVEL SECURITY; -- Allow app to insert its own device token CREATE POLICY "Users can insert own device" ON push_devices FOR INSERT WITH CHECK (true); -- Only service role can read all tokens (dashboard uses service role) CREATE POLICY "Service role reads all" ON push_devices FOR SELECT USING (auth.role() = 'service_role');
⚠ After enabling RLS, update your dashboard anon key to the service_role key so it can still read devices.
Step 3 · Password Protection
✓ Already Active
✓
Login screen is live
The dashboard is already password protected. To change your password, click the button below.
Compose In-App Message
● Live · in_app_messages
Preview — How it appears in app
📢
Title here
Message here
✕
Active Messages
Connect Supabase to see messages
⚠️
Are you sure?
Send Notification
Push to athletes via Expo — requires Edge Function setup
Target Audience
📱 Preview
FACE OFF ACADEMY
Title
Message...
Supabase Config
Connect to your Face Off Academy database
Use the Legacy anon key (eyJ...) from Supabase → Settings → API → Legacy anon, service_role API keys tab
Create Bonus Code
Add a new promo code to your database
Change Password
Update your dashboard access password