Architecture
Unified League Database Implementation Summary

Source: data_layer/docs/IMPLEMENTATION_SUMMARY.md

Unified League Database Implementation Summary

Architecture Overview

You now have a two-tier database system with intelligent database adapters:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    YOUR APPLICATION                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         unified_league_database.py (Orchestrator)        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  supabase_adapter.py β”‚    firebase_adapter.py           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚      SUPABASE        β”‚         FIREBASE                  β”‚
β”‚  (All Leagues)       β”‚    (Verified Only)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Files Created

Backend Services (Python)

  1. apps/backend/services/unified_league_database.py

    • Main orchestrator
    • Handles upserts to BOTH databases intelligently
    • Tracks source and verification status
    • Provides convenience functions
  2. apps/backend/services/supabase_adapter.py

    • Supabase database adapter
    • Handles all prospective leagues (scraped + verified)
    • Tracks enrichment, evaluations, contacts
  3. apps/backend/services/firebase_adapter.py

    • Firebase database adapter
    • Handles only verified partner leagues
    • Manages contracts, communications

Frontend (Next.js/TypeScript)

  1. clients/frontend-001-.../lib/league-database-client.ts

    • TypeScript client for frontend
    • Natural language query interface
    • Smart filtering and analytics
  2. clients/frontend-001-.../components/league-query-interface.tsx

    • React component for league queries
    • Beautiful UI with source tracking
    • Real-time statistics

Documentation

  1. database/DATABASE_ARCHITECTURE.md
    • Complete architecture documentation
    • Database schemas
    • Promotion workflow
    • Query patterns

How It Works

1. Upsert Scraped League (Supabase Only)

from apps.backend.services.unified_league_database import upsert_scraped_league
 
# Web scraping discovers a league
result = await upsert_scraped_league({
    "name": "International Basketball League",
    "sport_name": "Basketball",
    "sport_tier": "TIER2",
    "source_url": "https://example.com/ibl",
    "opportunity_score": 75
})
 
# Result:
# {
#   "supabase": {"success": True, "id": "abc-123"},
#   "firebase": {"status": "skipped", "reason": "Not human-verified"}
# }

Database State:

  • βœ… Supabase: League added with source_type: 'web_scrape', verification_status: 'unverified'
  • ❌ Firebase: Not added (only verified leagues go here)

2. Upsert Verified League (BOTH Databases)

from apps.backend.services.unified_league_database import upsert_verified_league
 
# Human verification through email/portal
result = await upsert_verified_league(
    {
        "name": "Premier Volleyball League",
        "sport_name": "Volleyball",
        "contact_info": {"email": "info@pvl.com"}
    },
    user_context={"email": "partner@altsportsdata.com"}
)
 
# Result:
# {
#   "supabase": {"success": True, "id": "def-456"},
#   "firebase": {"success": True, "id": "premier_volleyball_league"}
# }

Database State:

  • βœ… Supabase: League added/updated with source_type: 'human_verified', verification_status: 'human_verified'
  • βœ… Firebase: League ALSO added to verified_leagues collection

3. Owner Registration (BOTH Databases, Highest Trust)

from apps.backend.services.unified_league_database import upsert_owner_registered_league
 
# League owner registers through portal
result = await upsert_owner_registered_league(
    {
        "name": "Women's Soccer League",
        "sport_name": "Soccer",
        "contact_info": {"email": "owner@wsl.com"}
    },
    owner_context={"email": "owner@wsl.com"}
)
 
# Result:
# {
#   "supabase": {"success": True, "id": "ghi-789"},
#   "firebase": {"success": True, "id": "womens_soccer_league"}
# }

Database State:

  • βœ… Supabase: source_type: 'league_owner_registration', verification_status: 'owner_verified'
  • βœ… Firebase: Added with highest trust level

4. Query from Frontend (Natural Language)

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"
)
 
// Returns leagues matching:
// - sport_name: "Basketball"
// - opportunity_score >= 70
// - verification_status: "unverified"
// - source_type: "web_scrape"

5. 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"}
)
 
# Updates Supabase verification_status and adds to Firebase

Source Tracking

Every league has a source_type field:

Source TypeDescriptionGoes to Firebase?
web_scrapeDiscovered via web scraping❌ No (unless promoted)
email_ingestExtracted from email❌ No (unless promoted)
form_submissionSubmitted via form❌ No (unless promoted)
market_researchFound via research❌ No (unless promoted)
human_verifiedVerified via human contactβœ… Yes
onboarding_portalRegistered via portalβœ… Yes
direct_communicationEmail/phone confirmedβœ… Yes
league_owner_registrationOwner registeredβœ… Yes (highest trust)

Verification Status Tracking

Every league has a verification_status field:

StatusDescriptionFirebase Eligible?
unverifiedScraped, no contact❌ No
investigatingResearch in progress❌ No
contactedReached out, awaiting response❌ No
human_verifiedHuman communication confirmedβœ… Yes
owner_verifiedOwner verified through portalβœ… Yes
partnership_activeActive contractβœ… Yes
rejectedNot a fit❌ No

