AI or Real? — Can You Tell The Difference?
Inspiration
At every esports event, there's a moment when fans are waiting in line, buzzing with energy but with nothing to do. We wanted to create something that captures that competitive spirit and turns it into a fast, shareable experience. With AI-generated images becoming increasingly realistic, we thought: what if we turned that into a game? Can you actually tell the difference between an AI-generated portrait and a real photograph — in just 2 seconds?
That's how AI or Real? was born. A simple concept with a surprising amount of depth — and perfect for a Cloud9 & JetBrains event booth where fans can compete, flex their perception skills, and see their name on the live leaderboard.
What It Does
AI or Real? is a browser-based mini-game where players are shown 12 portrait images — a mix of AI-generated and real photographs — and must decide which is which. The catch? You only have 2 seconds per image.
Full Game Flow
- Register — Enter your name and optionally select your country (searchable dropdown with 200+ countries and flags)
- Asset Loading — All 12 images are preloaded into the browser so there's zero lag during gameplay
- Countdown — A dramatic 3-2-1 countdown with sound effects builds anticipation
- Gameplay — 12 rounds of rapid-fire decisions. For each image:
- A portrait is displayed with a tactical HUD overlay and scan-line animation
- A color-coded timer bar counts down from 2 seconds (cyan → yellow → red)
- Click AI Generated or Real Photo (or use keyboard shortcuts: A/1/← for AI, R/2/→ for Real)
- Instant feedback shows if you were correct or wrong
- Game Over — A holographic trading card displays your results:
- Final score with grade badge (S+, S, A, B, or C)
- Global rank among all players
- Accuracy percentage, average response time, and best streak
- Round-by-round result strip (green/red indicators)
- QR code linking back to the game
- Post-Game Actions:
- Take a Selfie — Use your device camera with a mirror-mode viewfinder and crosshair overlay
- Save Card — Download your personalized result card as a JPEG
- Upload to Gallery — Share your card to the public Wall of Fame
- Copy Link — Share the game URL with friends
- Play Again — Clears the form for the next player (designed for event use with many players)
Scoring System
The scoring rewards both speed and consistency:
- Base Points: 100 per correct answer
- Speed Bonus: Up to 100 extra points based on how quickly you answer (faster = more)
- Streak Multiplier: Consecutive correct answers multiply your score (1x → 1.25x → 1.5x → ... up to 3.75x for a perfect 12/12 streak)
- Wrong/Timeout: 0 points, streak resets
A perfect game with instant answers can score around 5,700 points. Average players typically score 600-1,200.
Live Pages
- Leaderboard — Top 50 players displayed in real-time, auto-refreshes every 5 seconds. Features a podium for the top 3 players with gold/silver/bronze styling, country flags, and highlight animations when new scores appear. Perfect for displaying on a screen at an event booth.
- Wall of Fame (Gallery) — A 4-column masonry grid of uploaded player cards with grade badges, player avatars, and stats. Click any card to view it full-size in a modal. Auto-refreshes every 30 seconds.
How We Built It
Development Environment
The entire project was built using JetBrains WebStorm with Junie (JetBrains AI Coding Agent). Before writing any code, we documented the full game concept, hackathon requirements, image descriptions, and technology choices in an idea/ folder. This structured approach gave Junie clear context to assist with:
- Designing the database schema (5 models: GameImage, Player, Score, Country, GalleryItem)
- Building the Next.js application architecture with App Router
- Creating the tactical esports-themed UI with VALORANT/LoL visual language
- Implementing the game state machine (register → loading → countdown → playing → feedback → gameover)
- Writing the scoring algorithm with speed bonus and streak multiplier mechanics
Tech Stack
| Layer | Technology | Why |
|---|---|---|
| Framework | Next.js 16 (App Router) | Full-stack React with server-side API routes |
| Language | TypeScript | Type safety across the entire codebase |
| Styling | Tailwind CSS 4 | Rapid UI development with utility classes |
| Animations | Framer Motion (LazyMotion) | Smooth, performant animations with tree-shaking |
| Database | PostgreSQL (Aiven Cloud) | Reliable cloud-hosted relational database |
| ORM | Prisma v6 | Type-safe database queries and schema management |
| Image Storage | AWS S3 | Scalable storage for game images and uploaded player cards |
| Card Export | html-to-image | Convert the result card DOM to a downloadable JPEG |
| Deployment | Vercel | Zero-config deployment with edge functions |
Architecture Highlights
- Server-side caching on all API routes (images, leaderboard, countries) to minimize database load during high-traffic event use
- Parallel database queries with
Promise.allfor faster API response times - Non-blocking audio preload — sound effects load in the background while only images block the loading screen
- Client-side image shuffle for additional randomization on top of the server-side random selection
- Responsive design using
dvhviewport units and dynamic sizing — works on phones, tablets, laptops, and event booth displays - Event-optimized flow — Play Again clears all form fields and localStorage so the next player at the booth starts fresh
Design Philosophy
The UI draws heavy inspiration from VALORANT and League of Legends competitive interfaces:
- Dark tactical background with scan-line overlays and hex patterns
- Signature red (
#ff4655) and cyan (#00eeff) color scheme - Clipped corners (
clip-path) for a tactical/angular aesthetic - Animated corner accents, glowing borders, and shimmer effects
- Sound design with distinct audio cues for clicks, correct/wrong answers, streaks, countdowns, and game over
Challenges We Ran Into
Mobile viewport handling — The
100vhunit doesn't account for browser chrome on mobile devices, causing content to overflow. We switched todvh(dynamic viewport height) units and usedoverflow-hiddenwith dynamicmax-hconstraints to ensure the game fits perfectly on any screen size.Audio preloading reliability — The
oncanplaythroughevent is unreliable across browsers and can hang indefinitely on slow connections. We solved this by making audio preloading non-blocking (fire-and-forget) while only waiting for images, which are the critical assets.Country dropdown performance — With 200+ countries, rendering animated Framer Motion components for each row caused significant jank. We replaced animated
m.buttonelements with plainbuttonelements and used emoji flags from the database instead of importing a heavy SVG flag library.Leaderboard polling performance — Auto-refreshing every 5 seconds was hammering the database. We added server-side in-memory caching with a 3-second TTL, fixed a React dependency loop that was causing unnecessary re-fetches, and added browser cache headers.
Scoring balance for 2-second timer — The original 5-second timer was too slow for event use. When we shortened it to 2 seconds, the scoring formula and timer color thresholds needed recalibration. Speed bonus now scales relative to
TIME_PER_IMAGE, and the timer turns yellow at 1.2s and red at 0.6s.
Accomplishments That We're Proud Of
- Under 30 seconds per game session — Players can complete a full 12-round game in under a minute including results, making it perfect for high-traffic event booths
- The trading card system — Players genuinely want to save and share their result cards. The selfie integration, holographic shimmer, and grade badges make it feel like collecting a real trading card
- Live leaderboard driving competition — At testing events, displaying the leaderboard on a screen created immediate competitive energy, with players trying to beat each other's scores
- Fully responsive across all devices — The same game works seamlessly on a phone in someone's hand, a tablet at a booth, or a laptop/desktop display
- Zero-friction player experience — No login, no signup, no tutorial. Enter your name and start playing in 3 seconds
What We Learned
dvhunits are essential for mobile web games —vhis fundamentally broken on mobile browsers with dynamic toolbars.dvhsolves this completely.- Framer Motion's
LazyMotionwithdomAnimationsignificantly reduces bundle size compared to importing the full motion library - In-memory server caching is a simple but highly effective optimization for read-heavy API routes, especially when data changes infrequently
- Structuring project requirements before development (in the
idea/folder) made Junie dramatically more effective as a coding assistant — clear context leads to better AI-assisted output - Event-oriented design decisions (clearing forms, fast timers, live leaderboards) require different thinking than consumer app design
What's Next for AI or Real?
- More image categories — Expand beyond portraits to landscapes, animals, food, and art
- Difficulty levels — Easy (5s), Normal (3s), Hard (2s), Insane (1s) timer options
- Tournament mode — Bracket-style competitions for organized events
- Image pool expansion — Continuously add new AI and real images to keep the game fresh
- Analytics dashboard — Track which images fool players the most and adjust difficulty
Built With
- jetbrains
- junie
- next.js
- postgresql
- prisma
- s3
- tailwind
- vercel
- webstorm


Log in or sign up for Devpost to join the conversation.