🎯 Trivista: Your Vista to Trivia

A multiplayer trivia experience powered by AI, built with RevenueCat, and vibe-coded with Claude Code


💡 Inspiration

Regular trivia nights with my wife and friends sparked the idea for Trivista. We loved the social connection and friendly competition, but coordinating schedules was always a challenge. I wanted to build an app that could recreate that same engaging experience—whether playing together in real-time or asynchronously on our own schedules, on any topic we could imagine.

I was also fascinated by the potential of context-aware AI image generation. The idea that each quiz could be unique, with custom-generated images that perfectly matched the questions, felt like the perfect blend of technology and creativity.


✨ What It Does

Trivista is a multiplayer trivia app that offers:

  • Dual Content System:
    • AI-generated quizzes on any topic with real-time generation using Perplexity Sonar
    • Curated question library from OpenTriviaDB with high-quality vetted content
    • Both types feature context-aware images generated with fal.ai Flux
  • Social Features: Friends system with invites, friend requests, and private challenges
  • Flexible Multiplayer: Real-time competitions or asynchronous play—challenge friends on your schedule
  • Party Mode: Local WiFi auto-discovery (mDNS/Bonjour) for friction-free multiplayer sessions on the same network
  • Diverse Content: Multiple categories (Science, History, Geography, Sports, Entertainment, etc.) with varying difficulty levels
  • Custom Challenges: Create and share custom quizzes with friends
  • Quality Control: Community-powered content reporting system to maintain high-quality questions
  • Premium Experience: RevenueCat-powered subscriptions unlock unlimited AI quizzes and remove ads

🛠️ How I Built It

Development Approach: Spec-Driven Vibe Coding with Claude Code

Trivista was built through a disciplined spec-driven vibe coding approach with Claude Code—combining detailed specifications with conversational implementation.

My Process

1. Start with a Spec Having built apps before, I knew exactly what architecture I wanted. I would work with Claude Code to generate and refine detailed specifications through iterative prompting until 100% satisfied with the spec.

2. Use Plan Mode Religiously For every feature, I used Claude Code's plan mode to review the implementation approach before execution:

  • Claude Code would read the spec and propose an implementation plan
  • I'd review, refine, and approve the plan
  • Only then would execution begin

3. Feature-Level Iteration As I honed in on specific features, I'd spec out the details and iterate with Claude Code until completely satisfied:

Spec → Plan → Review → Refine → Execute → Test → Iterate

4. Leverage My App Architecture Knowledge I provided very specific guidance on:

  • Flutter app architecture patterns
  • Firebase Cloud Functions structure and best practices
  • Security rules architecture from my previous experience
  • State management patterns for real-time multiplayer
  • RevenueCat integration—having used it before, it was a no-brainer choice

What Claude Code Handled:

  1. 🔍 Research the codebase to understand existing patterns
  2. ⚡ Implement features following my architectural specifications
  3. 🛡️ Handle edge cases and error states based on my requirements
  4. 📝 Write idiomatic code for each platform (Dart for Flutter, TypeScript for Cloud Functions, React for web)

This approach let me focus on the product vision, architecture decisions, and user experience while Claude Code handled the tedious implementation details. The combination of my domain expertise + detailed specs + Claude Code's execution speed created a powerful workflow.


🧰 Custom Developer Tooling

To optimize the spec-driven workflow with Claude Code, I built flutter-auto-reload—a suite of CLI tools that bring automatic hot reload to Flutter development without needing an IDE.

Key features:

  • 🔥 Automatic file watching: Monitors .dart files and triggers hot reload via SIGUSR1
  • 📦 Smart reload detection: Watches pubspec.yaml changes and triggers hot restart via SIGUSR2
  • 🔄 Multi-device support: Works with multiple connected devices simultaneously
  • Lightweight: Uses Flutter's built-in signal mechanism for minimal overhead
  • 🖥️ Terminal-first: Perfect for terminal workflows and AI coding assistants

The Multi-Device Advantage:

Since we were targeting both phone and tablet form factors on iOS and Android from the outset, I regularly ran the app simultaneously on multiple devices using the CLI tool—iOS phone, iOS tablet, Android phone, and Android tablet. Every change Claude Code made would automatically reload on all screens in real-time.

