This is a submission for Weekend Challenge: Passion Edition
What I Built
As I sat there watching the World Cup for the tenth hour in a row, snacks long gone, dignity mostly intact, I thought, why not build a World Cup Wrapped? What is stopping me?
Turns out, nothing, except sleep and a healthy fear of JSON parsing errors.
FanSaga is Spotify Wrapped for football fans.
You pick your team's flag out of a grid of every qualified nation, answer two quick questions about how you experienced the tournament, and the app turns your team's actual real match history into a five slide story where you are the main character.
Somehow a scoreless group stage draw against Curaรงao becomes a defining moment of personal growth. I did not expect to feel something about a spreadsheet of goals and dates, and yet here we are.
At the end you get an animated slide player with music, a shareable recap card, and a whole highlight reel you can export and send to whichever group chat still argues about football at two in the morning.
Demo
Live app
Go pick a flag, answer the two questions, and let Gemini write your saga.
No sign up, no fee, no fine print, just football feelings.
Code
Github Link
Three parts of this build actually mattered. Here is how I did each one.
Turning real stats into a story, not a stat sheet
I did not want Gemini improvising scores, so the whole real match history for the fan's team gets dropped straight into the prompt as JSON, and Gemini is only allowed to write around it.
The last slide is the one doing the heavy lifting, it has to invent a Wrapped style persona from the team's actual run:
Making sure Gemini's JSON never breaks the app
Even with responseMimeType: application/json, Gemini sometimes stops one bracket short of a valid response. Instead of crashing the whole flow over a missing ], I walk the string, track every open bracket in a stack, and quietly close whatever got left open:
for (const ch of text) {
if (ch === '"') inString = !inString
else if (!inString && (ch === '{' || ch === '[')) stack.push(ch)
else if (!inString && ch === '}' && stack.at(-1) === '{') stack.pop()
else if (!inString && ch === ']' && stack.at(-1) === '[') stack.pop()
}
return text + stack.reverse().map((c) => (c === '{' ? '}' : ']')).join('')
The fix was to stop racing React, mount every frame off screen at once, let it all settle, then capture in a separate second pass:
const mounted = nodes.map((node) => mountNode(node))
await settle(mounted)
const gif = GIFEncoder()
for (const { container } of mounted) {
const canvas = await html2canvas(container, { backgroundColor: '#05050a', scale: SCALE })
addFrame(gif, canvas)
}
How I Built It
The app is React and Vite on the front end, styled with Tailwind and animated with Framer Motion so screens actually feel alive instead of just appearing.
Google's Gemini API is the brain of the whole thing.
It reads the real match data for your team and your two short answers, then writes the five slides of your saga, including a Wrapped style fan persona at the end.
That is the Google AI part of this build, and it is doing the most important job in the app.
I originally added ElevenLabs to narrate each saga out loud, and it sounded great, until the free quota ran out mid demo like a narrator fainting on stage.
Instead of fighting a quota bar, I dropped narration and leaned on twelve licensed music tracks across six moods instead. Turns out a good beat covers for a missing voice better than expected.
What You Actually Get
Pick a mood first, stadium, hype, dramatic, fun, chill, or groovy, and a matching background track starts playing behind your saga right away, no narrator needed.
Then your saga plays out as five cards, one at a time, walking through your team's real journey and the moment that hit you hardest, basically a movie trailer for your own fandom.
It ends on one final card with your fan persona and a "Top Percent of Fans" badge, a small bragging right generated just for you, ready to screenshot and send.
For sharing, I kept it simple on purpose.You get a clean image card and an animated GIF highlight reel, both downloadable and both shareable straight from your phone.
No accounts, no video processing on a server, just Gemini writing the story and the browser doing the rest.
Prize Categories
Best Use of Google AI, since Gemini does all the heavy lifting here and I mostly just added emoji and vibes.
Your Saga Awaits
Your team already lived through the whole tournament.
Go find out what kind of fan it made you. ๐ LINK




Top comments (0)