BuildWithMatija
Back to Builds
ProductShippedPrivate

Rekreacija

Find a recreational football session, join it, and keep the organizer workflow in one place.

  • Next.js 16
  • React 19
  • TypeScript
  • Payload CMS 3
  • Postgres
  • Tailwind CSS
  • shadcn/ui
  • Radix UI
  • Server Actions
  • Payload Local API
  • Kotlin
  • Jetpack Compose
  • Android
  • Vitest
  • Playwright
GitHub
Problem
Recreational football and sports groups usually run through chats, spreadsheets, informal payment notes, and manual attendance lists. Players do not have one reliable place to discover upcoming games, see who is coming, check price and location, and join without messaging an organizer. Organizers also need visibility into members, attendance, balances, and private group access without turning the whole operation into admin chaos.
Thesis
A league-and-event model is a better fit than a generic calendar or chat group. Rekreacija connects leagues, events, memberships, attendance, payments, players, organizers, and visibility rules into one shared system. The bet is that recreational sports discovery works best when the player experience and organizer office are separate surfaces built on the same backend.
Validation
The repo contains a working private codebase with a player web app, organizer web office, Payload admin, player Android app, organizer Android app, and documented mobile APIs. The implementation snapshot says lint, build, and test release gates pass, with narrow E2E coverage and integration tests for mobile, registration/claim, and organizer access. There is no verified public production URL, public user count, paid customer proof, or revenue proof documented.
Proof points
  • Private GitHub repository at https://github.com/matija2209/rekreacija
  • README documents player web, organizer web office, Android player app, Android pisarna app, and Payload admin.
  • Canonical product brief documents the core product as recreational sports league and event participation with organizer operations.
  • Code status document marks player web, organizer web, Payload admin, player Android app, organizer Android app, player Android API, and organizer Android API as shipped.
  • Code status document says lint, build, and test release gates pass.
  • E2E coverage is documented as narrow, covering homepage/navigation, organizer login redirect, and player auth flows.
  • No public deployment URL, public user count, customer count, or revenue proof is documented.
Audience
  • Players looking for recreational football, futsal, or other sports sessions to join
  • Organizers running recurring recreational leagues or casual matches
  • Community sports groups replacing chat coordination and spreadsheets
  • Admins who need structured control over players, leagues, events, attendance, and payments

Executive summary

Rekreacija is a platform for recreational sports discovery and operations.

The player side helps people find upcoming recreational sessions, open event details, see schedule, location, price, capacity, and participants, then join with an account. The organizer side gives league organizers a private office at /pisarna for managing leagues, events, attendance, and payment visibility.

The product is not only football-specific in the codebase. It supports a broader recreational sports model, including football, futsal-style field sizes, basketball, volleyball, and tennis. But the core use case fits football recreation discovery very well: find a game, check if there is space, join, and let the organizer track who is coming.

The problem

Recreational football groups often run on messy coordination.

One WhatsApp group handles announcements. A spreadsheet tracks who paid. Someone manually counts who is coming. Another message thread decides whether the game is full. New players have to ask around to find out when and where people are playing.

That works for a small stable group, but it breaks once there are multiple leagues, venues, recurring sessions, changing attendance, private groups, and payments. Players need a simple discovery and join flow. Organizers need structured operations without forcing everyone into a generic admin system.

The thesis

The main bet is that recreational sports need a domain model, not just a calendar.

Rekreacija is centered around:

  • leagues
  • events
  • players
  • organizers
  • memberships
  • attendance
  • payments
  • locations
  • visibility rules

That lets the product connect actions that are usually scattered. When a player joins an event, the system can also handle league membership and attendance. When an organizer opens a league, they can see members and balances. When an event is private, discovery and direct access can respect membership rules.

The second bet is surface separation. Players and organizers should not use the same interface. Players need discovery, joining, and profile views. Organizers need an office for managing leagues, events, attendance, and payments.

What I built

Player web experience

The player-facing web app includes the main public and authenticated flows:

  • homepage
  • event discovery at /rekreacije
  • event detail pages at /rekreacije/[id]
  • league listing at /lige
  • league detail pages at /lige/[id]
  • player login at /prijava
  • player registration at /registracija
  • profile dashboard at /profil
  • profile editing at /profil/uredi
  • public player pages at /igralci/[id]

The event discovery page fetches the active dataset server-side, then filters and paginates on the client. That keeps filtering fast for the user without adding network calls for every search or filter change.

Discovery filters include:

  • text search
  • league
  • sport
  • location
  • status

Football and sport discovery

The core discovery flow is built around individual recreational sessions.

An event card shows:

  • status
  • price
  • event name
  • league name
  • date and time
  • location
  • current attendance count
  • maximum participants
  • link to details

This is the practical football recreation use case: a player can quickly answer “where is the game, when is it, what does it cost, how many people are already coming, and can I join?”

Join workflow

The join workflow is one of the product’s most important parts.

When a player joins an event, the system can:

  • create attendance
  • automatically create a league membership if the player is not already in the league
  • prevent duplicate joins
  • block joining when an event is full
  • block joining when an event is locked
  • show already-joined states

The implementation snapshot also says leave event exists on web, but not as a mobile endpoint.

Organizer office

The organizer office lives at /pisarna.

It includes:

  • organizer login
  • protected organizer dashboard
  • dashboard KPIs
  • league list scoped to the organizer
  • league create and edit
  • league detail with members and balances
  • event list
  • event create and edit
  • event detail with attendance table
  • attendance status updates
  • payment listing and read-only payment detail

