← My work

Full-stack web product · Social sports

Relay

Relay gives recreational pickleball groups one place to plan a session, invite players, split court costs, manage rotations, score matches, and save a recap.

Contribution
Designed and built independently
Current state
Live web product · Source available
Built with
Next.js · TypeScript · Supabase · PostgreSQL · Drizzle ORM · Zod · Vitest · Playwright

Product showcase

Inside Relay

Selected product surfaces from the live experience, presented without simulated chrome or scroll-driven effects.

Relay public pickleball invitation with session details, roster capacity, and guest RSVP controls
01Plan and RSVPFull resolution ↗
Relay play setup showing Paddle Stack, Mix It Up, Court Climb, and Team Round Robin formats
02Play formatFull resolution ↗
Relay active courts view with live scoring and the paddle queue
03Live courtsFull resolution ↗
Relay courtside scoring view with large team scores and touch controls
04Courtside scoringFull resolution ↗

Problem and response

The problem

Recreational pickleball groups coordinate the plan, roster, venue cost, court order, and scores across group chats, spreadsheets, and whoever happens to remember what comes next.

The approach

A host creates one session and shares a public link. The same workspace holds the plan, roster, venue costs, court queue, match scores, chat, and recap, so the group does not need to reconstruct the night across separate tools.

Product journey · 7 connected features

One session, from first plan to shared memory.

Relay replaces the scattered chat, spreadsheet, scorekeeper, and payment follow-up with one continuous product flow.

01 · Plan

Plan it before the chat gets noisy.

Venue search, date and time, courts, capacity, booking, and readiness.

Create a game

Set the plan. Share the link.

02 · Invite

One link answers every question.

Guest RSVP, host approval, capacity, and an automatic waitlist. Guests do not need an account.

Saturday, August 22

Saturday Night Pickle

Central Pickle · 7:00–10:00 PM

Players
8 of 10 going
Estimated
₱300 / player
Join this gameYour name
GoingMaybeCan’t go

03 · Organize

Keep the crew, not the admin.

Roster controls, recurring groups, calendar, global search, and Play Again.

Game readinessAlmost ready75%

Roster · 8 going · 1 waitlisted Add player

  • VanHostGoing
  • AJRegularGoing
  • MikaCasualGoing

04 · Play

Run every court from one phone.

Five play formats, paddle stack, fixed pairs, multi-court scoring, and standings.

Court 1Balanced Mix● Live
Van + AJ8VSMika + Bea6
−   +−   +

05 · Repay

Split what the host already covered.

GCash, Maya, bank or cash, proof review, exclusions, and adjusted shares.

Court repayment
₱2,4007 paying players · ₱300 each2 confirmed
  • VanPaid upfront₱2,400
  • AJConfirmed₱300
  • MikaProof sent₱300

06 · Stay in sync

The conversation stays with the game.

Realtime chat, photos, reactions, system updates, and useful notifications.

Saturday Night Pickle8 players in sync
AJ joined the game

Parking is open beside Court 2.

Perfect. I’ll bring the extra balls.

Court 1 match started
Message the group Send

07 · Remember

Turn the night into a story.

Seven portrait recaps, chosen backgrounds, standings, photos, and shared memories.

Session recapChoose your story3 of 7
My game3–1Van

#2 · +12

Winning teamVan + AJ3

wins together

Standings

1 Van 3–1

2 AJ 2–2

3 Mika

01 / 07

Architecture

Next.js Server Components load the initial session state. Server actions and queries enforce authorization and product rules, while small client components handle RSVP, scoring, forms, and live court updates.

  1. Feature-based modules

    Session, roster, payment, match, queue, group, and notification code is organized with its schemas, actions, queries, and interface components.

  2. Authorization on every write

    Mutations validate the signed-in user, session role, lifecycle state, and Zod input before changing data.

  3. Typed relational model

    Drizzle and PostgreSQL model sessions, players, courts, matches, queues, expenses, chat, and memories with explicit constraints.

  4. Small client boundaries

    Public RSVP, progressive forms, court controls, scoring, and realtime reconciliation run on the client. The rest of the page remains server-rendered.

Key product and engineering decisions

These decisions affect what users can do, where product rules live, and how the system handles failure or change.

Make the session the product boundary

The session owns the plan, roster, expenses, courts, queue, matches, chat, and recap. Users can move through one game without learning separate management areas.

Let the shared link carry the plan

Invitees can check the time, venue, capacity, estimated cost, and booking status, then RSVP by name without creating an account.

Design for courtside use

Large score controls, deterministic rotations, visible queue state, and focused live views prioritize fast one-handed decisions beside the court.

What you can inspect

The live product and public repository provide concrete evidence of the implemented features, architecture, tests, and documentation.