### Project Installation Source: https://github.com/alexanderop/workouttracker/blob/main/README.md Install project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Configure Browser Test Setup Source: https://github.com/alexanderop/workouttracker/blob/main/docs/vitest-browser-mode-plan.md Create `src/__tests__/browser/setup.ts` to configure global stubs and mocks for browser tests. This example shows how to stub `Teleport` components and mock the `$t` function for i18n. ```typescript import { config } from 'vitest-browser-vue' // Global stubs for shadcn-vue components that use Teleport config.global.stubs = { Teleport: true, } // Mock i18n if needed config.global.mocks = { $t: (key: string) => key, } ``` -------------------------------- ### Define Script Setup with TypeScript Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md All components must use the script setup syntax with TypeScript. ```vue ``` -------------------------------- ### Vitest Browser Mode Setup Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/vitest-browser-mode.md A minimal setup file for Vitest Browser Mode that leverages native browser APIs. ```typescript // Browser setup - real APIs, no mocks needed import 'fake-indexeddb/auto' export { resetDatabase } from '../helpers/resetDatabase' ``` -------------------------------- ### jsdom Mock Setup Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/vitest-browser-mode.md A complex setup file required to polyfill missing browser APIs in a jsdom environment. ```typescript // jsdom setup - 49 lines of faking browser APIs import 'fake-indexeddb/auto' import { setupAudioContextMock } from './helpers/audioMock' setupAudioContextMock() // 101 more lines in a separate file! window.matchMedia = (query: string): MediaQueryList => ({ matches: false, media: query, onchange: null, addListener: () => {}, removeListener: () => {}, addEventListener: () => {}, removeEventListener: () => {}, dispatchEvent: () => true, }) Object.defineProperty(window.HTMLMediaElement.prototype, 'play', { configurable: true, writable: true, value: vi.fn().mockResolvedValue(undefined), }) // ... more mocks for pause, load, etc. ``` -------------------------------- ### Setup Pre-commit Hooks Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Commands and configuration for Husky and lint-staged to automate linting before commits. ```bash pnpm add -D husky lint-staged pnpm husky init ``` ```json { "lint-staged": { "*.{ts,vue,js}": "eslint --fix --cache", "*.md": "markdownlint-cli2 --fix" } } ``` ```bash # .husky/pre-commit pnpm lint-staged pnpm type-check ``` -------------------------------- ### Install shadcn-vue Components Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Command-line instructions to initialize shadcn-vue in a project and add specific components like 'button' and 'dialog'. ```bash npx shadcn-vue@latest init npx shadcn-vue@latest add button dialog ``` -------------------------------- ### Standard Component Organization Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Follow the recommended order of operations within the script setup block. ```vue ``` -------------------------------- ### Usage of ExerciseSettingsItem Source: https://github.com/alexanderop/workouttracker/blob/main/plan/vue-component-review.md Example implementation showing how to use the ExerciseSettingsItem component within a parent container. ```vue
``` -------------------------------- ### Install Vitest Browser Dependencies Source: https://github.com/alexanderop/workouttracker/blob/main/docs/vitest-browser-mode-plan.md Install the necessary Vitest packages for browser testing and Playwright browsers. Run `pnpm exec playwright install chromium` to download the Chromium browser for Playwright. ```bash pnpm install -D vitest@latest @vitest/browser-playwright vitest-browser-vue pnpm exec playwright install chromium ``` -------------------------------- ### Development Server Source: https://github.com/alexanderop/workouttracker/blob/main/README.md Start the development server with Hot Module Replacement (HMR). ```bash pnpm dev ``` -------------------------------- ### View script output examples Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/enforcing-clean-composable-architecture-vue.md Expected console output when running the composable usage check. ```text $ pnpm check:composables ⚠️ useUserGreeting (src/composables/useUserGreeting.ts) - only 1 usage(s), minimum is 2 ``` ```text $ pnpm check:composables ✓ All composables are used at least 2 times ``` -------------------------------- ### Monolithic Component Structure Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/REFACTORING_PATTERNS.md An example of a monolithic component structure before refactoring. ```text src/views/ActiveWorkout.vue (520 lines) ├── State: workout, restTime, showAddExercise, ... ├── Functions: calculate10RM, formatTime, toggleTimer, ... ├── Template: Header, Carousel, Table, History, Timer └── All mixed together ``` -------------------------------- ### Install VueUse RxJS Dependencies Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/dexie-improvements.md Command to add necessary packages for reactive query integration. ```bash pnpm add @vueuse/rxjs rxjs ``` -------------------------------- ### Install VueUse Core Package Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Install the VueUse core package, a required utility library for Vue 3 Composition API. ```bash pnpm add @vueuse/core ``` -------------------------------- ### Plate Calculator Output Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/PRODUCT_ROADMAP.md Example output from the plate calculator showing bar weight, weight per side, and total weight. Configurable plates and nearest achievable weight are supported. ```text Bar: 20kg Each side: 20kg + 15kg + 5kg Total: 100kg ``` -------------------------------- ### shadcn-vue Carousel Installation and Reference Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Installation command and interface definition for the Carousel component. ```bash pnpm dlx shadcn-vue@latest add carousel ``` ```typescript interface CarouselApi { scrollTo(index: number, jump: boolean): void // jump=true for instant (no animation) selectedScrollSnap(): number // Current slide (0-based) on(event: 'select', callback: () => void): void canScrollNext(): boolean canScrollPrev(): boolean } ``` -------------------------------- ### Install Browser Testing Dependencies Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/vitest-browser-mode.md Command to add the necessary Vitest browser and Playwright packages. ```bash pnpm add -D @vitest/browser @vitest/browser-playwright playwright ``` -------------------------------- ### Add Pinia to `withSetup()` Helper (After) Source: https://github.com/alexanderop/workouttracker/blob/main/.plan.md This updated `withSetup` helper installs Pinia using `app.use(createPinia())`, ensuring Pinia context is available for composables in browser tests. Each call creates a new Pinia instance. ```typescript import type { App } from 'vue' import { createApp } from 'vue' import { createPinia } from 'pinia' // ← ADD export function withSetup(composable: () => TResult): [TResult, App] { let result: TResult const app = createApp({ setup() { result = composable() return () => {} }, }) app.use(createPinia()) // ← ADD app.mount(document.createElement('div')) // @ts-expect-error - result is assigned synchronously in setup return [result, app] } ``` -------------------------------- ### PWA Installation Detection Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Uses the `matchMedia` API to detect if the application is currently running in standalone mode as a Progressive Web App. This is used to dynamically skip the PWA installation slide. ```javascript matchMedia('display-mode: standalone') ``` -------------------------------- ### Install shadcn-vue calendar component Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/2024-12-14-workout-calendar-design.md Use this command to add the required calendar component to the project. ```bash pnpm dlx shadcn-vue@latest add calendar ``` -------------------------------- ### Initialize Internationalization Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Setup for vue-i18n with English as the default locale. ```typescript import { createI18n } from 'vue-i18n' import en from './locales/en.json' export const i18n = createI18n({ legacy: false, locale: 'en', fallbackLocale: 'en', messages: { en }, }) ``` -------------------------------- ### Weekly Program Planner Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/PRODUCT_ROADMAP.md A sample weekly schedule for a training program, showing assigned workouts and rest days. Supports drag-and-drop scheduling and recurring weekly routines. ```text Monday: Push Day (template) Tuesday: Pull Day (template) Wednesday: Rest Thursday: Legs (template) Friday: Upper Body (template) Saturday: CrossFit WOD Sunday: Rest ``` -------------------------------- ### Define Vite Environment Variables Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Example of .env file structure for Vite environment variables. ```bash # .env VITE_API_URL=https://api.example.com VITE_APP_VERSION=$npm_package_version # .env.local (gitignored) VITE_API_KEY=secret-dev-key ``` -------------------------------- ### Add Pinia to `withSetup()` Helper (Before) Source: https://github.com/alexanderop/workouttracker/blob/main/.plan.md The original `withSetup` helper function in `src/__tests__/helpers/withSetup.ts` did not install Pinia, causing issues in browser tests where Pinia context was expected. ```typescript import type { App } from 'vue' import { createApp } from 'vue' export function withSetup(composable: () => TResult): [TResult, App] { let result: TResult const app = createApp({ setup() { result = composable() return () => {} }, }) app.mount(document.createElement('div')) // @ts-expect-error - result is assigned synchronously in setup return [result, app] } ``` -------------------------------- ### Refactoring Output Summary Source: https://github.com/alexanderop/workouttracker/blob/main/docs/REFACTOR_COMMAND_USAGE.md Example output showing the results of a successful refactoring operation, including metrics and file changes. ```text ✅ Refactoring Complete 📊 Improvements: • Component size reduced by 88% • 6 reusable child components created • 2 state/logic composables extracted • 2 pure utility functions extracted 📁 Files Created: + src/lib/workout-utils.ts + src/composables/useWorkout.ts + src/composables/useRestTimer.ts + src/components/workout/WorkoutHeader.vue + src/components/workout/ExerciseCarousel.vue + src/components/workout/SetTable.vue + src/components/workout/PreviousHistory.vue + src/components/workout/RestTimerWidget.vue + src/components/workout/WorkoutAddExerciseDialog.vue 📝 Files Modified: ~ src/views/ActiveWorkout.vue (520 → 62 lines) ⚙️ Recommended Next Steps: 1. Run: pnpm type-check 2. Run: pnpm lint 3. Run: pnpm test 4. Review components for domain-specific adjustments ``` -------------------------------- ### Handle Tool Execution Errors Source: https://github.com/alexanderop/workouttracker/blob/main/docs/TIL-claude-parallel-tools.md Example output showing error results when the system attempts to execute invalid tool calls parsed from text. ```xml Edit File does not exist. Edit File does not exist. ``` -------------------------------- ### Define CI/CD Pipeline Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md GitHub Actions workflow for continuous integration, including setup, linting, type-checking, and testing. ```yaml name: CI on: push: branches: [main] pull_request: branches: [main] concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: setup: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' - run: pnpm install --frozen-lockfile lint: needs: setup # parallel with type-check, test type-check: needs: setup # parallel test: needs: setup strategy: matrix: shard: [1, 2, 3, 4] # run: pnpm vitest --shard=${{ matrix.shard }}/4 ``` -------------------------------- ### Implement Context Menu with VueUse Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/2026-01-16-set-context-menu.md Full example of using onLongPress and onClickOutside to manage a context menu for set rows. ```vue ``` -------------------------------- ### Manage Workout Templates Repository Source: https://github.com/alexanderop/workouttracker/blob/main/docs/agent/database.md Create templates from active workouts, start workouts from existing templates, and retrieve all templates sorted by usage. ```typescript const repo = getTemplatesRepository() // Create template from active workout const template = await repo.createFromWorkout(activeWorkout, 'My Template') // Start workout from template (updates lastUsedAt) const workout = await repo.startFromTemplate(templateId) // Get all templates (sorted by lastUsedAt) const templates = await repo.getAll() ``` -------------------------------- ### Configure CI for Browser Tests Source: https://github.com/alexanderop/workouttracker/blob/main/docs/vitest-browser-mode-plan.md GitHub Actions workflow steps to install Playwright dependencies and execute browser tests in a CI environment. ```yaml - name: Install Playwright run: pnpm exec playwright install chromium --with-deps - name: Run Browser Tests run: pnpm test:browser env: CI: true ``` -------------------------------- ### Create Test App Helper Source: https://github.com/alexanderop/workouttracker/blob/main/blog-tdd-workflow-claude-code.md A helper function that initializes a testing environment with Pinia, Vue Router, and user-event setup for consistent integration testing. ```typescript export async function createTestApp(): Promise { const pinia = createPinia() const router = createRouter({ history: createMemoryHistory(), routes, }) const user = userEvent.setup() render(App, { global: { plugins: [router, pinia], }, }) await router.isReady() return { router, user, getByRole: screen.getByRole, getByText: screen.getByText, // ... more helpers waitForDialog: () => waitFor(() => screen.getByRole('dialog')), waitForRoute: (pattern) => waitFor(() => { if (!pattern.test(router.currentRoute.value.path)) { throw new Error(`Route mismatch`) } }), // ... domain-specific helpers fillSet: async (index, values) => { /* ... */ }, getSetRow: (index) => { /* ... */ }, } } ``` -------------------------------- ### Onboarding State Management Interface Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Defines the state interface for the onboarding composable, including current step, completion status, returning user flag, and PWA installation status. Persists `currentStep` for resuming onboarding. ```typescript interface OnboardingState { currentStep: number // 0-indexed (0-5), persisted for resume completed: boolean // true when finished or skipped isReturningUser: boolean // true if existing data detected isPwaInstalled: boolean // true if running as PWA } // Computed totalSlides: number // 5 if PWA installed, 6 otherwise ``` -------------------------------- ### Achievement Badges Categories Source: https://github.com/alexanderop/workouttracker/blob/main/docs/PRODUCT_ROADMAP.md Defines categories for achievement badges, including 'Getting Started', 'Consistency', 'Strength', 'Volume', and 'Benchmarks', with examples for each. ```text Categories: - Getting Started: First workout, first template, first benchmark - Consistency: 7-day streak, 30-day streak, 100 workouts - Strength: First PR, 10 PRs, PR in every major lift - Volume: 10,000kg week, 100,000kg month, 1 million kg lifetime - Benchmarks: Complete Fran, sub-5 Fran, complete all Hero WODs ``` -------------------------------- ### Implement Onboarding Repository Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Creates a repository for managing onboarding state with fail-open error handling. ```typescript // src/db/implementations/dexie/onboarding.ts export function createDexieOnboardingRepository( database: WorkoutTrackerDatabase ): OnboardingRepository { return { async get() { try { const record = await database.onboarding.get('onboarding') return record ?? { id: 'onboarding', completed: false, currentStep: 0 } } catch { // Fail-open: assume complete to avoid blocking app access return { id: 'onboarding', completed: true, currentStep: 0 } } }, async update(data: Partial) { await database.onboarding.put({ id: 'onboarding', ...data }) } } } ``` -------------------------------- ### Production Build Source: https://github.com/alexanderop/workouttracker/blob/main/README.md Perform type-checking and build the application for production. ```bash pnpm build ``` -------------------------------- ### English Message Domain Example (Common) Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/2025-12-03-i18n-design.md Example of a message domain file for English, defining common strings for buttons, states, and empty states. Uses 'as const' for literal type inference. ```typescript // src/i18n/messages/en/common.ts export default { buttons: { cancel: 'Cancel', save: 'Save', delete: 'Delete', create: 'Create', finish: 'Finish', }, states: { loading: 'Loading...', exporting: 'Exporting...', }, empty: { noResults: 'No results found', noResultsFor: 'No results for "{query}"' }, } as const ``` -------------------------------- ### File Structure for Onboarding Feature Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Provides an overview of the directory structure for the onboarding feature, detailing the organization of components, composables, constants, and views. ```treeview src/features/onboarding/ ├── components/ │ ├── OnboardingCarousel.vue # Main carousel wrapper │ ├── OnboardingSlide.vue # Generic slide layout │ ├── WelcomeSlide.vue # Slide 1 │ ├── PwaInstallSlide.vue # Slide 2 (conditionally included) │ ├── QuickWorkoutSlide.vue # Slide 3 │ ├── TemplatesSlide.vue # Slide 4 │ ├── BenchmarksSlide.vue # Slide 5 │ ├── ChecklistSlide.vue # Slide 6 │ └── previews/ │ ├── OnboardingBlockPreview.vue │ ├── OnboardingTemplatePreview.vue │ └── OnboardingBenchmarkPreview.vue ├── composables/ │ └── useOnboarding.ts # State management + persistence ├── constants/ │ └── previewData.ts # Sample data for previews ├── views/ │ └── OnboardingView.vue # Route component └── spec.md # This file ``` -------------------------------- ### Mutation Testing: Boolean Logic Operator Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog-draft-mutation-testing-with-ai.md Demonstrates a mutation on a boolean condition by negating it. This mutation helps verify that tests correctly handle both positive and negative outcomes of logical checks. The example shows the original condition, the mutated version, and the test outcome. ```typescript // Original (composables/useTheme.ts:26) newMode === 'dark' // Mutation: Negate the condition newMode !== 'dark' // Result: Tests PASSED → Mutant SURVIVED ``` -------------------------------- ### Mutation Testing: Boundary Operator Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog-draft-mutation-testing-with-ai.md Illustrates a boundary mutation where a less than operator is changed to less than or equal to. This type of mutation is effective for testing edge cases in numerical comparisons. The provided example shows the original code, the mutation applied, and the test result. ```typescript // Original (stores/settings.ts:65) Math.min(Math.max(volume, 0.5), 1) // Mutation: Change 0.5 to 0.4 Math.min(Math.max(volume, 0.4), 1) // Result: Tests PASSED → Mutant SURVIVED ``` -------------------------------- ### Project Commands Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Common CLI commands for development, testing, linting, and building the project. ```bash pnpm dev # Development server pnpm test # Run tests pnpm lint # Fix lint errors pnpm type-check # TypeScript checking pnpm build # Production build ``` -------------------------------- ### Mutation Testing: Error Handling Path Example Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog-draft-mutation-testing-with-ai.md Shows a mutation applied to an error handling condition by inverting the check. This mutation is crucial for ensuring that error paths within the code are adequately tested. The example includes the original error check, the mutated version, and the test result. ```typescript // Original (stores/settings.ts:28) if (error) return // Mutation: Negate the condition if (!error) return // Result: Tests PASSED → Mutant SURVIVED ``` -------------------------------- ### Write Release Notes Source: https://github.com/alexanderop/workouttracker/blob/main/product-planning/CLAUDE_PROMPTS.md Use this prompt to generate user-friendly release notes from a list of shipped items. ```text These items shipped this sprint: [LIST ITEMS] Write user-friendly release notes that: 1. Focus on user benefits, not technical details 2. Are scannable with clear headers 3. Include any breaking changes or required actions ``` -------------------------------- ### PWA Detection Pattern Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Detects PWA installation status with a fallback for Safari iOS. ```typescript import { useMediaQuery } from '@vueuse/core' const isPwaInstalled = useMediaQuery('(display-mode: standalone)') // Safari iOS fallback const isSafariStandalone = computed(() => 'standalone' in globalThis.navigator && globalThis.navigator.standalone === true ) const isPWA = computed(() => isPwaInstalled.value || isSafariStandalone.value) const totalSlides = computed(() => isPWA.value ? 5 : 6) ``` -------------------------------- ### Configure Vue Router Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Setup for Vue Router with named routes and lazy-loaded components. ```typescript import { createRouter, createWebHistory } from 'vue-router' export const RouteNames = { Home: 'home', WorkoutDetail: 'workout-detail', Settings: 'settings', } as const const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', name: RouteNames.Home, component: () => import('@/views/HomeView.vue'), }, { path: '/workout/:id', name: RouteNames.WorkoutDetail, component: () => import('@/views/WorkoutDetailView.vue'), props: true, }, ], }) ``` -------------------------------- ### Onboarding Checklist Items with Deep-Links Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md Illustrates the structure of checklist items for the final onboarding slide, including a descriptive text and a deep-link route name for navigation. Clicking an item marks onboarding complete and navigates to the specified route. ```markdown - [ ] Create your first template → routes to `TemplatesCreate` - [ ] Browse the exercise library → routes to `Exercises` - [ ] Start a quick workout → routes to `WorkoutCreate` - [ ] Try a benchmark → routes to `Benchmarks` ``` -------------------------------- ### Configure Performance Budgets Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Lighthouse CI configuration to enforce performance and accessibility scores. ```json { "ci": { "assert": { "assertions": { "categories:performance": ["error", { "minScore": 0.80 }], "categories:accessibility": ["error", { "minScore": 1.0 }], "largest-contentful-paint": ["error", { "maxNumericValue": 3500 }] } } } } ``` -------------------------------- ### Project Directory Structure Source: https://github.com/alexanderop/workouttracker/blob/main/docs/TEMPLATE_PLAN.md The target file and folder hierarchy for the new PWA starter template. ```text vue-pwa-starter/ ├── src/ │ ├── components/ │ │ ├── ui/ # All shadcn-vue (copied as-is) │ │ ├── Layout.vue │ │ ├── PageHeader.vue │ │ ├── PageLayout.vue │ │ └── ErrorDialog.vue │ ├── composables/ │ │ ├── usePwaUpdate.ts │ │ ├── useVersionCheck.ts │ │ ├── useScreenWakeLock.ts │ │ ├── useGlobalWakeLock.ts │ │ ├── useTouchDevice.ts │ │ ├── useDialogState.ts │ │ ├── useAnimatedCounter.ts │ │ ├── useNumberLocale.ts │ │ └── useEnterAnimation.ts │ ├── db/ │ │ ├── schema.ts │ │ ├── interfaces.ts │ │ ├── implementations/ │ │ │ └── DexieItemRepository.ts │ │ ├── provider.ts │ │ ├── converters.ts │ │ └── index.ts │ ├── features/ │ │ └── items/ │ │ ├── components/ │ │ │ ├── ItemCard.vue │ │ │ ├── ItemForm.vue │ │ │ └── ItemStatusBadge.vue │ │ ├── composables/ │ │ │ └── useItems.ts │ │ ├── views/ │ │ │ └── ItemDetailView.vue │ │ ├── index.ts │ │ └── CLAUDE.md │ ├── i18n/ │ │ ├── index.ts │ │ ├── types.ts │ │ └── messages/ │ │ ├── en.ts │ │ └── de.ts │ ├── stores/ │ │ └── settings.ts │ ├── types/ │ │ └── item.ts │ ├── views/ │ │ ├── TheHomeView.vue │ │ ├── TheItemsView.vue │ │ └── TheSettingsView.vue │ ├── router/ │ │ └── index.ts │ ├── __tests__/ │ │ ├── setup.ts │ │ ├── factories/ │ │ │ └── itemFactory.ts │ │ ├── helpers/ │ │ │ └── testUtils.ts │ │ ├── composables/ │ │ │ └── useItems.spec.ts │ │ ├── db/ │ │ │ └── itemRepository.spec.ts │ │ └── CLAUDE.md │ ├── App.vue │ ├── main.ts │ └── style.css ├── CLAUDE.md ├── package.json ├── vite.config.ts ├── tsconfig.json ├── eslint.config.js └── README.md ``` -------------------------------- ### Localization Keys for Onboarding Source: https://github.com/alexanderop/workouttracker/blob/main/src/features/onboarding/spec.md YAML structure for onboarding-related text localization. ```yaml onboarding: welcome: title: "Workout Tracker" startTour: "Start Tour" skipToApp: "Skip to App" welcomeBack: title: "Welcome back!" resumeTour: "Resume Tour" pwa: title: "Install for the best experience" instruction1: "..." quickWorkout: title: "Build workouts on the fly" description: "..." templates: title: "Save your favorites" benchmarks: title: "Track your progress" checklist: title: "You're ready!" createTemplate: "Create your first template" browseExercises: "Browse the exercise library" startWorkout: "Start a quick workout" tryBenchmark: "Try a benchmark" navigation: next: "Next" back: "Back" skip: "Skip" letsGo: "Let's Go" ``` -------------------------------- ### Development and Build Commands Source: https://github.com/alexanderop/workouttracker/blob/main/CLAUDE.md Standard CLI commands for managing the development lifecycle of the project. ```bash pnpm dev # Development server pnpm test # Run tests (NOT test:unit!) pnpm lint # Fix lint errors pnpm type-check # TypeScript checking pnpm build # Production build pnpm knip # Find unused exports ``` -------------------------------- ### Create DbForTimeBenchmark Factory Source: https://github.com/alexanderop/workouttracker/blob/main/docs/test-factory-improvements.md Factory for creating 'fortime' type benchmarks. It sets default values specific to this type and includes predefined exercises. ```typescript import type { DbBenchmark, DbBenchmarkExercise } from '@/db/schema' import { generateId } from '@/db' const DEFAULTS: Readonly> = { name: 'Fran', type: 'fortime', rounds: 1, createdAt: Date.now(), lastUsedAt: null, } export function createDbBenchmarkExercise( overrides: Partial = {} ): DbBenchmarkExercise { return { exerciseDefinitionId: null, name: 'Thrusters', prescribedReps: 21, thumbnail: '🏋️', ...overrides, } } export function createDbForTimeBenchmark( overrides: Partial = {} ): DbBenchmark { return createDbBenchmark({ type: 'fortime', exercises: [ createDbBenchmarkExercise({ name: 'Thrusters', prescribedReps: 21 }), createDbBenchmarkExercise({ name: 'Pull-ups', prescribedReps: 21 }), ], ...overrides, }) } ``` -------------------------------- ### File Naming Conventions Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Naming patterns for components, utilities, and test files. ```text Component.vue # PascalCase for components useFeature.ts # camelCase with 'use' prefix featureName.ts # camelCase for utilities feature.spec.ts # camelCase with .spec.ts for tests ``` -------------------------------- ### Integrate WeekStrip into HomeView Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/2024-12-14-workout-calendar-design.md Example of placing the WeekStrip component within the main home view layout. ```vue ``` -------------------------------- ### Define a sample Vue composable Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/enforcing-clean-composable-architecture-vue.md An example of a composable that might be extracted prematurely if only used in a single component. ```typescript // src/composables/useUserGreeting.ts export function useUserGreeting(name: string) { return computed(() => `Hello, ${name}!`) } ``` -------------------------------- ### Run Project Test Commands Source: https://github.com/alexanderop/workouttracker/blob/main/docs/test-factory-improvements.md Standard commands for executing tests and verifying code quality. ```bash # Run all tests pnpm test # Run specific test file you're refactoring pnpm test src/__tests__/integration/benchmark-flows.spec.ts # Type check (catch any type errors in factories) pnpm type-check # Lint (auto-fix style issues) pnpm lint ``` -------------------------------- ### Integrate check into CI pipeline Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/enforcing-clean-composable-architecture-vue.md Example GitHub Actions step to enforce the composable usage rule during CI. ```yaml - name: Check composable usage run: pnpm check:composables ``` -------------------------------- ### Integration Test Structure Source: https://github.com/alexanderop/workouttracker/blob/main/docs/VUE_STYLE_GUIDE.md Use createTestApp() instead of render() for integration tests to ensure proper setup and cleanup. ```typescript describe('Template Flow', () => { beforeEach(setupIntegrationTest) afterEach(cleanupIntegrationTest) it('should save completed workout as template when user completes flow', async () => { const { builder, workout, router } = await createTestApp() await userEvent.click(getByRole('button', { name: /start new workout/i })) expect(router.currentRoute.value.path).toBe('/workout/builder') await builder.addExercise('Bench Press') await builder.startWorkout() await workout.fillSetAndComplete({ weight: '80', reps: '10' }) await workout.endWorkout() await userEvent.fill(getByRole('textbox', { name: /name/i }), 'Push Day') await userEvent.click(getByRole('button', { name: /save template/i })) const templates = await db.templates.toArray() expect(templates.find(t => t.name === 'Push Day')).toBeDefined() }) }) ``` -------------------------------- ### Update Imports in BenchmarkForTimeView Source: https://github.com/alexanderop/workouttracker/blob/main/docs/plans/2025-12-14-benchmark-workout-ui-implementation.md Update the script setup imports to include necessary components and types for the benchmark view. ```vue ``` -------------------------------- ### Define Boolean Flag Anti-pattern Source: https://github.com/alexanderop/workouttracker/blob/main/docs/state-machine-pattern.md Example of the boolean flag anti-pattern where multiple independent refs can lead to invalid UI states. ```typescript const showEquipmentModal = ref(false) const showMuscleModal = ref(false) const showTypeModal = ref(false) const showMetricsModal = ref(false) ``` -------------------------------- ### Execute Cross-Environment Test Source: https://github.com/alexanderop/workouttracker/blob/main/docs/blog/vitest-browser-mode.md Example of a test case that runs identically in both jsdom and browser environments using a shared test helper. ```typescript it('completes a workout flow', async () => { const { builder, workout, user, cleanup } = await createTestApp() await builder.addStrengthBlock('Squat') await builder.startWorkout() await workout.fillSet(0, { kg: 100, reps: 8, rir: 2 }) expect(await screen.findByText('1/3')).toBeTruthy() cleanup() }) ```