The custom office intentionally does not cover every possible admin action. League and event delete operations stay in Payload admin. Payment operations in /pisarna are read-only for now.

Payload admin and backend

Payload CMS is the internal admin and backend foundation.

The documented model includes collections for:

  • users
  • players
  • leagues
  • memberships
  • events
  • attendances
  • payments
  • locations
  • media
  • account merges
  • player invites
  • league locations

Payload provides the admin interface, auth routes, REST API, GraphQL API, and Local API used by the application.

The codebase was migrated from a Prisma-only architecture toward a Payload CMS-powered backend for better administration and data management.

Visibility and access control

Rekreacija supports public and private visibility for both leagues and events.

The discovery pages filter content based on visibility and membership. Public content can be shown broadly. Private content is visible only to members and admins. Direct URL access to private entities is also checked server-side.

That matters for real recreational groups because not every session should be listed publicly.

Payments and balances

Payments are modeled and connected to leagues and events.

The player profile can show balances. The organizer office can show payment records and payment detail pages, but payment creation, editing, and verification are not part of the custom /pisarna UI yet. Those workflows stay in Payload admin or are deferred.

This should be positioned as payment visibility and balance tracking, not full payment processing.

Android apps

The repo contains two Android apps under the Android project:

  • player app
  • pisarna organizer app

The implementation snapshot marks both as shipped, with the organizer Android app smoke-tested on device. The README also warns not to mix package IDs or network settings between the two apps.

The player Android app mirrors the player web experience: discovery, event detail, join, profile, league context, and profile editing. The documented V1 non-goals include chat, organizer flows inside the player app, payment recording, push notifications, maps, and profile photo upload.

Testing and readiness

The implementation snapshot says these release gates pass:

  • lint
  • build
  • test

It also documents that E2E coverage is narrow. Current E2E tests cover homepage and navigation to /rekreacije, organizer login redirect, and player auth flows.

Integration tests cover mobile API, registration/claim, and organizer access.

Architecture

text
Player web
  → Next.js App Router
  → discovery pages, event detail, league detail, profile
  → Server Actions and Payload Local API
  → Payload CMS
  → Postgres

Organizer web
  → /pisarna
  → league, event, attendance, payment views
  → role-based access
  → Payload CMS
  → Postgres

Android apps
  → player app and organizer app
  → mobile API routes and Payload REST
  → same backend model

Payload admin
  → full internal data management
  → users, players, leagues, events, attendances, payments, locations

Current status

Rekreacija is shipped-private. The player web app, organizer web office, Payload admin, player Android app, and organizer Android app are documented as shipped. Lint, build, and test release gates pass; E2E coverage is narrow.

There is no verified public production URL, public user count, paid customer proof, or revenue proof. Payment operations in /pisarna are read-only; full payment workflows stay in Payload admin or are deferred. Leave event exists on web but not as a mobile endpoint.

Next steps: public or staging deployment for demos, broader E2E coverage, mobile parity for leave event, and payment recording in the organizer office.

Related services

  • Internal tools
  • Payload CMS websites
  • Next.js developer

Working through something similar?

If your company has a workflow, content system, or internal process that needs to become real software, this is the kind of work I can help with.

Get in touch

Related builds

You might also find these useful

ProductShippedPrivate beta

Farmica

Order operations for direct-to-consumer farms — a spletna naročilnica that collects scattered channel orders into one weekly workflow.

  • Next.js
  • React
  • TypeScript
  • next-intl
  • Tailwind CSS
  • Vercel
  • Brevo
  • Google Analytics 4
View buildVisit
ProductShippedDemo available

Izložbica

Izložbica is a multi-tenant storefront and backoffice platform for creators who sell physical products through small catalogues, direct orders, pickup, delivery, and manual payment workflows. It gives sellers a simple public izložbica plus a private Pisarna for products, orders, stock, payments, and customer handling.

  • Next.js
  • React
  • TypeScript
  • Payload CMS
  • PostgreSQL
  • next-intl
  • TanStack Form
  • Zod
  • Radix UI
  • Stripe
  • Brevo
  • S3-compatible storage
  • Playwright
  • Vitest
  • pnpm
View buildLive demo
ToolActiveOpen source

DropImg

A self-hosted, Docker-first image hosting tool — drag, drop, or paste to get instant public URLs, with built-in multi-user support, S3-compatible storage, and optional background removal.

  • React 19
  • Vite
  • Hono
  • Node.js
  • TypeScript
  • Tailwind CSS 4
  • SQLite
  • Drizzle ORM
  • Garage S3
  • Docker
  • Better Auth
  • Cloudflare
View buildGitHub
Build with Matija logo

Build with Matija

Modern websites, content systems, and AI workflows built for long-term growth.

Services

  • Headless CMS Websites
  • Next.js & Headless CMS Advisory
  • AI Systems & Automation
  • Website & Content Audit

Resources

  • Case Studies
  • How I Work
  • Blog
  • Topics
  • CMS Hub
  • E-commerce Hub
  • B2B Website Strategy
  • Dashboard

Headless CMS

  • Payload CMS Developer
  • CMS Migration
  • Multi-Tenant CMS
  • Payload vs Sanity
  • Payload vs WordPress
  • Payload vs Contentful

Get in Touch

Ready to modernize your stack? Let's talk about what you're building.

Book a discovery callContact me →
© 2026Build with Matija•All rights reserved•Privacy Policy•Terms of Service
BuildWithMatija
Get In Touch