RiftVeil is a spoiler-aware League of Legends esports web app: one place to see schedules and series across leagues, with optional reveal of results and links to broadcasts and VODs.
- Home — Live, upcoming, and recent matches with global and per-match spoiler controls (
useSpoilerPrefs). Live matches show a red accent stripe, a pulsing badge, and a direct Watch live link to lolesports.com. - Leagues — Hub per league at
/leagues/:shortName: pick a tournament, browse matches grouped by round (only the active round expands when the tournament is ongoing), open a series without leaving the league context. - Match detail — Series scoreline with team watermarks in the hero; game tabs, VOD link, and dev import controls in a hero footer. Per-game draft (
GameDraft) and scoreboard (GameScoreboard) in a stacked panel, with global objectives and a lane-by-lane damage breakdown (GameDamageBars, Game/Team scaling) side by side. Manual VOD overrides are tracked separately from imported VOD rows, so local edits do not overwrite import-origin metadata. Layout is desktop-first for now (responsive breakpoints removed temporarily). - Admin — At
/admin, three tabs: Import (tournaments, matches, VODs, game details with league + scope and per-step run summaries), Backfill (game external IDs, blue/red sides, team metadata from Leaguepedia), and Teams (inspect/edit/sync logo URLs and shorts). Game VOD tools include quick-pick suggestions for recently finished matches that still miss game-level VOD links. There is no admin link in the navbar.
- Leaguepedia — Primary source for tournaments, matches, games, team metadata (logo/wordmark + square icon URLs from Cargo
Teams.Image), and related metadata via the import API. Import reconciliation can update placeholder opponents when later schedule rows resolve real participants. - Lolesports — Used to enrich games with VOD URLs where possible (LEC, LCS, LCK, LPL, CBLOL, LCP), with locale-priority selection for default playback URLs.
| Layer | Choice |
|---|---|
| Backend | ASP.NET Core Web API, EF Core, SQL Server |
| Frontend | React 19, TypeScript, Vite, React Router, TanStack Query |
backend/— .NET solution (RiftVeil.sln): API, domain, infrastructure, tests.frontend/— Vite + React client; dev server proxies/apito the backend.
The import pipeline depends on two external sources. Configure these via user secrets (development) or environment variables (production):
Leaguepedia:BotUsername/Leaguepedia:BotPassword— bot credentials for Leaguepedia (raises Cargo API rate limits vs anonymous access). Optional: anonymous fallback works for most reads.Lolesports:ApiKey— public x-api-key used against Riot's lolesports GraphQL gateway for VOD enrichment.
This is a personal portfolio project; credentials are not bundled. To run the importers you need your own Leaguepedia bot account and the public lolesports key (commonly known and rotated periodically).
- Database — Ensure SQL Server is available. The API’s
appsettings.Development.jsondefaults to LocalDB (RiftVeildatabase); adjust the connection string if you use another instance. - Backend — From
backend/RiftVeil.Api(or the solution root), apply EF migrations (includesTeams.IconLogoUrlandGameVods.Source) and run the API (HTTP profile listens on 5133 in development so it matches the Vite proxy). - Frontend — From
frontend/, runnpm installonce, thennpm run dev(opens the app, typically on port 5173). Copyfrontend/.env.exampleto.env.localif you want to set optional vars (e.g.VITE_CONTACT_EMAILfor the footer mailto link).
MVP-focused: solid import pipeline and browsing experience first; richer in-match stats UI and extras (for example reminders) come later. See CHANGELOG.md for a short dated summary, docs/technical-log.md for detailed development notes, and docs/data-import-notes.md for import-specific pitfalls and migrations.