
Trilo: Full-Stack SaaS for Sports League Automation
Executive Summary
Built a full-stack SaaS product from 0→1: a Discord bot automating fantasy football league management (reducing commissioner workload from 3+ hours/week to under 5 minutes) plus a conversion-optimized marketing site with Stripe payments and Discord OAuth. End-to-end ownership from AI feature development to user acquisition funnels.
The Problem
Running a fantasy football dynasty league on Discord is operationally brutal.
- Administrative Burden: Commissioners spend 3+ hours weekly creating matchup channels, tracking records, and managing team rosters manually.
- Commissioner Burnout: High friction causes 40%+ of leagues to fold within two seasons due to organizer fatigue.
- Fragmented Tools: Existing solutions either require external websites (friction) or charge per-league pricing ($15-35/league), making multi-league management expensive.
- No AI Integration: Manual schedule entry from game screenshots is tedious and error-prone.
The Solution
I built two interconnected products that form a complete SaaS business:
1. Trilo Bot (Discord)
An intelligent Discord bot that automates league operations through slash commands. Commissioners interact where their community already lives. No external tools required.
2. Trilo Website (React)
A marketing site that handles user acquisition, Discord OAuth authentication, Stripe payments, and license key delivery via Discord DM.

System Architecture
The platform is fully event-driven across both products, with shared state in Supabase.
Data Flow
- Acquisition: User visits trilo.gg → authenticates via Discord OAuth
- Conversion: Stripe checkout creates subscription → webhook fires
- Fulfillment: License key generated → delivered via Discord DM
- Activation: User runs
/admin activatein Discord → bot validates against Supabase - Usage: Bot handles all league operations, storing data in PostgreSQL
Key Features
AI-Powered Matchup Creation
The flagship feature: upload a schedule screenshot and Trilo extracts team matchups automatically.

Technical Implementation:
- OpenAI Vision API (gpt-4o-mini) processes images with structured JSON schema enforcement
- 95% extraction accuracy achieved through prompt engineering
- Cost-optimized: ~10x cheaper than GPT-4 Vision with comparable results
Discord-Native Operations
Everything happens where the community lives. No external dashboards.

Command Groups:
/teams- Assign users to teams, view rosters, auto-updating list embeds/matchups- Create game channels, sync records, AI schedule import/attributes- Award points, approve upgrades, track spending/settings- Configure roles, channels, league type (CFB/NFL)
Reaction-Based Game Status
Single-tap interactions for marking games complete.

Conversion-Optimized Website