This saved enormous amounts of time—no switching devices, no manual rebuilds, no context switching. I could see responsive layout issues and platform-specific differences instantly.

Read more about the implementation in my article: Flutter Auto-Reload CLI Tools.


📚 Tech Stack

Layer Technologies
Mobile Flutter, Dart, Firebase Auth, Firestore, AdMob, RevenueCat SDK
Web Next.js 15, React 19, TypeScript, Tailwind CSS, Server-Side Rendering
Content Perplexity Sonar (AI generation), OpenTriviaDB (curated), fal.ai Flux (images)
Backend Firebase Cloud Functions, Firestore, Cloud Storage, Cloud Scheduler
Security Firebase App Check, Rate Limiting, Firestore Security Rules, Content Safety
DevOps GitHub Actions, Fastlane, Firebase Hosting
Dev Tools Custom Flutter auto-reload CLI

Mobile App (Flutter)

  • Cross-platform iOS/Android app built with Flutter and Dart
  • Firebase backend (Firestore, Cloud Functions, Authentication)
  • Multiple authentication methods: Google Sign-In, Apple Sign-In (on Apple devices), and passwordless email link auth
  • Firebase App Check for bot protection and abuse prevention
  • Custom rate limiting
  • AdMob integration for monetization
  • RevenueCat SDK for subscription management

Web Platform (Next.js)

  • Marketing site and web app at trivista.ai
  • Social sharing of quizzes and results with deep linking for seamless app handoff
  • Friend invites system
  • Built with Next.js 15, React 19, and TypeScript
  • Tailwind CSS for styling
  • Server-side rendering for optimal performance

Content Pipeline

  • AI-Generated Content:
    • Perplexity Sonar for intelligent quiz generation—always accurate, current, and fast
    • Real-time generation with inline image creation
    • Custom prompts to ensure educational, safe content
  • Curated Content:
    • Curated question library from OpenTriviaDB (asynchronously integrated)
    • Admin panel for importing and managing curated questions
  • Image Generation:
    • fal.ai Flux for context-aware image generation
    • Real-time generation for AI quizzes
    • Scheduled batch processing for curated content

Infrastructure

  • Firebase Cloud Functions for serverless backend
  • Firestore for real-time data synchronization
  • Cloud Storage for image hosting
  • GitHub Actions for CI/CD
  • Fastlane for iOS and Android deployment automation and metadata management

🔒 Security Architecture

Building a real-time multiplayer app with AI features required robust security from day one. As detailed in my article Flutter Real-Time Multiplayer with Firebase, Trivista implements defense-in-depth security:

1. Firebase App Check

First line of defense against backend abuse and unauthorized access.

  • ✅ Enforced from early development (not just production)
  • ✅ Debug tokens for development environments
  • ✅ Protects all Firebase services (Cloud Functions, Firestore, Storage)

2. Multi-Layer Rate Limiting

Dual-tracking system to prevent abuse while maintaining good UX:

  • 📊 User ID tracking: Authenticated users have per-user limits
  • 🌐 Hashed IP tracking: Graceful degradation for shared networks
  • ⏱️ Configurable windows: Different limits for different operations
  • 💾 Firestore-based: Atomic transactions prevent race conditions

3. Firestore Security Rules & Data Design

Never trust the client - fundamental principle enforced through comprehensive security rules:

Key security patterns:

  • 🔐 User data isolation (users can only read their own data)
  • 🚫 Privacy-preserving blocks (userBlocks collection hidden from clients, enforced server-side)
  • 🎮 Game access controls (public/private/friends visibility with participant checks)
  • ✍️ Server-side mutations (all writes through Cloud Functions, except quiz answers which use real-time listeners for speed)
  • 🔍 Field-level validation (restrict which fields clients can modify)

Data design philosophy:

  • 📦 Aggressive denormalization for read performance (friends data, user lists embedded in documents)
  • ⚡ Real-time listeners optimized to minimize reads (single document subscriptions vs collection queries)
  • 🎯 Strategic data duplication to avoid expensive joins (usernames, avatars cached in quiz documents)

4. Content Safety & Moderation

All user-generated content is validated for safety:

