BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
Sync your Yahoo fantasy leagues to view live rosters, scoreboards, and standings
AI summary · README
Sports & fitnessGo · TypeScriptGitHub @davidhyoungOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Full-stack fantasy sports web app (multi-sport: NFL, NBA). Go backend + React/Vite/TypeScript frontend + PostgreSQL. Users authenticate via Yahoo OAuth, sync their Yahoo fantasy leagues, and view live rosters, scoreboards, standings, and matchup details.Read the full README ↗
Fantasy Sports
Full-stack fantasy sports web app (multi-sport: NFL, NBA). Go backend + React/Vite/TypeScript frontend + PostgreSQL. Users authenticate via Yahoo OAuth, sync their Yahoo fantasy leagues, and view live rosters, scoreboards, standings, and matchup details.
backend/ Go API server (Chi router, pgx/pgxpool, golang-migrate, gorilla/sessions, Yahoo OAuth2)
frontend/ React 18 + Vite 5 + TypeScript + Tailwind CSS + shadcn/ui + TanStack Query v5
Backend layout:
cmd/api/main.go — entry point; wires router, DB pool, sessions, oauth config, handlerscmd/import/main.go — CLI tool to download nflverse CSV data and upsert into nfl_players / nfl_player_statsinternal/handlers/ — one file per resource; all handlers are methods on Handler{db, sessions, oauthConfig, config}
handlers.go — Handler struct definition + constructorrespond.go — JSON response helpersauth.go — Login, Callback, Me, Logoutleagues.go — ListLeagues, CreateLeague, GetLeagueteams.go — ListLeagueTeams, GetTeam, GetTeamRoster (with stat period support); includes gsis_id batch lookup for player detail linksplayers.go — ListPlayers, CreatePlayer, GetPlayerscoring.go — GetLeagueScoreboard, GetLeagueStandingsyahoo_helpers.go — leagueYahooKey(), userTokens(), newYahooClient() shared helpers used by multiple handlerssync.go — Sync (Yahoo league+team upsert)league_players.go — SearchLeaguePlayers, GetAvailablePlayerskeepers.go — GetKeeperRules, UpdateKeeperRules, GetLeagueDraftResults, GetLeagueKeepers, GetKeeperSummary, ListTeamKeeperWishlist, AddKeeperWishlist, RemoveKeeperWishlist, SubmitKeepers, UnsubmitKeepersanalysis.go — GetLeagueRankings: weighted z-score rankings; category weights = CV × FA-scarcity (normalised); adds position_score (z-score within position group); includes gsis_id lookup for player detail linksprojections.go — ListProjections, GetProjectionDetail; serves pre-computed comp-based NFL player projections from nfl_projections tablenfl_players.go — GetNFLPlayer (full player detail: metadata + YoY stats + projection); GetNFLPlayerByYahooID (resolves Yahoo key → gsis_id and redirects)draft_values.go — GetDraftValues: league-specific auction values (VOR + $ value based on actual roster settings)grades.go — ListGrades, GetPlayerGrades: real-life player grades (0-100 percentile) from nfl_player_grades table; supports comma-separated position filter (e.g. ?position=RB,WR,TE)internal/models/models.go — shared domain types (User, League, Team, Player, RosterEntry)internal/middleware/auth.go — RequireAuth: reads session, attaches *models.User to ctxinternal/yahoo/ — Yahoo Fantasy API client, OAuth config, XML types
client.go — all API methods + dbTokenSource (auto-refreshes + persists tokens)oauth.go — Yahoo OAuth2 endpoint + NewOAuthConfigtypes.go — all XML response structsinternal/db/db.go — pgxpool connect helpermigrations/ — numbered SQL migration filesFrontend layout:
src/api/client.ts — all typed API functions + TypeScript interfacessrc/api/queryKeys.ts — all TanStack Query cache keyssrc/lib/queryClient.ts — QueryClient config (staleTime: 30s, retry: 1)src/lib/utils.ts — cn() utility (clsx + tailwind-merge), zScoreIndicator, zScoreColorsrc/lib/grades.ts — shared grade display utilities: gradeColorClass, trendIndicator, phaseLabel, phaseColorsrc/lib/constants.ts — CURRENT_SEASON (2025), PROJECTION_SEASON (2026)src/pages/ — pages by route; complex pages split into subdirectories:
Home.tsx, Leagues.tsx — simple single-file pagesleague-detail/ — index.tsx + tab components (StandingsTab, ScoreboardTab, PlayersTab, KeepersTab, RankingsTab, DraftTab [NFL only]) + hooksteam-detail/ — index.tsx + components/ (RosterTable, MatchupCard) + hooks/useTeamDetail.tsmatchup-detail/ — index.tsx + components/ (CategoryTotalsTable, TeamRosterTable) + hookplayer-detail/ — index.tsx + components/GradeCard.tsx — unified NFL player detail page (metadata, grade card, YoY stats table, projection with PPR/Half/Standard toggle + comps)projection-detail/ — index.tsx + components/ (CompCard, TrajectoryChart) + hook — legacy detail page (redirects to player-detail)rankings/ — index.tsx + hooks/useRankings.ts — standalone real-life player grades page (top-level /rankings) with Flex/Superflex position filtersprojections/ — index.tsx + hooks/useProjections.ts + components/ (ProjectionTable, ConfidenceBadge, UniquenessBadge) — comp-based projection rankings with PPR/Half/Standard togglesrc/components/ui/ — shadcn/ui components (badge, button, input, table, tabs, provider) + table-helpers (SortableHead, PlayerCell, ClickableRow, ZScoreCell, HeaderRow)src/App.tsx — router + nav (with active page highlighting) + auth checksrc/main.tsx — React root, QueryClientProvider, BrowserRouter/api and /auth → http://localhost:8080 in devPublic:
GET /auth/login, /auth/callback, /auth/logout
GET /api/health
GET/POST /api/leagues, GET /api/leagues/{id}
GET /api/leagues/{id}/teams
GET /api/teams/{id}
GET/POST /api/players, GET /api/players/{id}
GET /api/projections?season=&position=&sort=&limit=&offset=
GET /api/projections/{gsisId}?season=
GET /api/nfl/players/{gsisId} — full player detail (metadata + YoY stats + projection)
GET /api/nfl/players/by-yahoo/{yahooKey} — resolves Yahoo key → HTTP redirect to /api/nfl/players/{gsisId}
GET /api/grades?season=&position=&limit=&offset= — real-life player grades; position supports comma-separated (e.g. RB,WR,TE)
GET /api/grades/{gsisId} — all seasons of grades for a player
Protected (RequireAuth):
GET /api/auth/me
POST /api/sync
GET /api/leagues/{id}/scoreboard?week=N
GET /api/leagues/{id}/standings
GET /api/leagues/{id}/players?search=q
GET /api/leagues/{id}/players/available?position=&start=&status=
GET /api/leagues/{id}/draftresults
GET /api/leagues/{id}/keepers
GET /api/leagues/{id}/keeper-rules
PUT /api/leagues/{id}/keeper-rules
GET /api/leagues/{id}/keeper-summary
GET /api/leagues/{id}/rankings?stat_type=season
GET /api/leagues/{id}/draft-values?season=&format=ppr|half|standard&budget=200
GET /api/teams/{id}/roster?stat_type=lastweek|season|today (or ?week=N)
GET /api/teams/{id}/keepers
POST /api/teams/{id}/keepers/{playerKey}
DELETE /api/teams/{id}/keepers/{playerKey}
POST /api/teams/{id}/keepers/submit
DELETE /api/teams/{id}/keepers/submit
cd backend)make run # go run ./cmd/api
make build # go build -o bin/api ./cmd/api
make test # go test ./...
make migrate-up # run migrations up (requires DATABASE_URL env)
make migrate-down # roll back one migration
make generate # sqlc generate (regenerates internal/db/queries/)
make import-nfl # import nflverse data (default: 2020-2024)
make import-nfl ARGS="-from 2015 -to 2024" # custom year range
make import-nfl ARGS="-rosters-only" # just player metadata
make import-nfl ARGS="-stats-only" # just weekly stats
make project-nfl ARGS="-profiles" # build player season profiles (run after import)
make project-nfl ARGS="-project -season 2025" # compute comp-based projections
make project-nfl ARGS="-grades" # compute real-life player grades (0-100)
make project-nfl ARGS="-all -season 2025" # profiles + grades + projections
make backtest-nfl ARGS="-from 2015 -to 2024" # backtest projections across historical seasons
make autotune-nfl ARGS="-from 2015 -to 2024 -train-to 2021" # auto-tune weights, saves projection_config.json
Run a single test:
go test ./internal/handlers/... -run TestHealthHandler
cd frontend)yarn dev # Vite dev server on :5173 (proxies /api and /auth to :8080)
yarn build # tsc + vite build → dist/
yarn lint # eslint
cp .env.example .env
docker compose up # starts db + backend + frontend
docker compose up db # just PostgreSQL on :5432
Copy .env.example → .env. Required:
DATABASE_URL — e.g. postgres://fantasy:fantasy@localhost:5432/fantasy_sportsPORT — defaults to 8080YAHOO_CLIENT_ID, YAHOO_CLIENT_SECRET, YAHOO_REDIRECT_URLSESSION_SECRET — random 32+ char string*Handler; use r.Context().Value(models.UserContextKey) for current user in protected routesyahoo.NewClient(ctx, db, oauthConfig, userID, accessToken, refreshToken, expiry); tokens auto-refresh and persist to DBtype=week, type=lastweek, type=date;date=YYYY-MM-DD, etc.)roster[].stats[].label — no hardcoded stat IDssort_order field ("1" = higher is better, "0" = lower is better) is passed through to the frontend for correct winner determination in MatchupDetailanalysis.go concurrently fetches rosters, scoring categories, and top-25 FA stats. Category weights = CV × scarcity (normalised): CV = stdev/|mean|; scarcity = 1/(1 + max(0, avgFAz)). overall_score = weighted z-sum. position_score = z-score within position group (independent). RankedPlayer response includes position_score + position_rank. Frontend: TeamDetail RosterTable shows Value column (+8.3 #4 overall, PG #2 position) + color-coded stat cells. See docs/ranking-algorithm.mdcmd/import/ downloads roster + player_stats CSVs from nflverse GitHub releases, upserts into nfl_players and nfl_player_stats. Idempotent (ON CONFLICT upserts). Data available from 1999–present; default imports 2020–2024. nfl_players.yahoo_id links to Yahoo fantasy player keys for cross-referencing.cmd/projections/main.go is a batch CLI tool. Step 1 (-profiles) aggregates nfl_player_stats into per-player, per-season profiles with pre-computed z-scores stored as JSONB. Step 2 (-project) finds similar historical players (similarity threshold ≥ 0.60, not a fixed count) using weighted Euclidean distance on z-scored dimensions, then applies their post-match development trajectories (weighted by ) to project the target player. Comp count is itself a signal: many comps = common archetype (higher confidence), few/zero = unique profile. Draft capital only used as a similarity dimension for players with < 3 years experience. See .vite-plugin-basic-ssl (required for Yahoo OAuth)similarity²docs/projection-algorithm.mdcmd/projections/backtest.go defines projConfig (similarity threshold, age window, per-position dimension weights). Reads projection_config.json if it exists; otherwise uses hardcoded defaults. Auto-tuner (-autotune) does coordinate descent over these parameters across training seasons and saves the best config. -backtest runs temporal-integrity backtesting (only prior-season data used) and stores RMSE/MAE/correlation metrics in nfl_backtest_results.GET /api/nfl/players/{gsisId} returns metadata + year-over-year season stats + projection (if exists). Player rows in all tables (rosters, rankings, matchup, players tab, draft tab) are clickable and navigate to /players/:gsisId. Yahoo→GSIS lookup via nfl_players.yahoo_id; batch ANY() query for rosters, per-request map for rankings.league.sport === 'nfl'). Uses GET /api/leagues/{id}/draft-values to fetch league-specific VOR + auction values based on actual roster settings (superflex-aware). Position filter + PPR/Half/Standard format toggle. /projections/:gsisId routes redirect to /players/:gsisId.cmd/projections/grades.go; (2) Stat Projections — comp-based; (3) Fantasy League Value — VORP/z-scores. Grades use position-specific sub-score weights (production, efficiency, usage, durability). Computed via make project-nfl ARGS="-grades". nfl_player_grades table stores results. Grade z-score (overall_grade_z) is injected into season profiles and used as a similarity dimension for comp matching (weight 1.25). Grade YoY trend applies a bounded ±5% adjustment to projected stats. Frontend: GradeCard on player detail, Grade column on projections/draft/players tabs, standalone /rankings page. Former Rankings tab absorbed into Players tab.sqlc.yaml exists but is unused; raw queries are preferred for their directness and flexibility with pgx features (e.g. ANY($1) with slices). Keep queries in handler methods, not in a separate query layer.