Source: data_layer/docs/QUICKSTART.md
League Database Quick Start Guide
π Get Started in 5 Minutes
Step 1: Set Up Supabase (2 minutes)
- Go to https://supabase.com (opens in a new tab) and create a free account
- Create a new project
- Go to SQL Editor and run:
# Copy and paste the SQL from: database/schemas/supabase_migration_001_prospective_leagues.sql - Go to Settings β API to get your credentials:
Project URLβSUPABASE_URLanon publickey βSUPABASE_ANON_KEYservice_rolekey βSUPABASE_SERVICE_KEY
Step 2: Configure Environment Variables (1 minute)
Add to your .env file:
# Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key-here
SUPABASE_SERVICE_KEY=your-service-key-here
# Frontend
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
# Firebase (optional for now)
FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.jsonStep 3: Test the Backend (1 minute)
cd apps/backend
python -m services.unified_league_databaseYou should see:
β
Supabase adapter initialized (MOCK MODE)
β
Firebase adapter initialized (MOCK MODE)
β
Initialized Unified League Database
=== Test 1: Scraped League ===
β
Mock upserted league: International Basketball League (ID: 1)
...Step 4: Test the Frontend (1 minute)
cd clients/frontend-001-nextjs-ui-grok-chat-polymarket-micro-betting-altsport-opportunities
npm install
npm run devNavigate to the league query interface and try:
- "Show me all basketball leagues"
- "Find high-potential soccer leagues"
π― Common Use Cases
Use Case 1: Add a Scraped League
from apps.backend.services.unified_league_database import upsert_scraped_league
result = await upsert_scraped_league({
"name": "New Basketball League",
"sport_name": "Basketball",
"sport_tier": "TIER2",
"source_url": "https://example.com/nbl",
"opportunity_score": 75
})
print(result)
# {
# "supabase": {"success": True, "id": "..."},
# "firebase": {"status": "skipped"}
# }What happens:
- β
Added to Supabase with
source_type: 'web_scrape'andverification_status: 'unverified' - β NOT added to Firebase (only verified leagues go there)
Use Case 2: Add a Verified League (Both Databases)
from apps.backend.services.unified_league_database import upsert_verified_league
result = await upsert_verified_league(
{
"name": "Premier Volleyball League",
"sport_name": "Volleyball",
"contact_info": {"email": "info@pvl.com"}
},
user_context={"email": "partner@altsportsdata.com"}
)
print(result)
# {
# "supabase": {"success": True, "id": "..."},
# "firebase": {"success": True, "id": "premier_volleyball_league"}
# }What happens:
- β
Added to Supabase with
source_type: 'human_verified'andverification_status: 'human_verified' - β ALSO added to Firebase (human-verified leagues get promoted automatically)
Use Case 3: Query from Frontend
import { getLeagueDatabaseClient } from '@/lib/league-database-client'
const client = getLeagueDatabaseClient()
// Natural language query
const result = await client.query(
"Show me high-potential basketball leagues we haven't contacted"
)
console.log(result.leagues)
// [
// {
// name: "International Basketball League",
// sport_name: "Basketball",
// source_type: "web_scrape",
// verification_status: "unverified",
// opportunity_score: 75
// }
// ]Use Case 4: Promote Scraped β Verified
from apps.backend.services.unified_league_database import UnifiedLeagueDatabase
db = UnifiedLeagueDatabase()
# After human contact confirms legitimacy
result = await db.promote_to_firebase(
supabase_league_id="abc-123",
user_context={"email": "sales@altsportsdata.com"}
)
print(result)
# {
# "success": True,
# "league_id": "abc-123",
# "firebase_id": "international_basketball_league"
# }What happens:
- Updates Supabase:
verification_status β 'human_verified',promoted_to_firebase β true - Adds to Firebase: Creates document in
verified_leaguescollection
π Query Examples
Frontend (TypeScript)
const client = getLeagueDatabaseClient()
// 1. Get all basketball leagues
const basketball = await client.executeQuery({ sport: "Basketball" })
// 2. Get high-potential opportunities (score > 80)
const highPotential = await client.getHighPotentialOpportunities(80)
// 3. Get verified partnerships only
const verified = await client.getVerifiedPartnerships()
// 4. Get leagues needing contact (score > 70, unverified)
const needsContact = await client.getLeaguesNeedingContact(70)
// 5. Search by name
const search = await client.searchByName("Premier")
// 6. Get analytics
const analytics = await client.getAnalytics()
console.log(`Total: ${analytics.total_leagues}`)
console.log(`Verified: ${analytics.verified_count}`)
console.log(`Scraped: ${analytics.scraped_count}`)Backend (Python)
from apps.backend.services.unified_league_database import (
query_all_leagues,
query_verified_leagues_only,
query_scraped_leagues_only
)
# Get all leagues
all_leagues = await query_all_leagues()
# Get only verified
verified = await query_verified_leagues_only()
# Get only scraped
scraped = await query_scraped_leagues_only()
# Filter by sport
basketball = await query_all_leagues({"sport_name": "Basketball"})π Understanding the Data Flow
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β WEB SCRAPING β
β (Discovers Leagues) β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ
β
β
ββββββββββββββββββββββ
β Supabase Database β β ALL LEAGUES
β (prospective_ β β’ Scraped (unverified)
β leagues) β β’ Verified (human contact)
ββββββββββ¬ββββββββββββ
β
βββββββββββ΄ββββββββββ
β β
β β
UNVERIFIED VERIFIED
(Scraped) (Human Contact)
β β
β β
β ββββββββββββββββββββββ
β β Firebase Database β
β β (verified_ β
β β leagues) β
ββββββββββββ€ β
β ONLY VERIFIED β
β PARTNERSHIPS β
ββββββββββββββββββββββπ¨ Frontend Integration
Add the query interface to any page:
import { LeagueQueryInterface } from '@/components/league-query-interface'
export default function LeagueDashboard() {
return (
<div className="container mx-auto p-6">
<h1 className="text-3xl font-bold mb-6">League Database</h1>
<LeagueQueryInterface />
</div>
)
}π Access Control
Supabase (Public + Authenticated)
- β Public read access (for discovery)
- β Authenticated write (for data entry)
- β Service role full access (for backend)
Firebase (Restricted)
- β No public access
- β Authenticated users only
- β League owners can edit their own data
- β Internal team has full access
π Monitoring
Check database health:
from apps.backend.services.unified_league_database import UnifiedLeagueDatabase
db = UnifiedLeagueDatabase()
analytics = await db.get_league_analytics()
print(f"Supabase: {analytics['supabase']['total_leagues']} leagues")
print(f"Firebase: {analytics['firebase']['total_leagues']} verified")
print(f"Promotion rate: {analytics['promotion_rate']:.1%}")π Troubleshooting
"Supabase client not initialized"
- Check
.envfile has correct Supabase credentials - Verify project URL and keys from Supabase dashboard
"Firebase adapter in mock mode"
- Normal during development
- Add
FIREBASE_SERVICE_ACCOUNT_PATHto use real Firebase
"Query returns no results"
- Run the sample data INSERT from the migration SQL
- Or add leagues manually using the backend service
Frontend can't connect
- Check
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEY - Verify Supabase project is running
- Check CORS settings in Supabase dashboard
π Next Steps
- Build a web scraper to populate Supabase with leagues
- Create an onboarding portal for league owners to register
- Add email integration to auto-classify incoming league inquiries
- Build analytics dashboard to track promotion rates
- Add Neo4j integration for relationship mapping (optional)
π Further Reading
- DATABASE_ARCHITECTURE.md - Complete architecture docs
- IMPLEMENTATION_SUMMARY.md - Implementation details
- Supabase docs: https://supabase.com/docs (opens in a new tab)
- Firebase docs: https://firebase.google.com/docs (opens in a new tab)