A SvelteKit web application for managing recreational soccer groups, collecting player ratings through surveys, and automatically generating balanced teams using a snake draft algorithm.
Clone the repository:
git clone <your-repo-url>
cd sveltekit-soccer-draft
Install dependencies:
npm install
Set up Supabase:
.env file:PUBLIC_SUPABASE_URL=your_supabase_project_url
PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
Set up the database schema (see Database Schema section below)
Run the development server:
npm run dev
Run these SQL commands in your Supabase SQL Editor:
-- Groups table
CREATE TABLE groups (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
admin_email TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Events table
CREATE TABLE events (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
group_id UUID REFERENCES groups(id) ON DELETE CASCADE,
name TEXT NOT NULL,
date DATE NOT NULL,
player_names TEXT[] DEFAULT '{}',
status TEXT DEFAULT 'survey' CHECK (status IN ('survey', 'drafted', 'completed')),
teams JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Survey responses table
CREATE TABLE survey_responses (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
event_id UUID REFERENCES events(id) ON DELETE CASCADE,
respondent_name TEXT NOT NULL,
player_name TEXT NOT NULL,
rating DECIMAL(4,1) CHECK (rating >= 1 AND rating <= 10),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(event_id, respondent_name, player_name)
);
-- Enable Row Level Security
ALTER TABLE groups ENABLE ROW LEVEL SECURITY;
ALTER TABLE events ENABLE ROW LEVEL SECURITY;
ALTER TABLE survey_responses ENABLE ROW LEVEL SECURITY;
-- Public read access policies
CREATE POLICY "Public can read groups" ON groups FOR SELECT USING (true);
CREATE POLICY "Public can read events" ON events FOR SELECT USING (true);
CREATE POLICY "Public can read survey responses" ON survey_responses FOR SELECT USING (true);
-- Public write access (you can restrict this later)
CREATE POLICY "Public can insert groups" ON groups FOR INSERT WITH CHECK (true);
CREATE POLICY "Public can update groups" ON groups FOR UPDATE USING (true);
CREATE POLICY "Public can insert events" ON events FOR INSERT WITH CHECK (true);
CREATE POLICY "Public can update events" ON events FOR UPDATE USING (true);
CREATE POLICY "Public can insert survey responses" ON survey_responses FOR INSERT WITH CHECK (true);
CREATE POLICY "Public can delete survey responses" ON survey_responses FOR DELETE USING (true);
As Regular User:
As Admin:
Your ratings are saved and you can update them anytime before teams are drafted.
If you're not happy with the team balance:
The app uses a snake draft algorithm to create balanced teams:
This ensures each team gets a mix of high and low-rated players.
sveltekit-soccer-draft/
├── src/
│ ├── lib/
│ │ └── supabase.js # Supabase client configuration
│ └── routes/
│ ├── +page.svelte # Home page (group join/create)
│ ├── admin/
│ │ └── +page.svelte # Admin panel
│ └── group/
│ └── [id]/
│ └── +page.svelte # Group dashboard (user view)
├── static/ # Static assets
├── .env # Environment variables (not in git)
├── package.json
├── svelte.config.js
├── tailwind.config.js
└── vite.config.js
PUBLIC_SUPABASE_URL: Your Supabase project URLPUBLIC_SUPABASE_ANON_KEY: Your Supabase anonymous keyBoth are marked with PUBLIC_ prefix as they're used client-side.
Currently using @sveltejs/adapter-auto. For specific deployment targets:
# Vercel
npm install @sveltejs/adapter-vercel
# Netlify
npm install @sveltejs/adapter-netlify
# Node.js
npm install @sveltejs/adapter-node
Update svelte.config.js to use the desired adapter.
# Development server with hot reload
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Check for errors
npm run check
⚠️ Current Implementation:
For Production:
MIT License - feel free to use this for your own soccer groups!
For issues or questions:
Built with: