Frontend UX improvements: - Single-click Discord OAuth from home page (no intermediate /auth page) - Auto-redirect authenticated users from home to /games - Fixed Nuxt layout system - app.vue now wraps NuxtPage with NuxtLayout - Games page now has proper card container with shadow/border styling - Layout header includes working logout with API cookie clearing Games list enhancements: - Display team names (lname) instead of just team IDs - Show current score for each team - Show inning indicator (Top/Bot X) for active games - Responsive header with wrapped buttons on mobile Backend improvements: - Added team caching to SbaApiClient (1-hour TTL) - Enhanced GameListItem with team names, scores, inning data - Games endpoint now enriches response with SBA API team data Docker optimizations: - Optimized Dockerfile using --chown flag on COPY (faster than chown -R) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.0 KiB
Nuxt 4 Breaking Changes - Required Actions
Date: 2025-11-10 Status: Critical - Must Follow for All New Code
🚨 CRITICAL: Explicit Imports Required
Nuxt 4 removed auto-imports for Pinia stores and some composables. You MUST explicitly import these in your files.
❌ What No Longer Works (Nuxt 3 style):
<script setup lang="ts">
// This will cause "useAuthStore is not defined" error!
const authStore = useAuthStore()
</script>
✅ What You MUST Do (Nuxt 4 style):
<script setup lang="ts">
import { useAuthStore } from '~/store/auth' // ← REQUIRED!
const authStore = useAuthStore()
</script>
Required Explicit Imports
1. All Pinia Stores
// In pages, components, middleware, plugins:
import { useAuthStore } from '~/store/auth'
import { useGameStore } from '~/store/game'
import { useUiStore } from '~/store/ui'
2. Middleware Files
ALWAYS import stores in middleware:
// middleware/auth.ts
import { useAuthStore } from '~/store/auth' // ← REQUIRED!
export default defineNuxtRouteMiddleware((to, from) => {
const authStore = useAuthStore()
// ... rest of middleware
})
3. Pages
<!-- pages/games/index.vue -->
<script setup lang="ts">
import { useAuthStore } from '~/store/auth' // ← REQUIRED!
import { useGameStore } from '~/store/game' // ← REQUIRED if using
const authStore = useAuthStore()
</script>
4. Components
<!-- components/GameCard.vue -->
<script setup lang="ts">
import { useGameStore } from '~/store/game' // ← REQUIRED!
const gameStore = useGameStore()
</script>
What Still Auto-Imports (No Explicit Import Needed)
These Nuxt/Vue composables still auto-import:
- ✅
ref,computed,watch,reactive, etc. (Vue) - ✅
useRoute,useRouter(Vue Router) - ✅
useState,useFetch,useAsyncData(Nuxt) - ✅
navigateTo,definePageMeta(Nuxt) - ✅
onMounted,onUnmounted(Vue lifecycle)
BUT NOT:
- ❌ Your custom stores (
useAuthStore,useGameStore, etc.) - ❌ Your custom composables in
composables/folder (sometimes - test to verify)
Quick Reference: When to Add Imports
| File Type | Needs Explicit Imports? | Example |
|---|---|---|
pages/*.vue |
✅ YES | import { useAuthStore } from '~/store/auth' |
components/*.vue |
✅ YES | import { useGameStore } from '~/store/game' |
middleware/*.ts |
✅ YES | import { useAuthStore } from '~/store/auth' |
plugins/*.ts |
✅ YES | import { useAuthStore } from '~/store/auth' |
store/*.ts |
✅ YES (for other stores) | import { useAuthStore } from './auth' |
composables/*.ts |
⚠️ MAYBE | Test - may need imports for stores |
Common Errors and Fixes
Error: "useAuthStore is not defined"
Location: Any .vue or .ts file
Fix: Add import { useAuthStore } from '~/store/auth' at top of <script> section
Error: "useGameStore is not defined"
Location: Any .vue or .ts file
Fix: Add import { useGameStore } from '~/store/game' at top of <script> section
Error: "useUiStore is not defined"
Location: Any .vue or .ts file
Fix: Add import { useUiStore } from '~/store/ui' at top of <script> section
Standard Import Pattern for New Files
Use this template for all new .vue files:
<template>
<!-- Your template -->
</template>
<script setup lang="ts">
// 1. Import stores (if needed)
import { useAuthStore } from '~/store/auth'
import { useGameStore } from '~/store/game'
// 2. Import types (if needed)
import type { GameState, Player } from '~/types'
// 3. Define page meta (if needed)
definePageMeta({
middleware: ['auth'],
})
// 4. Initialize stores
const authStore = useAuthStore()
const gameStore = useGameStore()
// 5. Composables (these auto-import, no need to import)
const route = useRoute()
const router = useRouter()
// 6. Component logic
const someValue = ref('')
// ...
</script>
Why This Changed
Nuxt 4 prioritizes explicit over implicit for better:
- Type safety
- Build performance
- Code clarity
- IDE support
The tradeoff is more boilerplate, but it prevents "magic" import bugs.
Verification Checklist
Before committing new code:
- Check all
useAuthStore()calls have import - Check all
useGameStore()calls have import - Check all
useUiStore()calls have import - Check middleware files have store imports
- Run dev server - no "X is not defined" errors
- Test page navigation - no 500 errors
Related Changes
This document relates to:
- Nuxt 4 Directory Structure: Added
srcDir: '.'tonuxt.config.ts(see.claude/PHASE_F1_NUXT_ISSUE.md) - TypeScript in Dev: Disabled
typeCheck: truein dev mode for performance
🚨 CRITICAL: No app/ Directory in Project Root
Added: 2025-12-03
In Nuxt 4, the app/ directory is a reserved special directory that takes precedence over root-level files like app.vue.
The Problem
If an app/app.vue file exists, Nuxt will use it instead of the root app.vue, even with srcDir: '.' configured. This can cause unexpected behavior like the default NuxtWelcome component rendering instead of your actual pages.
What To Avoid
frontend-sba/
├── app/ ← ❌ DO NOT CREATE THIS
│ └── app.vue ← Will override root app.vue!
├── app.vue ← ✅ Your actual app entry point
├── pages/
│ └── index.vue
└── nuxt.config.ts
If You See NuxtWelcome in Production
- Check if
app/directory exists:ls -la app/ - If it contains
app.vuewith<NuxtWelcome />, delete the entire directory:rm -rf app/ - Rebuild:
./start.sh rebuild prod
Why This Happens
Nuxt 4's initialization (npx nuxi init) creates an app/app.vue with the default welcome component. If you then set srcDir: '.' to use root-level directories, both files exist and app/ takes priority.
Always import your stores explicitly!