// Username validation with profanity filter
export function validateUsername(username: string): {
  isValid: boolean;
  error?: string;
} {
  // Check format, profanity, leetspeak, reserved names, impersonation
  const inappropriateCheck = containsInappropriateContent(normalized);
  if (inappropriateCheck.isInappropriate) {
    return { isValid: false, error: inappropriateCheck.reason };
  }
  return { isValid: true };
}

// AI topic validation with two-tier context-aware system
const validation = validateTopic(topic);
if (validation.isNSFW) {
  throw new Error(`${validation.reason}. Please choose an appropriate topic.`);
}

// AI-generated content safety through prompts
const prompt = `CRITICAL SAFETY CHECK:
1. ALWAYS REJECT: sexual content, self-harm, drugs, terrorism
2. ALLOWED: entertainment, history, sports (educational context)
If inappropriate, return: {"success": false, "error": "Violates policy"}`;

Multi-layer content safety:

  • 🚫 Username filtering: Profanity, leetspeak, impersonation detection
  • 🎯 Context-aware topic validation: Two-tier system (always block vs. context-sensitive)
  • 🤖 AI safety instructions: Explicit prompts to reject inappropriate content
  • 🖼️ Image NSFW filter: fal.ai safety checker at maximum strictness
  • 📝 Post-generation validation: Final check on questions and answers
  • 🚨 Community reporting: User flagging with admin review dashboard

For a deep dive into the implementation, check out my article: Flutter Real-Time Multiplayer with Firebase.


🚧 Challenges I Faced

1. Speed: Real-Time AI Quiz Generation Under 30 Seconds

Problem: Users expect instant results when creating AI quizzes. The system needs to:

  1. Validate topic for safety (pre-check)
  2. Generate questions using Perplexity Sonar (which queries up-to-date web information for accuracy)
  3. Validate generated content for safety (post-check)
  4. Generate up to 20 contextual images with fal.ai Flux
  5. Return complete quiz to user in under 30 seconds

Solution: Aggressive optimization and parallelization at every step:

Speed Optimizations

1. Pre-validation Before Expensive Operations

// Check topic safety BEFORE calling Perplexity (saves $$ and time)
const validation = validateTopic(topic);
if (validation.isNSFW) {
  throw new Error(`${validation.reason}`); // Fail fast, no API calls
}

2. Parallel Image Generation

// Process 10 images at a time instead of sequentially
const BATCH_SIZE = 10;
for (let i = 0; i < questions.length; i += BATCH_SIZE) {
  const batch = questions.slice(i, i + BATCH_SIZE);

  // All images in batch generated in parallel
  const batchResults = await Promise.all(
    batch.map(q => generateAndStoreImage(...))
  );

  quizQuestions.push(...batchResults);
}

3. Fast Flux Model (Schnell)

// Use Flux Schnell: only 4 inference steps vs 28 for Dev model
const isSchnell = model?.includes('schnell');
const result = await fal.run('fal-ai/flux/schnell', {
  input: {
    num_inference_steps: isSchnell ? 4 : 28,  // 7x faster!
    guidance_scale: 3.6,
    sync_mode: true  // Direct execution, no polling
  }
});

4. Perplexity Sonar for Web-Verified Content

// Sonar queries real-time web sources for accurate, up-to-date facts
const response = await fetch('https://api.perplexity.ai/chat/completions', {
  body: JSON.stringify({
    model: 'llama-3.1-sonar-large-128k-online',  // Online model
    messages: [{ role: 'user', content: quizPrompt }],
  }),
});
// Returns questions with source citations for fact-checking

5. Increased Cloud Function Resources

export const httpCreateAIQuiz = onCall({
  memory: '1GiB',          // More memory for parallel processing
  timeoutSeconds: 300,     // 5 minutes max
  maxInstances: 10,        // Scale to handle concurrent users
  secrets: ['PERPLEXITY_API_KEY', 'FAL_API_KEY']
}, async (request) => { ... });

Results:

  • Average generation time: ~7 seconds for 10-question quiz with images
  • 📊 Breakdown:
    • Question generation (Perplexity): ~6 seconds
    • Image generation and storage (10 images in parallel): ~1 second
  • 🎯 Success rate: 95%+ within 30 seconds

2. Managing Multiple Content Sources

