# 🏗️ ThrillWiki Nuxt Frontend - Architecture Decisions **Status:** ✅ COMPLETE **Last Updated:** 2025-01-27 19:58 UTC **Dependencies:** requirements.md **Blocks:** All implementation phases ## 🎯 Architecture Overview ### System Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ ThrillWiki System │ ├─────────────────────────────────────────────────────────────┤ │ Frontend (Nuxt 3) │ Backend (Django) │ │ ┌─────────────────────┐ │ ┌─────────────────────┐ │ │ │ Pages & Components │ │ │ REST API (/api/v1/) │ │ │ │ ├─ Parks │ │ │ ├─ Authentication │ │ │ │ ├─ Rides │ │ │ ├─ Parks CRUD │ │ │ │ ├─ Auth │ │ │ ├─ Rides CRUD │ │ │ │ └─ Admin │ │ │ ├─ Photos │ │ │ └─────────────────────┘ │ │ └─ Moderation │ │ │ ┌─────────────────────┐ │ └─────────────────────┘ │ │ │ Composables │ │ ┌─────────────────────┐ │ │ │ ├─ useAuth │◄───┼──┤ JWT Authentication │ │ │ │ ├─ useApi │◄───┼──┤ Token Management │ │ │ │ ├─ useParks │◄───┼──┤ CORS Configuration │ │ │ │ └─ useRides │ │ └─────────────────────┘ │ │ └─────────────────────┘ │ │ │ ┌─────────────────────┐ │ ┌─────────────────────┐ │ │ │ Component Library │ │ │ Database (PostgreSQL)│ │ │ │ ├─ UI Components │ │ │ ├─ Parks │ │ │ │ ├─ Forms │ │ │ ├─ Rides │ │ │ │ ├─ Navigation │ │ │ ├─ Users │ │ │ │ └─ Modals │ │ │ └─ Photos │ │ │ └─────────────────────┘ │ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### Technology Stack Decisions #### Frontend Framework: Nuxt 3 **Decision:** Use Nuxt 3 with Vue 3 Composition API **Rationale:** - **Server-Side Rendering:** Better SEO and initial load performance - **File-based Routing:** Intuitive page organization - **Auto-imports:** Reduced boilerplate code - **Built-in Optimization:** Image optimization, code splitting, etc. - **TypeScript Support:** First-class TypeScript integration - **Ecosystem:** Rich ecosystem with modules and plugins **Alternatives Considered:** - **Next.js:** Rejected due to React requirement - **SvelteKit:** Rejected due to smaller ecosystem - **Vite + Vue:** Rejected due to lack of SSR out-of-the-box #### State Management: Pinia **Decision:** Use Pinia for global state management **Rationale:** - **Vue 3 Native:** Built specifically for Vue 3 - **TypeScript Support:** Excellent TypeScript integration - **DevTools:** Great debugging experience - **Modular:** Easy to organize stores by feature - **Performance:** Optimized for Vue 3 reactivity **Alternatives Considered:** - **Vuex:** Rejected due to Vue 3 compatibility issues - **Composables Only:** Rejected for complex state management needs #### Component Library: TBD (User Choice Required) **Status:** ⏳ PENDING USER DECISION **Options Analyzed:** ##### Option 1: Nuxt UI (Recommended) ```typescript // Installation npm install @nuxt/ui // Configuration export default defineNuxtConfig({ modules: ['@nuxt/ui'], ui: { global: true, icons: ['heroicons'] } }) ``` **Pros:** - Built specifically for Nuxt 3 - Tailwind CSS integration - Headless UI foundation (accessibility) - TypeScript support - Modern design system - Tree-shakable **Cons:** - Newer library (less mature) - Smaller component set - Limited complex components ##### Option 2: Vuetify ```typescript // Installation npm install vuetify @mdi/font // Configuration import { createVuetify } from 'vuetify' export default defineNuxtPlugin(() => { const vuetify = createVuetify({ theme: { defaultTheme: 'light' } }) return { provide: { vuetify } } }) ``` **Pros:** - Mature, battle-tested - Comprehensive component set - Material Design system - Strong community - Good documentation **Cons:** - Large bundle size - Material Design constraints - Vue 3 support still evolving - Less customizable ##### Option 3: PrimeVue ```typescript // Installation npm install primevue primeicons // Configuration import PrimeVue from 'primevue/config' export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(PrimeVue) }) ``` **Pros:** - Enterprise-focused - Comprehensive components - Good TypeScript support - Professional themes - Accessibility features **Cons:** - Commercial themes cost - Learning curve - Less modern design - Larger bundle size #### Authentication: JWT with Refresh Tokens **Decision:** Implement JWT authentication with refresh token mechanism **Rationale:** - **Stateless:** No server-side session storage required - **Scalable:** Works well with multiple frontend instances - **Secure:** Short-lived access tokens with refresh mechanism - **Standard:** Industry standard for API authentication **Implementation Strategy:** ```typescript // composables/useAuth.ts export const useAuth = () => { const accessToken = useCookie('access_token', { httpOnly: true, secure: true, sameSite: 'strict', maxAge: 15 * 60 // 15 minutes }) const refreshToken = useCookie('refresh_token', { httpOnly: true, secure: true, sameSite: 'strict', maxAge: 7 * 24 * 60 * 60 // 7 days }) const refreshAccessToken = async () => { // Auto-refresh logic } return { login, logout, refreshAccessToken, isAuthenticated: computed(() => !!accessToken.value) } } ``` #### API Integration: Custom Composables with $fetch **Decision:** Use Nuxt's built-in $fetch with custom composables **Rationale:** - **Built-in:** No additional HTTP client needed - **SSR Compatible:** Works seamlessly with server-side rendering - **Type Safe:** Full TypeScript support - **Caching:** Built-in request caching - **Error Handling:** Consistent error handling patterns **Implementation Pattern:** ```typescript // composables/useApi.ts export const useApi = () => { const { $fetch } = useNuxtApp() const { accessToken } = useAuth() const apiCall = async (endpoint: string, options: any = {}) => { return await $fetch(`/api/v1${endpoint}`, { ...options, headers: { 'Authorization': `Bearer ${accessToken.value}`, ...options.headers } }) } return { apiCall } } ``` ### Project Structure Decisions #### Directory Structure ``` frontend/ ├── assets/ # Static assets (images, fonts, etc.) ├── components/ # Vue components │ ├── ui/ # UI library components │ ├── layout/ # Layout components │ ├── forms/ # Form components │ └── features/ # Feature-specific components │ ├── parks/ # Park-related components │ ├── rides/ # Ride-related components │ ├── auth/ # Authentication components │ └── admin/ # Admin/moderation components ├── composables/ # Vue composables │ ├── useAuth.ts # Authentication logic │ ├── useApi.ts # API integration │ ├── useParks.ts # Parks data management │ ├── useRides.ts # Rides data management │ └── useModeration.ts # Moderation logic ├── layouts/ # Nuxt layouts │ ├── default.vue # Default layout │ ├── auth.vue # Authentication layout │ └── admin.vue # Admin layout ├── middleware/ # Route middleware │ ├── auth.ts # Authentication middleware │ └── admin.ts # Admin access middleware ├── pages/ # File-based routing │ ├── index.vue # Homepage │ ├── parks/ # Parks pages │ ├── rides/ # Rides pages │ ├── auth/ # Authentication pages │ └── admin/ # Admin pages ├── plugins/ # Nuxt plugins │ ├── api.client.ts # API configuration │ └── context7.client.ts # Context7 integration ├── stores/ # Pinia stores │ ├── auth.ts # Authentication store │ ├── parks.ts # Parks store │ └── ui.ts # UI state store ├── types/ # TypeScript type definitions │ ├── api.ts # API response types │ ├── auth.ts # Authentication types │ └── components.ts # Component prop types ├── utils/ # Utility functions │ ├── validation.ts # Form validation │ ├── formatting.ts # Data formatting │ └── constants.ts # Application constants ├── nuxt.config.ts # Nuxt configuration ├── package.json # Dependencies └── tsconfig.json # TypeScript configuration ``` ### Development Environment Decisions #### Package Manager: npm **Decision:** Use npm for package management **Rationale:** - **Consistency:** Matches existing project setup - **Reliability:** Stable and well-supported - **Lock File:** package-lock.json for reproducible builds - **CI/CD:** Easy integration with deployment pipelines #### Development Server Configuration ```typescript // nuxt.config.ts export default defineNuxtConfig({ devtools: { enabled: true }, // Development server configuration devServer: { port: 3000, host: '0.0.0.0' }, // Proxy API calls to Django backend nitro: { devProxy: { '/api': { target: 'http://localhost:8000', changeOrigin: true } } }, // Runtime configuration runtimeConfig: { public: { apiBase: process.env.NUXT_PUBLIC_API_BASE || 'http://localhost:8000/api/v1' } } }) ``` #### Environment Variables ```bash # .env NUXT_PUBLIC_API_BASE=http://localhost:8000/api/v1 NUXT_SECRET_JWT_SECRET=your-jwt-secret NUXT_PUBLIC_APP_NAME=ThrillWiki NUXT_PUBLIC_APP_VERSION=1.0.0 ``` ### Performance Optimization Decisions #### Code Splitting Strategy **Decision:** Implement route-based and component-based code splitting **Implementation:** ```typescript // Lazy load heavy components const PhotoGallery = defineAsyncComponent(() => import('~/components/PhotoGallery.vue')) // Route-based splitting (automatic with Nuxt) // pages/admin/ - Admin bundle // pages/parks/ - Parks bundle // pages/rides/ - Rides bundle ``` #### Image Optimization **Decision:** Use Nuxt Image module for automatic optimization **Configuration:** ```typescript // nuxt.config.ts export default defineNuxtConfig({ modules: ['@nuxt/image'], image: { provider: 'ipx', quality: 80, format: ['webp', 'avif', 'jpg'], screens: { xs: 320, sm: 640, md: 768, lg: 1024, xl: 1280 } } }) ``` #### Caching Strategy **Decision:** Multi-layer caching approach **Layers:** 1. **Browser Cache:** Static assets with long cache times 2. **API Cache:** Response caching with TTL 3. **Component Cache:** Expensive component computations 4. **Route Cache:** Static route pre-generation ```typescript // API caching example export const useParks = () => { const { data: parks } = useLazyFetch('/api/v1/parks/', { key: 'parks-list', server: true, default: () => [], transform: (data: any) => data.results || data }) return { parks } } ``` ### Security Decisions #### Token Storage **Decision:** Use HTTP-only cookies for token storage **Rationale:** - **XSS Protection:** Tokens not accessible via JavaScript - **CSRF Protection:** SameSite cookie attribute - **Automatic Handling:** Browser handles cookie management #### Input Validation **Decision:** Client-side validation with server-side verification **Implementation:** ```typescript // utils/validation.ts import { z } from 'zod' export const parkSchema = z.object({ name: z.string().min(1).max(100), location: z.string().min(1), operator: z.string().optional(), status: z.enum(['OPERATING', 'CLOSED', 'UNDER_CONSTRUCTION']) }) export type ParkInput = z.infer ``` #### CORS Configuration **Decision:** Strict CORS policy for production **Django Configuration:** ```python # backend/config/settings/production.py CORS_ALLOWED_ORIGINS = [ "https://thrillwiki.com", "https://www.thrillwiki.com" ] CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_ALL_ORIGINS = False # Never true in production ``` ### Testing Strategy Decisions #### Testing Framework: Vitest **Decision:** Use Vitest for unit and component testing **Rationale:** - **Vite Integration:** Fast test execution - **Vue Support:** Excellent Vue component testing - **TypeScript:** Native TypeScript support - **Jest Compatible:** Familiar API for developers #### E2E Testing: Playwright **Decision:** Use Playwright for end-to-end testing **Rationale:** - **Cross-browser:** Chrome, Firefox, Safari support - **Mobile Testing:** Mobile browser simulation - **Reliable:** Stable test execution - **Modern:** Built for modern web applications #### Testing Configuration ```typescript // vitest.config.ts import { defineConfig } from 'vitest/config' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], test: { environment: 'happy-dom', coverage: { reporter: ['text', 'json', 'html'], threshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } } } } }) ``` ### Deployment Decisions #### Build Strategy **Decision:** Hybrid rendering with static generation for public pages **Configuration:** ```typescript // nuxt.config.ts export default defineNuxtConfig({ nitro: { prerender: { routes: [ '/', '/parks', '/rides', '/about', '/privacy', '/terms' ] } }, // Route rules for different rendering strategies routeRules: { '/': { prerender: true }, '/parks': { prerender: true }, '/rides': { prerender: true }, '/admin/**': { ssr: false }, // SPA mode for admin '/auth/**': { ssr: false } // SPA mode for auth } }) ``` #### Docker Configuration **Decision:** Multi-stage Docker build for production **Dockerfile:** ```dockerfile # Build stage FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build # Production stage FROM node:18-alpine AS production WORKDIR /app COPY --from=builder /app/.output ./ EXPOSE 3000 CMD ["node", "server/index.mjs"] ``` ### Context7 Integration Decisions #### Documentation Strategy **Decision:** Integrate Context7 for automatic documentation generation **Implementation:** ```typescript // plugins/context7.client.ts export default defineNuxtPlugin(() => { if (process.dev) { // Initialize Context7 connection const context7 = new Context7Client({ endpoint: 'http://localhost:8080', project: 'thrillwiki-frontend' }) // Auto-document API calls context7.trackApiCalls() // Document component usage context7.trackComponentUsage() } }) ``` #### Knowledge Preservation **Decision:** Structured documentation with progress tracking **Features:** - Automatic API endpoint documentation - Component usage tracking - Implementation decision logging - Progress milestone tracking - LLM handoff preparation --- ## 🔧 Implementation Priorities ### Phase 1: Foundation (Week 1) 1. **Project Setup:** Initialize Nuxt 3 with TypeScript 2. **Component Library:** Integrate chosen UI library 3. **Authentication:** Implement JWT auth system 4. **API Integration:** Set up Django backend communication 5. **Basic Layout:** Create header, footer, navigation ### Phase 2: Core Features (Week 2) 1. **Parks System:** Listing, detail, search functionality 2. **Rides System:** Listing, detail, filtering 3. **User Profiles:** Profile management and settings 4. **Photo System:** Upload, display, basic moderation ### Phase 3: Advanced Features (Week 3) 1. **Submission System:** Content submission workflow 2. **Moderation Interface:** Admin tools and queues 3. **Advanced Search:** Filters, autocomplete, suggestions 4. **Maps Integration:** Location visualization ### Phase 4: Polish & Deployment (Week 4) 1. **Performance Optimization:** Bundle size, loading times 2. **Testing:** Comprehensive test suite 3. **Documentation:** Complete user and developer docs 4. **Deployment:** Production setup and monitoring --- ## 🚨 Critical Dependencies ### Immediate Blockers 1. **Component Library Choice:** Must be decided before implementation 2. **Django JWT Setup:** Backend enhancement required 3. **Development Environment:** CORS and proxy configuration ### Technical Dependencies 1. **Node.js 18+:** Required for Nuxt 3 2. **Django Backend:** Must be running for development 3. **PostgreSQL:** Database must be accessible 4. **Context7:** Integration approach needs clarification --- **Next Document:** `component-library-analysis.md` - Detailed analysis of chosen library **Status:** Ready for component library decision and implementation start