Cross-platform application that helps weightlifters calculate optimal plate distribution for barbell exercises. Available as a web app (Solid.js) and mobile app (React Native/Expo).
- Calculate plate distribution for target weight
- Select available plate weights
- Choose barbell type (45 lb or 33 lb)
- Percentage calculator for training programs
- Manual plate counter
- Light/dark theme support
- State persistence across sessions
packages/
shared/ # Framework-agnostic calculation logic & types
web/ # Solid.js web application
mobile/ # React Native + Expo mobile application
- Pure TypeScript calculation logic
- Type definitions (BarWeight, PlateWeight, PlatePair)
- Constants (storage keys, input constraints)
- Framework-agnostic, used by both web and mobile
- Solid.js 1.9.10
- TypeScript 5.9.3 (strict mode)
- Vite 5.4.21
- Tailwind CSS 4.1.17 + DaisyUI 5.4.7
- React Native 0.76.9
- Expo SDK 52
- Expo Router 4.0 (file-based routing)
- Zustand 5.0.3 (state management)
- NativeWind 4.1.28 (Tailwind for RN)
- AsyncStorage persistence
- Node.js 18+
- pnpm 8+
pnpm installRun Web App:
pnpm dev:webOpens at http://localhost:5173
Run Mobile App:
pnpm dev:mobileThen press i for iOS simulator or a for Android emulator
Build All Packages:
pnpm build:allTypeScript Check:
pnpm typecheckRun Tests:
pnpm testWeb:
pnpm --filter @barbell/web dev
pnpm --filter @barbell/web build
pnpm --filter @barbell/web serveMobile:
pnpm --filter @barbell/mobile start
pnpm --filter @barbell/mobile ios
pnpm --filter @barbell/mobile androidShared:
pnpm --filter @barbell/shared test
pnpm --filter @barbell/shared test:watchUnit tests for shared calculation logic:
cd packages/shared
pnpm test15 test cases covering:
- Basic calculations (135, 225, 315 lb)
- Edge cases (target < barbell, no plates)
- Multiple plate types
- Barbell weight variations (33/45 lb)
- Disabled plates
- Greedy algorithm verification
- Fractional plates (0.25, 0.5 lb)
- Max weight scenarios
Deploy packages/web/dist to Vercel, Netlify, or any static host.
Use EAS Build:
cd packages/mobile
eas build --platform ios
eas build --platform android- Web: Solid.js createStore with localStorage
- Mobile: Zustand with AsyncStorage persistence
Both platforms import from @barbell/shared:
import { calculatePlates, type PlateWeight } from '@barbell/shared';Greedy algorithm using largest plates first:
- Sort enabled plates by weight (descending)
- For each plate, add as many pairs as fit
- Return plate distribution per side
MIT