Problem: The app needed both AI-generated and curated content. Curated questions came from OpenTriviaDB (with rate limits) and required images to be generated, but unlike AI quizzes, these didn't need real-time generation.

Solution: Built a dual content system:

Curated Content Pipeline

  • OpenTriviaDB integration for high-quality curated questions across multiple categories
  • Rate limit handling for external API with proper error handling and retry logic
  • Admin interface to import and manage curated questions
  • Firestore-based question storage with questions organized by category
  • Automatic deduplication using question content hashing

Asynchronous Image Generation Queue

Since curated questions don't need instant images, implemented a scheduled background processing system using Firestore triggers and Cloud Scheduler. This allows using higher-quality Flux models without time or cost constraints.

Benefits:

  • Higher quality: Can use better models since speed isn't critical
  • Cost-effective: Spreads image generation over time instead of expensive bursts
  • Reliable: Failed generations moved to failedImageQueue for review
  • Non-blocking: Curated quizzes work without images, images added later
  • Automatic: Triggers when admins add new questions via admin panel

3. Real-Time Multiplayer Synchronization

Problem: Keeping quiz state synchronized across multiple players in real-time was complex, especially handling edge cases like players joining mid-game or network interruptions.

Solution: Leveraged Firestore's real-time listeners with careful transaction management and optimistic updates. Implemented a state machine to handle all possible game states:

// Real-time game state synchronization
_gameSubscription = FirebaseFirestore.instance
  .collection('games')
  .doc(gameId)
  .snapshots()
  .listen((snapshot) {
    final newState = GameState.fromFirestore(snapshot);
    _updateGameState(newState);
  });

4. Security Without Friction

Problem: Implementing comprehensive security (App Check, rate limiting, Firestore rules) without degrading user experience or blocking legitimate users.

Solution: Multi-layer approach with graceful degradation:

  • App Check with debug tokens for development
  • Dual-tracking rate limits (user ID + hashed IP)
  • Smart retry logic for transient failures
  • Clear error messages when limits are hit

This architecture is detailed in my article: Flutter Real-Time Multiplayer with Firebase.


5. RevenueCat Integration & Subscription Flow

Problem: Getting the subscription flow right across multiple entry points (onboarding, settings, premium features) while handling edge cases like purchase restoration and subscription status changes required careful coordination. Server-side verification of entitlements was critical.

Solution: Having worked with RevenueCat before, it was a no-brainer choice for handling subscriptions. As always, it performed flawlessly with zero friction.

Architecture:

  • Client SDK (RevenueCatService) - Handles purchases and provides immediate feedback
  • Webhook Handler - Syncs RevenueCat events (purchases, renewals, cancellations) to Firestore in real-time
  • Server Enforcement - Fetches subscription status via RevenueCat REST API on every login to verify entitlements
class RevenueCatService extends Component {
  CustomerInfo? _customerInfo;

  Future<bool> purchasePackage(Package package) async {
    try {
      final result = await Purchases.purchasePackage(package);
      _customerInfo = result.customerInfo;
      return true;
    } catch (e) {
      // Handle purchase errors
      return false;
    }
  }

  // Prioritize server-side truth over client SDK
  bool hasActiveSubscription(UserData? user) {
    if (user != null) {
      return user.hasEffectiveSubscription; // Server truth
    }
    // Fallback to client SDK
    return _customerInfo?.entitlements.active['premium']?.isActive ?? false;
  }
}

The webhook ensures Firestore stays in sync with RevenueCat, while server enforcement via REST API prevents client manipulation. This defense-in-depth approach means entitlements are always verified server-side.

RevenueCat handled all the complexity: cross-platform purchase validation, subscription status synchronization, receipt validation, entitlement management, and webhook delivery. The SDK just works—exactly what you need when building fast.


6. Cross-Platform Consistency

Problem: Building simultaneously for iOS and Android across both phone and tablet form factors (including landscape and portrait tablet orientations) required ensuring consistent UX while respecting platform conventions.

Solution: Built a comprehensive design system with platform-adaptive widgets in Flutter. Using the custom auto-reload tooling, I could run all variants simultaneously (iOS phone, iOS tablet, Android phone, Android tablet) and see every change instantly across all screens. This made maintaining feature parity and responsive layouts effortless.


📖 What I Learned

About Development

