Freelance / Client project · 2026

Copon

Private football prediction tournaments

Platform to run private football prediction pools (prode) with automatic scoring and live standings. Online at copon.com.ar running its first tournaments.

Role

Full Stack Developer (client project)

Context

Freelance / Client project

Year

2026

Links

Technologies: Next.jstRPCDrizzle ORMSupabaseTanStack QueryBetter-AuthTailwindshadcn/ui

Overview

Copon is a web platform to run private football prediction tournaments among friends, coworkers or a community. Whoever organizes the pool creates a tournament, invites people with a link, and the app scores every matchday on its own. It is not a betting site: it is the tool that replaces the spreadsheet.

The problem

A client came to me with the pool of his group running on an Excel file and a WhatsApp thread. Somebody had to load every result by hand, recalculate the table, and settle arguments about who predicted what and when. Predictions arrived late, points came out wrong, and nobody could see the standings without asking for the file.

What was needed was not a bigger spreadsheet: it was predictions that close on a deadline, scoring computed by the system, and a standings table anyone can open from their phone.

Landing: organize your tournament, manage the pool

Joining a tournament

Mobile flow: joining a tournament via invite link (2026 World Cup group stage)

Decisions

  • Scoring and standings as a pure module (@repo/core): it is the part that has to be right, so it lives with no framework around it, returns Result<T,E> instead of throwing, and is unit tested with Vitest before anything renders.
  • tRPC instead of a REST layer: one developer, one codebase, and every router typed from server to client, so a change in a payload breaks the build and not the pool.
  • Drizzle ORM over Supabase Postgres: the schema is TypeScript, migrations stay versioned in the repo, and the queries read next to the business logic.
  • T3-turbo monorepo split by responsibility (@repo/db, @repo/api, @repo/auth, @repo/core, @repo/ui, @repo/validators): the pure logic never imports Next.js, so it stays testable and portable.
  • Better-Auth with invite links: joining a tournament had to be one tap from WhatsApp, not a signup form plus a code.
  • Three configurable formats (round robin League, Groups plus Knockout, Knockout only) with custom or real teams, editable fixtures and configurable point systems: every group scores its pool differently, and the app had to absorb that instead of imposing one rulebook.
  • TanStack Query on the client: standings and matchdays change while people are watching the match, so the cache refetches instead of the user reloading.
Groups plus Knockout format: bracket view
League format: standings table
Finished matchday: fixture and results
Pool standings: who is winning the pot

Result

Copon is online at copon.com.ar running the pools of the client's group, starting with the 2026 World Cup group stage. Nobody loads points by hand any more: results come in, the table updates, and the round based pot is settled by the same code that is covered by tests.

What it confirmed for me is that keeping business logic pure pays off in the first week: every argument about scoring was closed by reading a test, not by reading the interface.