Trackmania club seasons platform with:
api/: Laravel REST APIweb/: Vue 3 + TypeScript frontend
The app lets admins run seasonal competitions on selected Trackmania maps and gives players transparent standings and point events.
- Discord OAuth login for website access
- Admin-managed seasons and season maps
- Automatic season lifecycle transitions (
scheduled -> active -> ended) - Automatic polling of the active season leaderboard
- Event-based scoring (first finish, medal rewards, final placement rewards)
- Public views for season overview, standings, events, and player details
- Backend: Laravel 13, Sanctum (SPA/session auth), Socialite (Discord)
- Frontend: Vue 3, Vue Router, TypeScript, Vite, Tailwind CSS
- Data model highlights:
seasons,maps,season_mapstrackmania_players,season_map_player_recordspoint_events(auditable scoring log)leaderboard_polls,leaderboard_snapshots
Domain documentation:
| Domain | Owns | Key Models | Key Services | Route File |
|---|---|---|---|---|
| Identity | Authentication, current-user profile, admin gate | User |
EnsureUserIsAdmin (middleware), DiscordAuthController |
api/routes/domains/identity.php |
| Trackmania | Clubs, members, players, maps, external Trackmania data integration | TrackmaniaClub, ClubMember, TrackmaniaPlayer, Map |
TrackmaniaClient, TrackmaniaTokenService, TrackmaniaIoClient, TrackmaniaClubSyncService, MapImportService, ActiveClubPlayerService |
api/routes/domains/trackmania.php |
| Seasons | Season lifecycle, map assignment, polling, polls/snapshots, standings APIs | Season, SeasonStatus, LeaderboardPoll, LeaderboardSnapshot, SeasonMapPlayerRecord, PlayerMapMilestone |
SeasonLifecycleService, SeasonLeaderboardPollingService, SeasonScoringService, SeasonStandingsService, SeasonPollingPersistenceService |
api/routes/domains/seasons.php |
| Activity | Scoring event ledger and activity/stat query support | PointEvent |
SeasonActivityFeedService, SeasonActivityStatsService, SeasonPointEventWriteService |
api/routes/domains/activity.php |
| Integrations | Future external adapters (bot/overlay/plugin/webhooks) | (planned) | (planned) | api/routes/domains/integrations.php |
Important: this project uses two similarly named but different Trackmania APIs.
Used for website authentication.
- Redirect endpoint:
/auth/discord/callback - Required scopes:
identify,email - Docs: docs/discord-oauth-setup.md
Used to fetch map metadata and leaderboard data.
- Auth base URL (default):
https://prod.trackmania.core.nadeo.online - API base URL (default):
https://live-services.trackmania.nadeo.live - Uses dedicated server login/password for token acquisition
- Docs: docs/trackmania-client-setup.md
Used for player/account detail enrichment (for example display names and zone info) during club sync.
- Base URL (default):
https://trackmania.io - Endpoint used:
GET /api/player/{accountId} - Config key:
services.trackmania_ioinapi/config/services.php - Dedicated docs: docs/trackmania-io-account-api.md
Configured in api/config/seasons.php under scoring:
first_finish: 10 points- Medal rewards:
- bronze: 5
- silver: 10
- gold: 20
- author: 35
- Final placement rewards:
- top 20: 10
- top 10: 20
- top 5: 35
- top 1: 50
Each award is stored as an immutable point event so totals are explainable.
Configured in api/routes/console.php:
season:update-statusesruns every minuteseason:poll-activeruns every minute
Run this to enable automation:
cd api
php artisan schedule:workFinalization is intentionally manual (ended -> finalized).
Defined in api/routes/api.php.
OpenAPI documentation is generated with Scramble:
- UI:
/docs/api - JSON document:
/docs/api.json - Static export: docs/openapi.json
Public endpoints include:
GET /api/seasonsGET /api/seasons/{slug}GET /api/seasons/{slug}/leaderboardGET /api/seasons/{slug}/standingsGET /api/seasons/{slug}/events
Admin endpoints (auth + admin middleware) include:
- season CRUD + finalize
- map import/management
- season map attach/order/active toggles
- manual poll + records
- points/events/recalculation
cd api
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate
php artisan serveSet required env vars for Discord and Trackmania in api/.env (see docs above).
cd web
npm install
cp .env.example .env
npm run devSet VITE_API_URL in web/.env to your API URL (commonly http://localhost:8000).
In a separate terminal:
cd api
php artisan schedule:workBackend:
cd api
php artisan test
php artisan scramble:export --path=../docs/openapi.json
php artisan schedule:list
php artisan trackmania:test-map {mapUid}
php artisan season:poll-active
php artisan season:update-statuses
php artisan season:finalize {seasonIdOrSlug}Frontend:
cd web
npm run type-check
npm run test:unit
npm run test:e2e
npm run build