1. Specs + Plan Mode = Speed with Control: Detailed specs and plan mode ensured Claude Code built exactly what I wanted. The discipline of spec → plan → review → execute prevented costly mistakes while maintaining rapid iteration.

2. AI as Co-Pilot, Not Autopilot: Claude Code handled implementation brilliantly, but architectural decisions, product vision, and UX came from me. When blocked, switching to other tools like Codex for a fresh perspective helped unblock issues.

3. Experience Multiplies AI Effectiveness: Prior app development experience meant I could specify "use Provider for state management" or "implement with Firestore transactions" and Claude Code would execute perfectly.

4. Custom Tooling Multiplies Productivity: Building flutter-auto-reload created 10x iteration speed. Running on phone and tablet simultaneously with instant reload eliminated device switching.

About the Tech

5. Perplexity Sonar for Factual Content: Online models ensured quiz questions were accurate and up-to-date

6. fal.ai Flux Schnell for Speed: 4 inference steps vs 28 made real-time image generation viable and cost-effective

7. Aggressive Parallelization Required: Batching image generation, pre-validation, and increased Cloud Function resources enabled sub-30-second generation

8. RevenueCat Just Works: Handled subscriptions, entitlements, and cross-platform purchases with zero friction

9. Security Built In, Not Bolted On: App Check, rate limiting, and Firestore rules from day one prevented abuse. See: Flutter Real-Time Multiplayer with Firebase

10. Async Processing Reduces Costs: Scheduled Cloud Functions for curated content images spread costs over time

About the Product

11. Dual Content Strategy: AI generation provides infinite variety; curated content ensures quality. Users appreciate both options.

12. Community Features Drive Engagement: Custom quizzes and friend challenges created significantly more engagement than solo play

13. Context-Aware Moderation Works: Simple keyword blocking would flag "Game of Thrones violence" as inappropriate. Context-aware filtering allows educational/entertainment content while blocking truly inappropriate topics

14. Speed Is a Feature: Sub-10-second generation for a complete 10-question quiz made the difference between delight and frustration


🚀 What's Next

  • 🎯 Leaderboards & Achievements: Global and friend-based competition tracking with Game Center and Google Play Games integration
  • 🏆 Tournament Mode: Bracket-style competitions with elimination rounds
  • 🎤 Voice Questions: Audio-based trivia for accessibility and variety
  • 👥 Team Play: Cooperative multiplayer modes
  • 📊 Analytics Dashboard: Personal stats and performance insights for premium users
  • 🎨 Custom Image Styles: Experimenting with different Flux LoRAs for specialized quiz aesthetics (e.g., comic book style, pixel art, photorealistic)
  • 🏢 B2B Features: White-label quiz platform for corporate training, education, and events

🎓 Key Takeaway

Building Trivista demonstrated that modern AI tools like Claude Code fundamentally change how we can build software. I built this entire app solo—no PM, no UX designer, no team. What would traditionally require 3-4 people (developer, designer, PM, QA) was accomplished by one person leveraging AI tools effectively.

By combining my architectural expertise with detailed specs and Claude Code's execution speed, I shipped a complete cross-platform app with sophisticated AI features, real-time multiplayer, and robust monetization—all in a fraction of the time traditional development would require.

The combination of:

  • 📋 Detailed specs + plan mode for architectural control
  • Claude Code for execution speed
  • 🛠️ Custom dev tooling (flutter-auto-reload)
  • 🤖 Intelligent AI services (Perplexity Sonar, fal.ai)
  • 💳 Streamlined monetization (RevenueCat)
  • 🔒 Defense-in-depth security (App Check, rate limiting, Firestore rules)
  • 🧠 Prior app development experience for architectural decisions

...represents a new paradigm for indie development. Experienced developers can now build ambitious products solo that would have required entire teams just a few years ago.


Try Trivista: trivista.ai | Download on App Store & Google Play

Read More:

Built With

  • admob
  • app-check
  • authentication
  • cloud-functions
  • cloud-scheduler)
  • cloud-storage
  • fal.ai-flux-api
  • fastlane
  • firebase-(firestore
  • flutter-(dart)
  • github-actions
  • next.js-(react-19
  • opentriviadb
  • perplexity-sonar-api
  • revenuecat
  • typescript)
Share this project:

Updates