NBA Feed
팀 뉴스와 경기 정보를 제공, 점수는 직접 확인할 때까지 숨겨져 있습니다
NFL·대학 풋볼·NHL·MLB 개인 맞춤 동반자, 실시간 점수·순위·시즌 통계 제공
A personal companion for NFL, college football, NHL and MLB. Live scores, standings and season stats for only the teams and players you follow.
스포츠·피트니스TypeScript · SwiftGitHub @germanndarian온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Live demo ↗ · the only scores, standings and stats that matter — yours.
Most sports apps drown you in every game on earth. Frontrow does the opposite:
pick your teams and players once, and get a single, broadcast-grade dashboard that
shows only what you follow — live scores, recent form, next fixtures, standings,
and season stats.
Real accounts keep it in sync across devices, and the whole thing is yours to
re-skin. No noise. No clutter. Front-row seats.README 전문 보기 ↗Live demo ↗ · the only scores, standings and stats that matter — yours.
Most sports apps drown you in every game on earth. Frontrow does the opposite: pick your teams and players once, and get a single, broadcast-grade dashboard that shows only what you follow — live scores, recent form, next fixtures, standings, and season stats.
Real accounts keep it in sync across devices, and the whole thing is yours to re-skin. No noise. No clutter. Front-row seats.
Mood: a floodlit night game from the press box. Midnight slate, broadcast overlays, cobalt as the brand voice, a single live-red pulse, amber for the leaders.
| 🎟️ A dashboard that's only yours | No firehose — just live & upcoming, your teams, your players, and the standings around them. |
| 🔴 Live, but quiet | Auto-refresh polls only while a game is actually live. The rest of the time it's still and fast. |
| 🎨 Make it yours | 7 accent themes, corner roundness, density, motion & glow toggles, a custom greeting, default league, and per-section visibility. |
| 🔐 Real accounts | Supabase email + password auth with confirmation, Row-Level Security, and cross-device sync. |
| 📊 Stats with shape | Season-trend charts, output sparklines, recent form, and league-ranked player numbers. |
| 🌒 Considered everywhere | Loading, empty & error states on every surface; mobile-first; honors prefers-reduced-motion. |
git clone https://github.com/germanndarian/frontrow.git
cd frontrow
npm install
cp .env.example .env.local # add the two public Supabase values (below)
npm run dev # → http://localhost:3000
npm run build && npm run start # production build · Node 18.18+ (built on 24)
ESPN needs no API key — it's read through keyless public endpoints, server-side.
Accounts need Supabase: in production the Vercel integration injects everything;
for local dev, add the two browser-safe values to .env.local.
| Variable | Purpose | Required |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase project URL | ✅ |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Public anon key (RLS-guarded) | ✅ |
SUPABASE_SERVICE_ROLE_KEY | Server-only — account deletion | — |
NEXT_PUBLIC_LIVE_POLL_MS | Live-game refresh cadence | 30000 |
NEXT_PUBLIC_USE_MOCK | Run fully offline on the demo dataset | false |
Apply the schema once from supabase/migrations/0001_init.sql
(Supabase → SQL Editor) — it creates profiles / preferences / settings,
Row-Level Security so a user only ever touches their own rows, and a trigger that
seeds defaults on signup.
┌───────────────┐ ┌─────────────────────┐ ┌──────────────┐
Browser ──▶│ /api/* handlers│ ──▶ │ ESPN (cached · 8s │ ──▶ │ normalizer │ ──▶ UI
│ (server) │ │ timeout · retry-once)│ │ (defensive) │
└───────────────┘ └─────────────────────┘ └──────────────┘
Accounts ─▶ Supabase Auth (cookies · @supabase/ssr) ─▶ Postgres + RLS ◀─ follows & settings
The browser never calls ESPN directly. Each surface is cached server-side (scoreboard 20s · team/standings/player 5m · teams/rosters 24h) and the client polls only while a game is live. Every normalizer is defensive, so an upstream field change degrades to a placeholder instead of a crash.
| Route | Source |
|---|---|
GET /api/scoreboard?leagues= | {sport}/{league}/scoreboard |
GET /api/team/[id]?league= | team detail + teams/{id}/schedule |
GET /api/standings/[league] | v2/.../standings?level=3 |
GET /api/player/[id]?league= | athletes/{id} + athletes/{id}/gamelog |
GET /api/teams · /api/roster | onboarding selectors |
GET /auth/confirm · DELETE /api/account | email confirm · account deletion |
Next.js 16 · React 19 · TypeScript · Tailwind CSS v4 (OKLCH tokens)
Supabase (Auth · Postgres · RLS) · TanStack Query · Zustand · Motion · Recharts
Vitest · Playwright · GitHub Actions · Vercel (Analytics · Speed Insights)
src/
app/
layout.tsx Fonts + providers + Analytics / Speed Insights
page.tsx Dashboard (auth-gated)
login/ · setup/ Email auth · four-step onboarding
settings/ Profile · appearance · dashboard · follows
auth/confirm/route.ts Email-confirmation handler
api/ ESPN route handlers + /api/account
globals.css OKLCH design tokens, base styles, keyframes
lib/
supabase/ Browser + server clients (@supabase/ssr)
auth.ts · sync.ts Supabase Auth store · follows & settings ⇄ Postgres
store.ts · settings.ts In-memory working state (DB-backed)
espn/ Server-only ESPN integration
leagues.ts · types.ts League config + normalized domain models
components/ dashboard · setup · ui · system · brand
supabase/migrations/ SQL schema + Row-Level Security
main is protected — nothing merges red. Every PR runs:
npm run lint # ESLint
npx tsc --noEmit # type-check
npm test # Vitest · pure functions in src/lib
npm run e2e # Playwright · every screen, Chromium + WebKit
npm run build # production build
Both suites are hermetic — the browser tests drive the real app against the bundled
demo dataset, so no ESPN and no Supabase. A separate npm run e2e:upstream calls
ESPN for real and stays out of the merge gate, so a third party can't block a
release. Its twice-a-day schedule is paused for now; run it by hand from
Actions → Upstream watch → Run workflow.
Frontrow · unofficial data via ESPN's public endpoints, refreshed as games unfold.
Built for the only seats worth having — front row. 🏟️