Overview
Basketball TicTacToe is a pnpm workspace monorepo for an NBA trivia grid game inspired by tic tac toe.
Players fill a 3×3 board by naming real NBA players who match both the row and column criteria for each square.
Stack
- Monorepo:
pnpmworkspaces - Language: TypeScript
- Frontend: React, Vite, Tailwind CSS, shadcn/ui, framer-motion
- Backend: Express 5
- Validation: Zod, drizzle-zod
- API codegen: Orval
- Database: PostgreSQL with Drizzle ORM
- AI validation: Google Gemini via
@google/genai
Workspace Structure
Basketball-TicTacToe/
├── artifacts/
│ ├── api-server/ # Express API server
│ ├── mockup-sandbox/ # Separate Vite sandbox artifact
│ └── ttt-basketball/ # Main React + Vite app
├── lib/
│ ├── api-client-react/ # Generated React Query client
│ ├── api-spec/ # OpenAPI spec + Orval config
│ ├── api-zod/ # Generated Zod schemas
│ └── db/ # Drizzle schema + DB connection
├── scripts/
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.base.json
Game Modes
- Local Multiplayer
- Online Multiplayer
- Solo Box-Out Challenge
Core Features
- Random NBA trivia grids generated by the backend
- Optional steal mode
- Era selection:
all,90s,2000s,2010s,modern - Fast local validation from curated known intersections
- Gemini fallback validation with Google Search grounding when needed
- Online rooms backed by PostgreSQL when
DATABASE_URLis configured - In-memory online room fallback for local development when
DATABASE_URLis missing
Main Routes
/home page/locallocal multiplayer/solosolo challenge/online/lobbycreate/join online rooms/online/game/:codelive online match
API Endpoints
POST /api/game/gridgenerate a solvable 3×3 gridPOST /api/game/validatevalidate a player against row and column criteriaPOST /api/game/roomscreate an online roomGET /api/game/rooms/:codeget room statePOST /api/game/rooms/:code/joinjoin a roomPOST /api/game/rooms/:code/movemake a moveGET /api/healthzhealth check
Local Development
Requirements
- Node.js 22+ recommended
pnpm
Install
pnpm install
Frontend Environment
Create or update:
artifacts/ttt-basketball/.env
VITE_API_URL=http://localhost:5000
GEMINI_API_KEY=your_key_here
Notes:
VITE_API_URLis used by the frontend.GEMINI_API_KEYis loaded by the API server through the shared env loader.- You can also place env vars in a root
.envorartifacts/api-server/.env.
Start Everything
pnpm run dev:ttt
This does all of the following:
- builds the API server
- starts the API server on
http://localhost:5000 - starts the Vite frontend on its dev port
Manual Start
Backend:
pnpm --filter @workspace/api-server run build
node --enable-source-maps artifacts/api-server/dist/index.mjs
Frontend:
pnpm --filter @workspace/ttt-basketball run dev
Database Behavior
- If
DATABASE_URLis set, online rooms use PostgreSQL. - If
DATABASE_URLis not set, online rooms fall back to in-memory storage for local testing. - In-memory rooms are lost when the backend restarts.
Validation Behavior
Player validation works in two layers:
- Fast local validation using curated intersections in
artifacts/api-server/src/lib/nbaData.ts - Gemini validation for cases not covered by the curated dataset
The validator prompt date is generated dynamically at runtime.
SEO and Metadata
The frontend includes:
- canonical URLs
- route-level titles and descriptions
- Open Graph and Twitter metadata
- JSON-LD structured data
robots.txtsitemap.xmlllms.txt- favicon, Apple touch icon, and web manifest support




