Inspiration

Ever finish a game of League and wonder, "What's my real playstyle?" Are you a calculated Grandmaster, a chaotic Glorious Executioner, or an Unbreakable Shield for your team? The scoreboard tells you what happened, but it doesn't tell you who you are on the Rift.

The ranked grind is a story of epic wins and crushing defeats. But how do you turn that chaos into a clear path for growth? How do you understand the core identity behind your clicks, your map movements, and your champion picks?

What it does

Our Solution: Your AI Coach & Chronicler Introducing League MBTI Analytics. We go beyond KDA and win rates to tell the story of your unique journey. Using powerful analysis, we map your in-game decisions, tendencies, and triumphs to a personalized, MBTI-like gameplay archetype. We don't just show you stats; we reveal your legend.

League-MBTI-Analysis is a web application that analyzes League of Legends player behavior and maps gameplay patterns to MBTI personality types. Users enter their Riot ID (e.g., "Faker#KR1"), and the app:

  1. Fetches Match Data: Retrieves up to 100 ranked matches from 2025 using the Riot API
  2. Analyzes Playstyle: Processes KDA, damage, vision score, champion diversity, and teamfight participation
  3. Maps to MBTI: Calculates scores across 8 dimensions (E/I, S/N, T/F, J/P) to determine personality type
  4. Visualizes Insights: Displays performance charts, growth trends, and queue breakdowns (Ranked vs. Casual)
  5. Generates Narratives: Provides AI-powered insights about playstyle evolution and strengths

The app distinguishes between team-oriented players (high assists = Extroverted) and solo carries (high kills = Introverted), cautious strategists (low deaths = Sensing) and aggressive risk-takers (high volatility = Intuitive), and more.

How we built it

Frontend: React 19 + TypeScript + Vite + Tailwind CSS

  • Modern, responsive UI with League of Legends-themed styling
  • Recharts for data visualization (growth charts, performance metrics)
  • Multi-page flow: Landing → Loading → Results

Backend: Cloudflare Pages Functions (Edge Functions)

  • Serverless API proxy (functions/api/riot/[[path]].ts) to keep Riot API keys secure
  • Intelligent regional routing based on player tags (Americas, Europe, Asia, SEA)
  • CORS handling for cross-origin requests

Data Processing Pipeline:

  1. riotApiService.ts: Fetches PUUID, match IDs, and match details with pagination
  2. dataFilterService.ts: Filters matches (removes remakes, validates gameType/queueId)
  3. incrementalDataService.ts: Aggregates stats (win rates, KDA, damage per minute)
  4. mbtiMappingService.ts: Calculates MBTI scores from gameplay metrics
  5. mbtiAnalysisFlow.ts: Orchestrates the full analysis pipeline

Caching Strategy (Multi-layer):

  • Memory Cache: In-browser Map for same-session queries
  • IndexedDB: Persistent browser storage (7-day TTL for PUUID, 30-day for match details)
  • Future: Cloudflare KV for cross-user cache sharing

Rate Limiting: Custom rate limiter (p-limit) to respect Riot API limits (20 req/s, 100 req/2min)

Key Technical Decisions:

  • Client-side caching to reduce API calls (match details never change)
  • Parallel fetching of match details using Promise.all
  • Queue ID filtering (420 = Ranked Solo/Duo, 440 = Flex, etc.)
  • Data compression: 150 fields/match → 20 filtered fields → 8 MBTI dimensions → 4-letter type

Challenges we ran into

  1. AWS Bedrock Integration: Setting up Bedrock Runtime API with proper IAM permissions and region configuration. We solved this by:

    • Creating IAM role with bedrock:InvokeModel permission
    • Configuring AWS SDK v3 (@aws-sdk/client-bedrock-runtime)
    • Using us-east-1 region for Titan model availability
  2. Cost Optimization: Bedrock API calls can be expensive at scale. We implemented:

    • DynamoDB caching (24h TTL) to avoid redundant calls
    • Token limits (max 200 tokens) to control costs
    • Batch processing (single call per player analysis)
    • Model selection (Titan Express vs Claude Haiku) based on use case
  3. Rate Limiting: Riot API has strict limits (20 req/s dev key). We implemented:

    • Multi-layer caching (memory + IndexedDB)
    • Batch processing with p-limit
    • Client-side caching for immutable data (match details)
  4. Data Complexity: Each match has 150+ fields per participant. We built a filtering pipeline that extracts only relevant metrics (KDA, damage, vision, gold) and validates game types/queue IDs.

  5. MBTI Mapping Logic: Translating gameplay to personality types required careful calibration. We tested different thresholds (e.g., assists > kills = Extroverted) and balanced multiple signals to avoid false positives.

  6. CORS & API Key Security: We couldn't call Riot API directly from the browser (CORS + exposed keys). We built a Cloudflare Pages Function as a secure proxy that handles authentication server-side.

Accomplishments that we're proud of

  1. Efficient Data Pipeline: Reduced data from 150 fields/match to 8 MBTI dimensions (99.5% reduction) while preserving meaningful insights.

  2. Smart Caching: Implemented multi-layer caching that reduces API calls by ~80% for repeat queries, improving performance and staying within rate limits.

  3. Beautiful UI: Created a League of Legends-themed interface with gradient text, backdrop blur effects, and responsive charts that make data exploration engaging.

  4. Robust Error Handling: Graceful handling of missing players, invalid tags, network errors, and API rate limits with user-friendly error messages.

  5. Type Safety: Full TypeScript coverage with comprehensive types for Riot API responses, ensuring reliability and better developer experience.

  6. Regional Routing: Intelligent region detection from player tags, automatically routing to correct Riot API regional endpoints.

  7. Queue Analysis: Separate analysis for Ranked (420, 440) vs. Casual (400, 430, 450) games, providing nuanced insights into different playstyles.

What we learned

  1. API Design Matters: Riot API's regional routing and rate limits taught us to design for constraints early. Caching became essential, not optional.

  2. Data Compression: Not all data is equal. Filtering irrelevant fields (like participantId) before processing saves memory and improves performance.

  3. Edge Functions: Cloudflare Pages Functions are powerful for API proxying. They provide low latency, automatic scaling, and serverless simplicity.

  4. MBTI Mapping: Translating quantitative gameplay data into qualitative personality traits requires domain knowledge and iterative testing. Our mapping evolved as we analyzed more players.

  5. Client-Side Caching: IndexedDB is underrated. Persisting API responses client-side reduces server load and improves UX, especially for immutable data like match history.

  6. TypeScript Benefits: Strong typing caught many bugs early, especially with complex nested API responses. The investment in type definitions paid off.

What's next for League-MBTI-Analysis

  1. Cloudflare KV Caching: Add server-side caching so multiple users analyzing the same player share cached data, reducing API calls globally.

  2. Timeline Analysis: Analyze match timelines for "milestone moments" (epic comebacks, perfect games) to add narrative depth.

  3. Comparative Analysis: Compare players' MBTI types and playstyles, showing compatibility or complementary strengths.

  4. Historical Trends: Track MBTI evolution over time (monthly/seasonal) to show how playstyles change.

  5. Shareable Cards: Generate beautiful, shareable summary cards (like Spotify Wrapped) that players can post on social media.

  6. Champion Recommendations: Suggest champions that match a player's MBTI type for optimal performance.

  7. Performance Optimization: Increase match count to 100+ per analysis for more accurate MBTI mapping.

Built With

Share this project:

Updates