workouttracker

内容来源:README.md(说明文档) · 原始地址 · 查看安装指南

原始内容

Workout Tracker

My personal Progressive Web App for tracking strength training and CrossFit-style workouts. I built this because I wanted a workout app that actually works offline, supports the timer protocols I use (AMRAP, EMOM, Tabata), and doesn't require a subscription.

Features

Block-Based Workouts

Compose workouts from different block types that you can mix and match:

  • Strength Blocks — Track sets with weight (kg/lbs), reps, and RIR (Reps In Reserve)
  • Timed Blocks — CrossFit-style interval protocols

Timer Modes

Full support for popular CrossFit timing protocols:

Mode Description
AMRAP As Many Rounds As Possible — set a duration, track rounds completed
EMOM Every Minute On the Minute — exercises reset each minute
Tabata Classic 20s work / 10s rest intervals
For Time Race to complete all reps, optional time cap

Exercise Library

  • 100+ pre-loaded exercises with icons and muscle group tags
  • Create your own custom exercises
  • Filter by muscle group (chest, back, legs, shoulders, arms, core)
  • Full-text search

Workout Templates

Save your favorite workouts as templates to reuse later. No more rebuilding the same workout every week.

Offline-First PWA

  • Works completely offline — no internet required during workouts
  • Installable on your home screen (iOS, Android, desktop)
  • All data stored locally in IndexedDB
  • Export/import your data anytime

Customization

  • Dark mode
  • Multiple languages (i18n ready)
  • Weight units (kg or lbs)
  • Timer volume control

Tech Stack

  • Vue 3.5+ with Composition API and <script setup>
  • TypeScript with strict type checking
  • Tailwind CSS 4 for styling
  • shadcn-vue (reka-ui) component library
  • Pinia for state management
  • Dexie for IndexedDB persistence
  • Vite 6 with PWA plugin
  • Vitest with Playwright browser testing

Getting Started

Prerequisites

  • Node.js ^20.19.0 or >=22.12.0
  • pnpm 10.24.0+

Installation

pnpm install

Development

pnpm dev

Build

pnpm build

Scripts

Command Description
pnpm dev Start dev server with HMR
pnpm build Type-check and build for production
pnpm test Run all tests (Playwright browser)
pnpm test:headed Run tests with visible browser
pnpm test:ui Run tests with Vitest UI
pnpm test:coverage Run tests with coverage report
pnpm lint Run oxlint + eslint with auto-fix
pnpm type-check TypeScript type checking only
pnpm knip Find unused exports/dependencies

Architecture

This project follows Bulletproof feature-based architecture:

src/
├── features/          # Domain-specific modules
│   ├── exercises/     # Exercise library CRUD
│   ├── settings/      # App settings
│   ├── templates/     # Workout templates
│   ├── timers/        # Timer UI components
│   └── workout/       # Core workout execution
├── composables/       # Shared Vue composables
│   └── timers/        # Timer state machines
├── components/        # Shared UI components
│   └── ui/            # shadcn-vue primitives
├── db/                # Dexie database layer
│   └── repositories/  # Data access patterns
├── stores/            # Pinia stores
├── views/             # Route-level components
└── types/             # TypeScript types

Dependency Rules

  • Views → Features → Shared (composables, components, stores, db)
  • Features cannot import other features
  • Shared code cannot import features

Contributing

Contributions are welcome! Whether it's bug reports, feature suggestions, or pull requests.

Reporting Bugs

Open an issue with:

  • What you expected to happen
  • What actually happened
  • Steps to reproduce
  • Browser/device info

Suggesting Features

Open an issue describing:

  • The problem you're trying to solve
  • Your proposed solution
  • Any alternatives you considered

Pull Requests

  1. Fork the repo and create your branch from main
  2. Run pnpm install to set up dependencies
  3. Make your changes
  4. Ensure the tests covering your change pass: pnpm exec vitest run --project=default src/__tests__/<area> (the full suite runs in CI on your PR — see Running Tests)
  5. Ensure linting passes: pnpm lint
  6. Ensure types check: pnpm type-check
  7. Open a PR with a clear description of your changes

Code Style

  • TypeScript strict mode — no any, no type assertions
  • Vue 3.5+ APIs (reactive props destructure, defineModel, useTemplateRef)
  • Composition API with <script setup>
  • See CLAUDE.md for detailed coding standards

Testing

This project uses Vitest with Playwright for browser-based testing. Tests run in a real browser environment, not jsdom.

Running Tests

# Run the tests covering what you changed — the everyday command.
# Filters match test paths under src/__tests__/, not source paths.
pnpm exec vitest run --project=default src/__tests__/features/workout
pnpm exec vitest run --project=default src/__tests__/browser/timer-audio.spec.ts

# Fast Node tier: pure logic, no DOM or IndexedDB (~1.5s)
pnpm test:unit

# Run with visible browser (great for debugging)
pnpm test:headed

# Run with Vitest UI (interactive test explorer)
pnpm test:ui

# Run with coverage
pnpm test:coverage

# Run the whole browser tier (~5 min) — CI does this for you on every PR
pnpm test

Prefer the scoped run locally. The full browser tier takes about five minutes on one machine, and CI shards it four ways and runs the a11y, visual, e2e, and coverage tiers alongside it on every pull request, so a local full run mostly buys a slower copy of a signal the PR gets anyway.

Test Structure

Specs are not colocated with source. They all live under src/__tests__/, mirroring the source tree — so the test for src/features/workout/foo.ts lives at src/__tests__/features/workout/foo.spec.ts, and a scoped run filters on the test path, never the source path.

src/
└── __tests__/
    ├── features/      # Feature specs, mirroring src/features/
    │   └── workout/
    ├── composables/   # Composable specs, mirroring src/composables/
    │   └── timers/
    ├── components/    # Shared component specs
    ├── db/            # Repository and converter specs
    ├── stores/        # Shared store specs
    ├── integration/   # Cross-feature flows
    ├── browser/       # Browser-only behavior (wake lock, timer audio)
    ├── unit/          # `unit` project — pure Node, no DOM or IndexedDB
    ├── a11y/          # `a11y` project
    ├── visual/        # `visual` project
    ├── architecture/  # `arch` project
    ├── helpers/       # Test utilities (createTestApp, withSetup)
    └── factories/     # Test data builders

The default project covers src/__tests__/**/*.spec.ts but excludes unit/, a11y/, and visual/ — those have their own projects (pnpm test:unit, test:a11y, test:visual), so scope a run with the project that owns the specs you want.

Writing Tests

  • Composables: Test directly or use withSetup() helper for lifecycle hooks
  • Integration: Use createTestApp() for full app testing with routing
  • Factories: Use builders like workoutBuilder() and dbWorkoutBuilder() for test data

IDE Setup

License

MIT