skillby alexanderop
workout-domain
Workout block model, types, and operations. Use when building workouts, managing block kinds (strength/AMRAP/EMOM/Tabata/ForTime/cardio), handling sets/reps, or working with workout persistence and benchmarks. Triggers: "workout", "block", "strength", "cardio", "AMRAP", "EMOM", "Tabata", "ForTime", "exercise", "set", "reps", "weight", "RIR", "timed block", "create workout", "build workout", "block kind", "discriminated union", "block result", "round", "interval", "benchmark", "template", "persist workout", "complete workout".
Installs: 0
Used in: 1 repos
Updated: 2d ago
$
npx ai-builder add skill alexanderop/workout-domainInstalls to .claude/skills/workout-domain/
# Workout Domain
## Block-Based Workout Model
Workouts are sequences of **blocks** using discriminated unions via `kind`:
```ts
type WorkoutBlock = StrengthBlock | TimedBlock | CardioBlock
type TimedBlock = AmrapBlock | EmomBlock | TabataBlock | ForTimeBlock
```
### Strength Block
Traditional sets/reps exercises:
```ts
type StrengthBlock = {
kind: 'strength'
id: number
exerciseName: string
sets: Array<Set>
}
type Set = {
id: number
weight?: string // User input as string
reps?: string
rir?: string // Reps in reserve
completed: boolean
}
```
### Timed Blocks
AMRAP, EMOM, Tabata, ForTime:
```ts
type AmrapBlock = {
kind: 'amrap'
id: number
config: AmrapConfig
exercises: Array<BlockExercise>
result?: AmrapResult
}
type EmomBlock = {
kind: 'emom'
id: number
config: EmomConfig
exercises: Array<BlockExercise>
result?: EmomResult
}
type TabataBlock = {
kind: 'tabata'
id: number
config: TabataConfig
exercises: Array<BlockExercise>
result?: TabataResult
}
type ForTimeBlock = {
kind: 'fortime'
id: number
config: ForTimeConfig
exercises: Array<BlockExercise>
result?: ForTimeResult
}
```
### Cardio Block
```ts
type CardioBlock = {
kind: 'cardio'
id: number
exerciseName: string
duration?: number
distance?: number
calories?: number
}
```
## Type Files
| File | Purpose |
|------|---------|
| `src/types/blocks.ts` | Runtime block types |
| `src/db/schema.ts` | Persistence types with `Db` prefix |
**Convention**: Database types use `Db` prefix (e.g., `DbStrengthBlock`) and `null` instead of `undefined`.
## Key Composables
### Workout Feature
| Composable | Purpose |
|------------|---------|
| `useWorkout.ts` | Singleton state, block/set CRUD operations |
| `useWorkoutPersistence.ts` | Auto-save, complete, discard active workout |
| `useWorkoutExercise.ts` | Exercise selection within workout |
| `useWorkoutBuilder.ts` | Build workout from scratch or template |
### Benchmark Feature
| Composable | Purpose |
|------------|---------|
| `useBenchmark.ts` | Core benchmark state and operations |
| `useBenchmarkPersistence.ts` | Save benchmark attempts |
| `useBenchmarkTimer.ts` | Timer for timed benchmarks |
### Template Feature
| Composable | Purpose |
|------------|---------|
| `useTemplateForm.ts` | Create/edit template form state |
| `useTemplatePicker.ts` | Select template to start workout |
## Working with Blocks
### Adding a Block
```ts
import { useWorkout } from '@/features/workout/composables/useWorkout'
const { addBlock } = useWorkout()
// Add strength block
addBlock({
kind: 'strength',
exerciseName: 'Squat',
sets: []
})
// Add AMRAP block
addBlock({
kind: 'amrap',
config: { duration: 10 },
exercises: []
})
```
### Type-Safe Block Handling
Use exhaustive switch for block kinds:
```ts
function getBlockTitle(block: WorkoutBlock): string {
switch (block.kind) {
case 'strength':
return block.exerciseName
case 'amrap':
return `AMRAP ${block.config.duration}min`
case 'emom':
return `EMOM ${block.config.rounds}x${block.config.interval}s`
case 'tabata':
return 'Tabata'
case 'fortime':
return 'For Time'
case 'cardio':
return block.exerciseName
default:
// TypeScript exhaustiveness check
const _exhaustive: never = block
return _exhaustive
}
}
```
## Quick Find
```bash
rg -n "kind: '(strength|amrap|emom|tabata|fortime|cardio)'" src/ # Block usage
rg -n "type.*Block = " src/types/blocks.ts # Block type definitions
rg -n "export function use" src/features/workout/composables # Workout composables
```Quick Install
$
npx ai-builder add skill alexanderop/workout-domainDetails
- Type
- skill
- Author
- alexanderop
- Slug
- alexanderop/workout-domain
- Created
- 6d ago