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
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.