Frontend Query Examples

const client = getLeagueDatabaseClient()
 
// 1. All basketball leagues
await client.query("Show me all basketball leagues")
 
// 2. High-potential opportunities
await client.getHighPotentialOpportunities(80)
 
// 3. Verified partnerships only
await client.getVerifiedPartnerships()
 
// 4. Leagues needing contact
await client.getLeaguesNeedingContact(70)
 
// 5. Search by name
await client.searchByName("Premier")
 
// 6. Analytics
await client.getAnalytics()

Environment Variables Required

# Supabase (Required)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-key
 
# Firebase (Required for verified leagues)
FIREBASE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json
 
# Frontend (Required)
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000

Next Steps

1. Set Up Supabase

# Create Supabase project at https://supabase.com
# Run the SQL schema from DATABASE_ARCHITECTURE.md
# Add environment variables

2. Test Database Adapters

cd apps/backend
python -m services.unified_league_database

3. Populate Test Data

# Create a script to populate initial test data
from services.unified_league_database import upsert_scraped_league
 
leagues = [
    {"name": "International Basketball League", "sport_name": "Basketball"},
    {"name": "Premier Soccer League", "sport_name": "Soccer"},
    # ... more leagues
]
 
for league in leagues:
    await upsert_scraped_league(league)

4. Test Frontend Query Interface

cd clients/frontend-001-nextjs-ui-grok-chat-polymarket-micro-betting-altsport-opportunities
npm install
npm run dev
 
# Navigate to the league query interface
# Try natural language queries

5. Build Web Scraper

# Create a scraper that uses the unified database
from services.unified_league_database import upsert_scraped_league
 
async def scrape_leagues():
    # Scrape websites
    leagues = scrape_basketball_leagues()
 
    # Upsert to database
    for league in leagues:
        await upsert_scraped_league(league)

Benefits of This Architecture

βœ… Single Source of Truth: Supabase has ALL leagues βœ… Clear Separation: Firebase only has verified partners βœ… Source Tracking: Always know where data came from βœ… Easy Promotion: Simple workflow from scraped β†’ verified βœ… Database Adapters: Clean abstraction, easy to mock βœ… Natural Language Queries: Frontend can ask questions naturally βœ… Analytics Ready: Built-in statistics and reporting

Summary

You now have:

  1. βœ… Unified database service that upserts to both Supabase and Firebase
  2. βœ… Database adapters for clean abstraction
  3. βœ… Source tracking to distinguish scraped vs verified leagues
  4. βœ… Verification status workflow
  5. βœ… Frontend query interface with natural language
  6. βœ… Complete documentation of architecture and implementation

The system is ready to:

  • Accept scraped leagues (Supabase only)
  • Accept verified leagues (both databases)
  • Query intelligently from frontend
  • Track source and verification for every league

Multi-Database Enhancement (Neo4j + Pinecone)

🎯 Extension Overview

Extended the proven Prisma + JSONL pattern to add:

  • Neo4j: Graph relationships and archetype navigation
  • Pinecone: Vector embeddings for semantic search

πŸ“ Additional Files Created

  1. schemas/prisma/schema.v2.enhanced.prisma - Enhanced schema with embeddings + graph sync
  2. scripts/seed_unified_multi_db.py - Unified seeding (PostgreSQL β†’ Neo4j β†’ Pinecone)
  3. MULTI_DATABASE_ARCHITECTURE.md - Complete multi-DB architecture guide
  4. QUICKSTART_MULTI_DB.md - 10-minute setup guide

πŸ—οΈ Extended Architecture

JSONL Seeds (Source of Truth)
    ↓
PostgreSQL/Supabase (Primary DB) β†’ Fast queries, transactions
    ↓
Firebase (Verified Partners) β†’ Active partnerships
    ↓
Neo4j (Graph DB) β†’ Archetype relationships, pattern discovery
    ↓
Pinecone (Vector DB) β†’ Semantic search, similarity matching

✨ New Capabilities

1. Sport Archetypes

# Five master archetypes
archetypes = ["racing", "combat", "team_sport", "precision", "large_field"]
 
# Query leagues by archetype
combat_leagues = await db.league.find_many(
    where={"sport_archetype": "combat"}
)

2. Semantic Search

# Find leagues similar to "Formula 1"
query_embedding = generate_embedding("High-speed global racing championship")
 
similar = pinecone_index.query(
    vector=query_embedding,
    top_k=10,
    filter={"status": "active"}
)

3. Graph Relationships

// Find similar leagues within same archetype
MATCH (l:League {league_tag: 'ufc'})-[:BELONGS_TO_ARCHETYPE]->(a)
MATCH (similar:League)-[:BELONGS_TO_ARCHETYPE]->(a)
WHERE similar.league_tag <> 'ufc'
RETURN similar.league_name

4. Multi-DB Query Patterns

# 1. Vector search (Pinecone)
semantic_matches = index.query(vector=embedding, top_k=20)
 