UX Decisions:
- Discord OAuth pre-checkout reduces friction
- License key delivered via Discord DM (arrives where they'll use it)
- Interactive setup guide with progress tracking
Technical Stack
| Layer | Technology | Purpose |
|---|---|---|
| Discord Bot | Python 3.11 + discord.py | Async-first bot framework with slash command support. |
| OpenAI Vision API (GPT-4o-mini) | AI-powered schedule screenshot extraction. | |
| PostgreSQL (Supabase) | Production database with connection pooling. | |
| SQLite (aiosqlite) | Local development database. | |
| Railway | Hosting with auto-deploy from main branch. | |
| Marketing Site | React 19 + TypeScript | Type-safe frontend with latest React features. |
| Vite | Fast build tooling and HMR. | |
| Tailwind CSS + Framer Motion | Styling and animations. | |
| Vercel Serverless Functions | API endpoints for OAuth and webhooks. | |
| Payments & Auth | Stripe | Subscription billing and checkout sessions. |
| Discord OAuth2 | User authentication and license key delivery via DM. | |
| License Key System | Custom TRILO-XXXX-XXXX-XXXX format with 3-server activation. |
Key Product Decisions
This table represents the core PM thinking behind the product. It weighs trade-offs and makes defensible choices.
| Area | Decision | Rationale |
|---|---|---|
| AI & Automation | GPT-4o-mini for Vision | 95% accuracy at ~10x lower cost than GPT-4. Acceptable error rate for human review. |
| Structured prompt engineering | Strict JSON schema enforcement eliminates parsing failures without fine-tuning costs. | |
| Database Architecture | Dual-mode abstraction layer | SQLite for frictionless local dev; PostgreSQL for production. Abstraction auto-converts query syntax. |
| Connection pooling (2-10) | Balanced pool prevents connection exhaustion while staying within Supabase free tier. | |
| Monetization | Flat $69.99/year for 3 servers | Competitive moat vs NeonSportz ($14.99-$34.99/league). Simpler mental model for users. |
| License keys via Discord DM | Zero friction: key arrives where users will activate it. No email verification needed. | |
| User Experience | Discord-native (no external dashboard) | Commissioners don't want another tool. Everything happens where the community already is. |
| Emoji reactions for game status | Single-tap interaction. Visual status at a glance. Familiar Discord pattern. | |
| Infrastructure | Railway for bot, Vercel for site | Right tool for each job. Railway handles long-running Python; Vercel handles serverless API routes. |
| Stripe webhooks for fulfillment | Event-driven ensures no missed payments. Automatic license key generation on successful charge. |
Database Architecture
A critical technical decision: supporting both SQLite (local dev) and PostgreSQL (production) through a unified abstraction layer.
Why This Matters:
- Local dev: Zero setup friction with SQLite. Just run
python -m src.bot - Production: PostgreSQL with connection pooling (2-10 connections) for concurrent Discord servers
- Abstraction: Auto-converts
?placeholders to$1, $2for PostgreSQL
Schema Design
server_settings → Per-guild configuration
cfb_teams/nfl_teams → Team assignments (user_id, team_name, server_id)
cfb_matchups → Matchup data with game status tracking
attribute_points → User balances (available, total_earned)
attribute_requests → Pending upgrades with approval workflow
server_subscriptions → Subscription status, expiration, license keys
command_usage → Analytics (timestamp, execution_time, success/failure)
User Journey & Conversion Funnel
Funnel Stages:
- Awareness: User lands on trilo.gg via Discord community referral
- Consideration: Explores features page, interactive setup guide
- Conversion: Connects Discord, completes Stripe checkout ($69.99/year)
- Fulfillment: Webhook generates license key → DM'd to user
- Activation:
/admin activate TRILO-XXXX-XXXX-XXXXin their server - Retention: Daily bot usage for league operations
Impact & Metrics
| Metric | Before | After | Impact |
|---|---|---|---|
| Weekly admin time reduction | 3+ hours | < 5 minutes | 95% reduction |
| Matchup channel creation | 45-60 minutes | < 1 minute | 98% faster |
| AI schedule extraction accuracy | N/A (manual) | 95% | Enabled automation |
| Discord response latency | N/A | < 3 seconds | Meets Discord API requirement |
| Servers per license | Industry: 1 | 3 servers | Competitive advantage |
| Annual pricing vs competitor | $14.99-34.99/league | $69.99 flat | ~60% savings for multi-league users |
Competitive Analysis
Positioning: Only solution combining AI automation with flat-rate multi-league pricing.
Challenges & Learnings
Challenge 1: SQLite → PostgreSQL Migration
- Problem: Started with SQLite; needed production-grade database
- Solution: Built abstraction layer that auto-converts query syntax
- Learning: Would start with PostgreSQL from day one in future projects
Challenge 2: Discord's 3-Second Interaction Timeout
- Problem: AI operations exceed Discord's response window
- Solution:
interaction.response.defer()for long operations, thenfollowup.send() - Learning: Always design for async-first in chatbot architectures
Challenge 3: License Key Delivery UX
- Problem: Email delivery adds friction; users might not check email
- Solution: Discord OAuth + DM delivery-key arrives where they'll use it
- Learning: Deliver value in the channel where users already are
Challenge 4: Pricing Strategy
- Problem: Per-league pricing is industry standard but punishes power users
- Solution: Flat rate for 3 servers-competitive moat for multi-league commissioners
- Learning: Understand user behavior (2-3 leagues typical) before pricing
What I'd Do Differently
- Start with PostgreSQL: Avoid migration complexity
- Add analytics earlier: No conversion tracking currently. I would add GA/Mixpanel from day one
- User interviews before building: More upfront research on pricing sensitivity
- Build webhook monitoring: Dashboard for Stripe webhook failures
Skills Demonstrated
Defined requirements, prioritized features, made trade-off decisions
Python bot + React site + serverless APIs
Dual-mode abstraction, connection pooling, schema design
OpenAI Vision API, prompt engineering, structured outputs
Stripe integration, webhooks, license key system
Discord-native design, OAuth flow, conversion optimization
Competitive analysis, pricing strategy, value positioning
Links
- Live Site: trilo.gg
- Discord Bot: Invite Link
- Support Server: Join