A playful rivalry tracker for couples who take their ping pong way too seriously.
Track matches. Talk trash. Raise the stakes. Unlock achievements.
Ping Pong Rivals is a fun pet project built for me and my partner to track our head-to-head ping pong battles. What started as a casual game has turned into a full-blown rivalry -- complete with trash talk, playful bets, and bragging rights.
No backend. No accounts. Just pure, local, competitive fun stored in your browser.
The home screen shows the head-to-head scoreboard at a glance -- who's leading, active win streaks, and dynamic trash talk that evolves with your rivalry. Recent matches are displayed with scores and dates.
Log matches with a clean score input (first to 10 wins). The winner is highlighted with a glowing accent as you adjust scores. After logging, you get a victory screen with trophy animation and any newly unlocked achievements.
Raise the stakes with the built-in bet generator. Choose your intensity level:
| Level | Vibe | Examples |
|---|---|---|
| Chill | Low-key fun | Make tea, do the washing up, give up the good couch spot |
| Spicy | Medium heat | Cook dinner, give a massage, plan date night |
| FIRE | Maximum chaos | TikTok dance of winner's choice, dramatic love poem reading, week of pampering |
Don't like the generated bet? Re-roll or write your own custom bet.
Deep-dive into your rivalry with comprehensive statistics:
- Win rate and win/loss records
- Current and best win streaks
- Clean sweeps (10-0 victories) and nail biters (10-9 thrillers)
- Average victory margin
- Visual head-to-head bar showing the win percentage split
- Rivalry numbers -- total matches played, total points scored, and bets made
Unlock 14 unique achievements across both players (28 total). Unlocked achievements glow gold, while locked ones stay dimmed with a padlock:
| Achievement | How to Unlock |
|---|---|
| First Blood | Win your first match |
| High Five | Win 5 matches |
| Perfect Ten | Win 10 matches |
| Quarter Century | Win 25 matches |
| Clean Sweep | Win a match 10-0 |
| Total Domination | Win 5 matches 10-0 |
| Three-Peat | Win 3 matches in a row |
| On Fire | Win 5 matches in a row |
| Unstoppable | Win 10 matches in a row |
| Nail Biter | Win a match 10-9 |
| Heartbreaker | Win 3 matches by 10-9 |
| Comeback Kid | Win after losing 3 in a row |
| The Rivalry Begins | Play 10 matches total |
| Dedicated | Play 50 matches total |
| Century Club | Play 100 matches total |
A beautiful timeline view of every match played, grouped by month. Each match card shows the winner, score, and any bet that was on the line. Color-coded timeline dots mark each player's victories. At the very bottom -- a little marker where it all began.
Context-aware banter that adapts to your rivalry:
- No matches yet? The cat judges you for not playing.
- Tied up? It gets tense.
- Close rivalry? The pressure builds.
- Dominant lead? The roasting begins.
- On a streak? It gets personal.
Plus revenge prompts after losses to keep the competitive fire burning.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| UI Library | React 19 with Server Components |
| Styling | Tailwind CSS v4 with OKLch color system |
| Components | shadcn/ui + Radix UI |
| Variants | CVA (Class Variance Authority) |
| Icons | Lucide React |
| Dark Mode | next-themes |
| Fonts | Geist Sans & Mono |
| Persistence | Browser localStorage (no backend needed) |
| Monorepo | Turborepo with pnpm workspaces |
| Language | TypeScript (strict mode) |
# Clone the repo
git clone https://github.com/your-username/ping-pong-fun.git
cd ping-pong-fun
# Install dependencies
pnpm install
# Start the dev server
pnpm devOpen http://localhost:3000, enter your rival's name, and let the games begin.
pnpm build # Production build
pnpm lint # Run ESLint
pnpm format # Run Prettier
pnpm typecheck # TypeScript type checkingping-pong-fun/
├── apps/
│ └── web/ # Next.js application
│ ├── app/ # App Router pages
│ │ ├── page.tsx # Rivalry dashboard
│ │ ├── play/ # Match logging
│ │ ├── stats/ # Stats & achievements
│ │ └── history/ # Match timeline
│ ├── components/ # React components
│ └── lib/ # Game logic
│ ├── achievements.ts # Achievement definitions
│ ├── bets.ts # Bet generator pools
│ ├── stats.ts # Stats calculations
│ ├── trash-talk.ts # Trash talk engine
│ ├── storage.ts # localStorage persistence
│ └── types.ts # TypeScript types
├── packages/
│ ├── ui/ # Shared component library
│ ├── eslint-config/ # Shared ESLint configs
│ └── typescript-config/ # Shared TypeScript configs
└── turbo.json # Turborepo pipeline
- Mobile-first -- designed for phones propped up next to the ping pong table
- No backend -- your data stays in your browser, no sign-ups needed
- Playful personality -- cat emojis, animated paw prints, and floating elements
- Dark mode by default -- easy on the eyes during late-night matches
- Smooth animations -- slide-ups, glowing accents, and bouncing paws
Built with love, competitive spirit, and way too many 10-9 nail biters.
The cat is always watching. Always judging.





