# Frontend SBA - Strat-O-Matic Baseball Association Web App ## Overview Vue 3 + Nuxt 3 frontend for the SBA league. Real-time game interface with WebSocket communication to backend. **Tech Stack**: Nuxt 4.1.3, TypeScript (strict), Tailwind CSS, Pinia, Socket.io-client, Discord OAuth ## CRITICAL: Nuxt 4 Breaking Changes **MUST READ**: `.claude/NUXT4_BREAKING_CHANGES.md` ### 1. Explicit Store Imports Required All Pinia stores MUST be explicitly imported: ```typescript // WRONG - will cause "useAuthStore is not defined": const authStore = useAuthStore() // CORRECT: import { useAuthStore } from '~/store/auth' const authStore = useAuthStore() ``` ### 2. No `app/` Directory Allowed **CRITICAL**: Do NOT create an `app/` directory in the frontend root. Nuxt 4 treats this as a special directory that overrides `app.vue`. If NuxtWelcome appears instead of your app, delete `app/` and rebuild. ## Project Structure ``` frontend-sba/ ├── components/ # See components/CLAUDE.md for inventory │ ├── Game/ # ScoreBoard, GameBoard, CurrentSituation, PlayByPlay │ ├── Decisions/ # DecisionPanel, DefensiveSetup, OffensiveApproach │ ├── Substitutions/ │ └── UI/ # ActionButton, ButtonGroup, ToggleSwitch ├── composables/ # See composables/CLAUDE.md for data flow │ ├── useWebSocket.ts # Connection, event handlers │ └── useGameActions.ts # Game action wrappers ├── store/ # See store/CLAUDE.md for patterns │ ├── auth.ts # Discord OAuth, HttpOnly cookie auth │ ├── game.ts # Game state, lineups, decisions │ └── ui.ts # Toasts, modals ├── types/ # See types/CLAUDE.md for mappings │ ├── game.ts # GameState, PlayResult │ ├── player.ts # SbaPlayer, Lineup │ └── websocket.ts ├── pages/ ├── layouts/ ├── middleware/ └── plugins/ ``` ## Development ```bash npm install # First time npm run dev # Dev server at http://localhost:3000 npm run type-check # Check types npm run lint # Lint code ``` ## Configuration ### Environment Variables Copy `.env.example` to `.env` and configure: ```bash # API endpoints NUXT_PUBLIC_API_URL=http://localhost:8000 NUXT_PUBLIC_WS_URL=http://localhost:8000 # Discord OAuth (public client ID - safe to expose) NUXT_PUBLIC_DISCORD_CLIENT_ID=your-client-id NUXT_PUBLIC_DISCORD_REDIRECT_URI=http://localhost:3000/auth/callback # Vite dev server allowed hosts (comma-separated) # Add your domain for external access NUXT_ALLOWED_HOSTS=localhost,127.0.0.1 ``` **Note**: `NUXT_ALLOWED_HOSTS` is read in `nuxt.config.ts` to configure Vite's `allowedHosts`. Required when accessing dev server through a reverse proxy or external domain. ### League Theme - Primary: #1e40af (SBA Blue) - Secondary: #dc2626 (SBA Red) ## Mobile-First Design - **Breakpoints**: xs(375px), sm(640px), md(768px), lg(1024px) - Touch-friendly: 44x44px minimum buttons - Sticky scoreboard, bottom sheets for inputs ## Key Architecture Concepts ### Data Resolution Pattern Game state contains minimal `LineupPlayerState` (lineup_id, position). Use `gameStore.findPlayerInLineup(lineupId)` to get full player data (name, headshot). ### Team Determination - Top of inning: away bats, home fields - Bottom of inning: home bats, away fields - Use `gameStore.battingTeamId` / `gameStore.fieldingTeamId` **Full details**: See subdirectory CLAUDE.md files for component inventory, data flow, store patterns, and type mappings. ## References - **WebSocket Protocol Spec**: `../.claude/WEBSOCKET_PROTOCOL_SPEC.md` - Complete event catalog and workflow - **Implementation Guide**: `../.claude/implementation/01-infrastructure.md` - **Full PRD**: `../prd-web-scorecard-1.1.md` --- **League**: SBA | **Port**: 3000 | **Last Updated**: 2025-01-19 ## Current Phase ### Phase F2: Game State Display - COMPLETE (2025-01-10) Components: ScoreBoard, GameBoard, CurrentSituation, PlayByPlay ### Phase F3: Decision Input Workflow - NEXT Components to integrate with live backend **See**: `.claude/implementation/NEXT_SESSION.md` for detailed plan