# 2. Get full data (PostgreSQL)
leagues = await db.league.find_many(
    where={"league_tag": {"in": [m['id'] for m in semantic_matches]}}
)
 
# 3. Get relationships (Neo4j)
with neo4j_driver.session() as session:
    relationships = session.run("""
        MATCH (l:League {league_tag: $tag})-[:SIMILAR_TO]->(s)
        RETURN s
    """, tag=league.league_tag)

πŸš€ Quick Start (Multi-DB)

# 1. Install additional dependencies
uv add neo4j pinecone-client openai
 
# 2. Generate enhanced Prisma client
cd database/schemas/prisma
uv run prisma generate --schema=schema.v2.enhanced.prisma
 
# 3. Seed all databases
cd ../..
uv run python scripts/seed_unified_multi_db.py --all
 
# Or seed selectively
uv run python scripts/seed_unified_multi_db.py --archetypes
uv run python scripts/seed_unified_multi_db.py --leagues --limit 10
uv run python scripts/seed_unified_multi_db.py --examples --category triage

πŸ“Š Database Comparison

Use CaseDatabaseReason
Get league by IDPostgreSQL/SupabaseFast indexed lookup
Find verified partnersFirebaseOnly verified leagues
"Find leagues like F1"Pinecone β†’ PostgreSQLSemantic similarity
Discover archetype patternsNeo4jGraph traversal
Track web scrapingSupabaseAll prospective leagues
Active partnershipsFirebaseContract management

🎯 Enhanced Features

Automatic Embedding Generation

# During seeding
embedding = openai.embeddings.create(
    model="text-embedding-3-small",
    input=create_league_embedding_text(league)
).data[0].embedding
 
# Stored in PostgreSQL, synced to Pinecone

Sync Status Tracking

model League {
  // ... existing fields
 
  // Neo4j sync
  neo4j_node_id String?
  neo4j_synced_at DateTime?
  neo4j_sync_status String? @default("pending")
 
  // Pinecone sync
  pinecone_id String?
  pinecone_synced_at DateTime?
  pinecone_sync_status String? @default("pending")
}

Relationship Tracking

model LeagueRelationship {
  source_league_id String
  target_league_id String
  relationship_type String  // SIMILAR_TO, COMPETES_WITH, SAME_ARCHETYPE
  strength_score Decimal?
  neo4j_rel_id String?
}

πŸ’‘ Use Cases Enabled

1. League Discovery

// "Find elite combat sports leagues I might not know about"
const embedding = await generateEmbedding("elite combat sports global reach")
const matches = await pineconeIndex.query({vector: embedding, top_k=20})
const leagues = await db.league.findMany({
  where: {league_tag: {in: matches.map(m => m.id)}}
})

2. Competitive Intelligence

// Which archetypes have most TIER1 leagues?
MATCH (l:League {tier: 'TIER1'})-[:BELONGS_TO_ARCHETYPE]->(a:SportArchetype)
RETURN a.name, count(l) as tier1_count
ORDER BY tier1_count DESC

3. Similar Partnership Discovery

# Find leagues similar to successful partnerships
successful = await db.league.find_many(
    where={"firebase_synced": True, "status": "partnership_active"}
)
 
for league in successful:
    similar = pinecone_index.query(
        vector=league.embedding_vector,
        top_k=10
    )
    # Now you have leads similar to successful partners!

πŸ”„ Migration Path

Phase 1: Testing (This Week)

  • Use enhanced schema alongside existing
  • Test seeding with --limit 5
  • Validate sync accuracy

Phase 2: Parallel Run (Next Week)

  • Run both schemas in parallel
  • Compare query performance
  • Build confidence

Phase 3: Full Migration (Week 3)

  • Migrate to enhanced schema
  • Seed all historical data
  • Deploy to production

πŸ“š Documentation

  • MULTI_DATABASE_ARCHITECTURE.md - Deep dive into architecture
  • QUICKSTART_MULTI_DB.md - 10-minute setup guide
  • DATABASE_ARCHITECTURE.md - Original Supabase/Firebase architecture
  • IMPLEMENTATION_SUMMARY.md - This file

βœ… Complete System Capabilities

You now have:

  1. βœ… Supabase: All leagues (scraped + verified)
  2. βœ… Firebase: Verified partners only
  3. βœ… Neo4j: Graph relationships + archetypes
  4. βœ… Pinecone: Semantic search + similarity
  5. βœ… Prisma: Unified query layer
  6. βœ… JSONL: Single source of truth
  7. βœ… Sync Tracking: Per-database status monitoring
  8. βœ… Automatic Embeddings: OpenAI integration

Result: Best-in-class multi-database sports partnership intelligence platform! πŸš€

Platform

Documentation

Community

Support

partnership@altsportsdata.comdev@altsportsleagues.ai

2025 Β© AltSportsLeagues.ai. Powered by AI-driven sports business intelligence.

πŸ€– AI-Enhancedβ€’πŸ“Š Data-Drivenβ€’βš‘ Real-Time