SportHub

A platform for local sport: pickup games, leagues and venue booking. It is used primarily in the Balkans, with English for other markets. It is our own product, and we run it.

Industry
Sports
Our role
Our own product, idea to production
Live since
2025
The SportHub home screen, with open pickup games, leagues and recent notifications

Sport that runs on group chats.

Amateur sport in a Balkan city is organised in group chats. Someone asks who is playing tomorrow, twenty messages later nobody knows the time, and the pitch was never booked.

SportHub replaces the chat with one place: find a game, take a spot, see who is coming and know the venue has confirmed. Leagues keep their own table, and every result lands on the players' profiles.

3

ways to post a game: the site, Telegram and the Android share sheet

1,448

interface strings, every one in English and Serbian

~180

tests, the AI agent included, run on every push

What we built.

The game box turning “basketball tomorrow at 8pm at Budućnost sala, 6 of us, 90 minutes” into a draft: basketball at Budućnost sala, Thu 1 Oct at 20:00, 6 players, 90 minutes

A game from one sentence

Type “football tomorrow at 7pm, 10 of us” on the site, in Telegram or from the Android share sheet. An AI agent drafts the game, checks it against the same rules as the form, and asks one question if something is missing.

The page for a football game at Zenit, with capacity, price and a game chat beside it

Pickup games with a live chat

Every open game in the city, by sport. One tap to join, a chat for each game and a reminder before kickoff. Pages update the moment something changes, with no refresh.

The leagues page, with live and open-registration leagues across several sports and their current tables

Leagues that run themselves

Pick a start date and an interval and every round is scheduled, home and away balanced. Post a result and the table, goal difference and top scorers update for everyone watching.

The games list, with three open games in the city and the spots left in each

Venues that confirm bookings

Partner venues list their pitches and hours, see holds from new games in an inbox, and confirm or reject them. Two games can never hold the same pitch at the same hour.

What broke, and what we changed.

Slow for the people it was built for.

Most players are in the Balkans; the servers and the database are in the US. Every request paid a round trip across the Atlantic plus a cold start. The home screen now loads in one request instead of six, public pages come from the CDN, the next page is fetched on hover, and a scheduled job pings the functions every two minutes to keep them warm, so nobody meets a cold one.

The update that broke every query.

Moving to Prisma's engine-free client made cold starts smaller. The first deploy built cleanly and then failed every query, because the bundler dropped a file that is only loaded at runtime. The build config now includes it, and a check after every build catches it.

Adding venues to a live database.

Venue booking changed the schema in a way old and new code could not share, so the migration and the deploy had to land in the same minute. Every existing booking was moved onto a pitch, a read-only diff was checked first, and no rows were lost.

What it runs on

Next.js, React and TypeScript on Vercel. Postgres on Supabase with Prisma, live updates over Supabase channels, Firebase for sign-in. The AI agent runs on LangGraph with Gemini and is traced in LangSmith. In-app, push and Telegram notifications go out from one call.

Live since 2025. Still shipping.