Skip to content

Paliago/lagom-eurovision

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

42 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Lagom Eurovision

A real-time scoring app for watching Eurovision Song Contest with friends.

Create a room, share the name, and rate every contestant across three categories β€” Music, Performance, and Vibes. Scores sync live across devices so you can see exactly how your friends voted and who crowned the winner.

Live at lagomeurovision.com

Third Iteration

The first iteration of the application was done in 2024 to test the capabilities of building applications just relying on AI agents to do the job while incorporating new tech (outside of it's training data). It used Reflect to livesync rooms and was mostly built with Cursor. 2024 Github

The second iteration uses convex and is mostly the same as this third version. That version was built with OpenCode using mostly Claude Sonnet (3.5 I think would be correct for the time).

And now for 2026 I've just cleaned up the repo with GPT 5.5 and Kimi 2.6. Also redesigned it and added haptics and the ability to just add new contestants to allow this to be easily maintainable.

Features

  • Live rooms β€” Join a room with a nickname and vote in real-time. No accounts, no passwords.
  • Three scoring categories β€” Music, Performance, and Vibes on a 1–12 scale. Totals update automatically.
  • Room + global scoreboards β€” See your room's average alongside the global average across all rooms.
  • Per-contestant breakdown β€” View how every individual in your room voted, anonymised with emoji avatars.
  • Swipe navigation β€” Mobile-first design with swipeable contestant cards.
  • Multi-year support β€” Browse and score past contests alongside the current year.
  • Haptic feedback β€” Subtle vibration on taps and interactions when supported.
  • Responsive & dark by default β€” Built for phones during the show, looks good on desktop too.

Tech Stack

Layer Tech
Frontend React 19 Β· Vite Β· TypeScript Β· Tailwind CSS v4 Β· shadcn/ui
Router react-router v7
Backend Convex (real-time database + server functions)
Deployment SST v3 β†’ AWS StaticSite (eu-north-1)
Icons Lucide React
Package Manager Bun

Getting Started

Prerequisites

  • Bun installed
  • A Convex account and the CLI authenticated (npx convex login)

Install & Run

bun install
bun run dev

This starts the Vite frontend and Convex backend in parallel, then opens the Convex dashboard.

Script Purpose
bun run dev Frontend + backend concurrently
bun run dev:frontend Vite dev server only
bun run dev:backend Convex dev server only
bun run build Type-check and production build
bun run preview Preview the production build locally
bun run lint TypeScript + ESLint

Environment Variables

VITE_CONVEX_URL is required at build/dev time. It is already set in .env.local (committed for this repo).

How It Works

  1. Landing page β€” Enter a room name and a nickname. The app creates the room on Convex if it doesn't exist, or joins it if it does.
  2. Contestant list β€” Browse all entries for the selected year. Tap any to open the scoring view.
  3. Scoring view β€” Rate the current act in Music, Performance, and Vibes. Scores save instantly and sync to everyone in the room.
  4. Overview β€” A sortable table showing every contestant's average scores and overall total for the room.

Data Model

  • rooms β€” Stores room name, creation time, and connected users.
  • ratings β€” One document per user + contestant + room combination. Stores the three category scores.

Year Support

The app defaults to the latest contest year (currently 2026). To view or score a previous year, prefix the URL with /{year}/:

Page 2026 (default) 2025
Contestant List /room/:roomName/contestants /2025/room/:roomName/contestants
Rate Contestant /room/:roomName/contestant/:id /2025/room/:roomName/contestant/:id
Overview /room/:roomName/overview /2025/room/:roomName/overview

Once on a year-prefixed route, all navigation preserves the year automatically.

Adding a New Year

Update src/lib/contestants.ts:

  1. Add a new contestants{YYYY} array.
  2. Change DEFAULT_YEAR = {YYYY}.
  3. Add {YYYY} to VALID_YEARS.

No other files need to change β€” routing, lookups, and navigation adapt automatically.

Deployment

The app deploys automatically via SST v3 to an AWS StaticSite in eu-north-1, served at lagomeurovision.com.

# Build locally for production
bun run build

# Deploy with SST
npx sst deploy

Project Structure

src/
  main.tsx          # Convex client init + BrowserRouter
  App.tsx           # Route definitions (year-prefixed and default)
  pages/            # LandingPage, ContestantListPage, ContestantRatingPage, OverviewPage
  lib/              # Contestant data, year parsing, user hooks, haptics
  components/ui/    # shadcn/ui components
convex/
  schema.ts         # Database schema with indexes
  rooms.ts          # Room join/create logic
  ratings.ts        # Submit, query, and aggregate ratings
  _generated/       # Auto-generated Convex types (ignored by ESLint)

Notes

  • No test runner is currently configured.
  • Contestant data is hardcoded in src/lib/contestants.ts, not fetched from an API.
  • User identity is tied to localStorage (eurovisionUserId, eurovisionNickname, eurovisionRoomId). Returning to the same room with the same nickname restores your previous votes.
  • Convex _generated is auto-generated by the dev server. Do not edit manually.

License

MIT

About

Eurovision rating application with multiplayer functionality! πŸ‘¨β€πŸŽ€

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors