A pseudo NBA investment platform where users invest in players rated by a PR Score — a composite of in-game stats and social media sentiment analysis.
This repo is Courtside, the Next.js frontend. The Python backend (Combine) lives in cicero-scripts.
| Layer | Tool |
|---|---|
| Framework | Next.js 15 (App Router, Turbopack) |
| Language | TypeScript |
| Styling | Tailwind CSS v4, Radix UI, shadcn/ui |
| Auth | Better Auth v1.6 (Google OAuth) |
| Database | Neon (PostgreSQL) via Drizzle ORM |
| File Uploads | Uploadthing |
| Data Fetching | TanStack Query v5 |
| Animations | Motion (Framer Motion) |
| Charts | Recharts |
| Forms | React Hook Form + Zod |
| Deployment | Vercel |
- Node.js >= 20
- A Google OAuth app (Client ID + Secret)
- A Neon database
- A Better Auth secret
- An Uploadthing account
1. Clone and install
git clone <repo-url>
cd cicero
npm install2. Set up environment variables
Copy the example below into .env.local and fill in your values:
# Better Auth
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000
# Google OAuth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Database
DRIZZLE_DATABASE_URL=
# Uploadthing
UPLOADTHING_TOKEN=3. Push the database schema
npm run db:push4. Start the dev server
npm run devApp runs at http://localhost:3000.
| Command | What it does |
|---|---|
npm run dev |
Start dev server with Turbopack |
npm run build |
Production build |
npm run lint |
Run ESLint |
npm run generate |
Generate Drizzle migration files |
npm run db:push |
Push schema changes directly to DB |
npm run studio |
Open Drizzle Studio (DB browser) |
npm run seed |
Seed the database |
app/
(main)/ # Authenticated routes (dashboard, players, users)
(public)/ # Public routes (login, landing)
onboarding/ # Onboarding flow (runs after first login)
api/ # API routes (auth, users, uploadthing)
components/ # Shared UI components
lib/ # Auth config, data fetching, type definitions
server/
db/ # Drizzle schema + client
middleware.ts # Auth + onboarding redirect logic
- User clicks "Sign in with Google" → Better Auth initiates OAuth flow
- Google redirects back → Better Auth creates
usersrow withonboarding_status=false - Middleware checks session + onboarding status:
- No session → redirect to
/login - Session but not onboarded → redirect to
/onboarding - Onboarded → allow access to protected routes
- No session → redirect to
- Onboarding form POSTs to
/api/users/complete-onboarding→ flipsonboarding_status=true
| Environment | Branch | URL | Neon DB |
|---|---|---|---|
| Local | — | http://localhost:3000 |
main branch |
| Staging | staging |
cicero-git-staging-noel-alfaros-projects.vercel.app |
staging branch |
| Production | main |
cicero-coral.vercel.app |
main branch |
BETTER_AUTH_URL and DRIZZLE_DATABASE_URL differ per environment. All other env vars are shared.
Branches:
main— production, always stablestaging— permanent beta environment for live testing, never merges into maincrt-XX-short-description— feature branches, always off latestmain
Starting a ticket:
git checkout main && git pull
git checkout -b crt-XX-short-descriptionBefore merging a PR — test on staging:
git checkout staging && git pull
git merge crt-XX-short-description
git push # triggers Vercel staging deploy
# verify on staging URL, check the AC box, then merge PR → mainAfter merging to main — reset staging:
git checkout staging
git fetch origin
git reset --hard origin/main
git push --force # staging mirrors main again- Combine (Python backend):
cicero-scriptsrepo — owned by Bryan - Linear: Courtside project — P1 (User Platform) active through mid-May 2026
- Vercel: Deployed on Vercel, preview deploys on every PR