← projects/tapapamai

2026 →

Tapapamai

Community sports platform

tapapamai.com
In progressProductFull-stack

Challenges, video submissions, verified leaderboards. Full-stack monorepo in production.

4

apps in the monorepo

3

surfaces (API · Admin · Mobile)

71

backend tests (xUnit)

The problem

In a sports community, tracking challenges and performances means using Strava, Instagram or a shared Google Sheet. No single tool lets you publish a challenge with clear rules, receive submissions with video proof, and produce a credible leaderboard. Existing platforms are expensive and designed for affiliated clubs, not informal groups or one-off competitions.

The approach

Monorepo with 4 surfaces: REST API (.NET 8 + PostgreSQL on Railway), Flutter mobile app (iOS/Android/Web), Next.js admin panel and landing page. The athlete submits their score with a video link, the admin validates it before it counts in the leaderboard. Stateless JWT architecture with automatic refresh token on mobile.

Key decisions

01

WOD statuses calculated client-side

The backend stores startDate/endDate/isActive. OPEN, UPCOMING, CLOSED statuses are computed in the UI, with no cron job to maintain. Single source of truth.

02

Dockerfile builder forced on Railway

Railpack ignored the Dockerfile ENTRYPOINT, breaking dynamic PORT binding. railway.toml forces builder = "dockerfile" to work around the bug.

03

Soft-delete on all critical entities

Users, Challenges, Submissions are never physically deleted. IsActive + DeletedAt flags preserve leaderboard history and allow account restoration.

Stack

Next.jsReact QueryRechartsZodTailwind.NET 8ASP.NET CorePostgreSQLEntity FrameworkJWTSendGridFlutterRiverpodGo Router

What I learned

Managing 4 surfaces simultaneously in a monorepo enforces an architectural discipline you wouldn't have with a simple project. The real challenge isn't technical: it's keeping interface contracts in sync across clients without introducing coupling.