Skip to content

Latest commit

 

History

103 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

iRace

iRace is an invite-only fitness challenge app powered by Strava: set a goal, share a link, and race your crew on real activities. Not affiliated with Strava.

Live: iraceapp.vercel.app


Screenshots

Captures live in docs/strava-submission-screenshots/ — the same set used for Strava API review.

Landing and home

Landing page Signed in
Landing — hero, CTAs, footer links Home with user in header

Challenges: create, join, race

Creator consent (step 2) Join + participant consent
Create challenge — acknowledgement Join flow — consent and Connect Strava
Demo race / leaderboard
Race view — demo challenge

Profile and Strava connection

Connected Not connected
Settings — Strava connected, disconnect Settings — not connected

Privacy and terms

Privacy Policy Terms
Privacy Policy (full page) Terms (full page)

Strava OAuth (on Strava)

After choosing Connect Strava, Strava handles login and authorization:

Strava login Authorize app (scopes)
Strava.com login Strava authorize — profile and activities

Features

  • Strava OAuth with activity-based progress toward distance goals
  • Multi-sport challenges (running, cycling, swimming, and more) with per-sport goals
  • Shareable invite links, plus a demo challenge for trying the UI without connecting Strava
  • Profile dashboard: lifetime stats, activity heatmap, streaks and PBs, head-to-head, challenge history
  • Taunts between participants, and optional web push notifications
  • English and Spanish, light and dark
  • Responsive UI (React, Tailwind, framer-motion)

Tech stack

  • Frontend: React 18, TypeScript, Vite, Tailwind CSS, framer-motion, react-router-dom v7
  • Backend: Vercel serverless functions (TypeScript) under api/
  • Database: PostgreSQL via Prisma, hosted on Neon
  • Auth: Custom JWT access tokens + opaque refresh tokens — no next-auth
  • External: Strava OAuth 2.0, REST, and webhooks — all server-side

See docs/ARCHITECTURE.md for how the pieces fit.

Quick start

Prerequisites: Node.js 20+, npm, and a PostgreSQL instance (local or hosted).

git clone https://github.com/FelixBC/irace
cd irace
npm install          # also runs prisma generate
npm run dev          # http://localhost:5173

Copy .env.example to .env and fill it in. The minimum to boot:

# Server — never exposed to the browser
DATABASE_URL=postgresql://...
DATABASE_URL_UNPOOLED=postgresql://...   # same value for local Postgres
AUTH_SESSION_SECRET=a_long_random_string
STRAVA_CLIENT_ID=your_strava_client_id
STRAVA_CLIENT_SECRET=your_strava_client_secret
FRONTEND_URL=http://localhost:5173

# Browser — public, ships in the bundle
VITE_STRAVA_CLIENT_ID=your_strava_client_id
VITE_SUPPORT_EMAIL=you@yourdomain.com

AUTH_SESSION_SECRET signs 15-minute access JWTs and hashes 30-day refresh tokens; auth routes error at runtime without it. Never put STRAVA_CLIENT_SECRET behind a VITE_ prefix — that would ship it to every browser.

In Strava API Settings, set Authorization Callback Domain to your hostname only (no scheme, no path). localhost is always allowed for dev.

npm run dev serves the frontend only. For the API routes you also need the Vercel CLI (vercel dev). Full environment reference: docs/DEPLOYMENT.md.

Before you push

npm run verify       # typecheck (both TS projects) + lint + tests
npm run compliance   # Strava brand rules
npm run build        # prisma generate + production build

CI runs all three on every push and PR to main, but running them locally is faster than waiting. Also scan git status for stray files, and confirm no secret is in the diff — STRAVA_CLIENT_SECRET, AUTH_SESSION_SECRET, DB passwords, VAPID private keys, and webhook tokens belong in env vars only.

Scripts

Command Description
npm run dev Vite dev server
npm run build prisma generate + production build
npm run preview Preview the production build
npm run verify function-count + typecheck + lint + tests — the quality gate
npm run check:functions Guards Vercel's 12-function Hobby ceiling
npm run typecheck TypeScript for both projects (api/+server/+shared/, then src/)
npm run lint ESLint
npm test / npm run test:watch Vitest
npm run compliance Strava brand and trademark checks
npm run db:setup / npm run db:clean Local database helpers
npm run generate-vapid Generate web push VAPID keys
npm run strava:webhook-register Register the Strava webhook subscription
npm run strava:encrypt-tokens One-shot re-encryption of stored Strava tokens

Docker

Optional local Postgres and Redis, defined in docker-compose.yml:

docker compose up -d

Point DATABASE_URL and DATABASE_URL_UNPOOLED at the postgres service to use it.

Documentation

Doc What it covers
ARCHITECTURE.md Runtimes, the Strava token boundary, API surface, auth, data
DEPLOYMENT.md Database, every env var, the canonical domain, rollout hazards
STRAVA_COMPLIANCE.md Strava's rules, reviewer checklist, open risk register
STRAVA_SUBMISSION.md Submission copy, scopes, screenshots, pre-flight
STRAVA_WEBHOOK.md Webhook subscription setup
DESIGN_SYSTEM.md Tokens, components, visual language
WEB_PUSH.md Push notification setup
REAL_APP_ENGINEERING_GUIDE.md What production apps need, mapped onto this codebase

Contributor and agent conventions live in CLAUDE.md.

Contributing

  1. Branch from main
  2. Make focused changes with clear commit messages
  3. npm run verify must pass
  4. Open a pull request

License

MIT

About

iRace is a real-time fitness challenge app: race friends using your Strava activities. Think TypeRacer meets group goals. Not affiliated with Strava.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages