A zero-friction, progression-guided gym logger.
Unit lets beginner-to-experienced gym users choose a ready-made program or bring their own, then replaces the paper notebook and Notes app with a tool that survives gym fatigue. Last time pre-fills the previous weight and reps; one tap confirms a set. After training, optional transparent double progression suggests one next target without taking control of the program.
Authoritative product / design docs:
PRODUCT.md— persona, voice, anti-references, design principlesDESIGN.md— palette, typography, components, do/don't (mirrored machine-readably inDESIGN.json)CLAUDE.md— session-level intent doc for AI agents working on this repodocs/product-compass.md— live positioning decisions and the decision logdocs/goals.md— measurable targets and v1 scope boundariesdocs/AGENTS.md— UX rules, product model, scope fences
- Swift 6 (strict concurrency)
- SwiftUI (NavigationStack, custom
AppScreentemplate) - SwiftData (local-first; no CloudKit in v1)
- iOS 18+
- Live Activities (rest timer on Lock Screen / Dynamic Island)
- Swift Charts (history sparklines, progress views)
- Geist / Geist Mono (bundled
.ttffonts inUnit/Resources/Fonts/)
Unit/
UnitApp.swift — App entry, ModelContainer
ContentView.swift — Root tab navigation + AppScreen wiring
UI/
DesignSystem.swift — Atoms, molecules, organisms, AppScreen template (single file)
Models/
DayTemplate.swift — Template (split + ordered exerciseIds + planned sets/reps)
Exercise.swift — Exercise (displayName, aliases, isBodyweight)
WorkoutSession.swift — Session (date, templateId, isCompleted)
SetEntry.swift — Set (weight, reps, rpe, isWarmup, isCompleted, setIndex)
Features/
Today/ — TodayView, ActiveWorkoutView, TrainingWeekProgress, RestTimerAttributes
Templates/ — TemplatesView, TemplateDetailView, AddTemplateView, ProgramLibrary*
History/ — HistoryView (single list), SessionDetailView, ExerciseProgressView
Onboarding/ — Splash, import method, program-import, split-builder, exercises
Settings/ — SettingsView (weight unit, restart onboarding)
Subscription/ — PaywallView, StoreManager
ProgramLaunch/ — Quick-start affordances
Resources/
Fonts/ — Geist + Geist Mono .ttf files
docs/ — Product, design, references, claude/ intent spillovers
- DayTemplate — id, name, splitId, orderedExerciseIds, planned targets, optional JSON-backed per-exercise progression state, lastPerformedDate
- Exercise — id, displayName, aliases, notes, isBodyweight
- WorkoutSession — id, date, templateId, isCompleted
- SetEntry — id, sessionId, exerciseId, weight, reps, rpe, isWarmup, isCompleted, setIndex
Rule: Last-time values are computed at read-time from the most recent completed SetEntry for the same exercise (any template). An explicitly accepted progression target is persisted per routine/exercise and takes precedence for the next matching workout.
The following were intentionally cut or deferred — see docs/claude/scope.md for the full list:
- Legacy cycle/failure/deload progression logic → excluded; v2.1 ships only opt-in, transparent double progression after a workout
- 8-week cycles,
Cycle,WeekDetailView, "Week N of M" → templates replace cycles - Target-vs-actual weight columns → last-time pre-fill only
- Plate calculator, social / feeds / sharing, exercise discovery → not for this product
- CloudKit sync → local-first only
Paywall on core logging→ lifted 2026-06-16; v2 ships a hard paywall after onboarding (seedocs/pricing.md)
- Open
Unit.xcodeprojin Xcode 16+. - Select the Unit scheme and an iPhone simulator running iOS 18+.
- Build and run (⌘R).
The UnitWidgetExtension target is built alongside the app and provides the rest timer Live Activity.
Proprietary.