Inspiration
We spend hours hunched over laptops every day and barely notice until our neck starts aching. Most posture apps either require expensive hardware or just remind you on a timer, they don't actually know if you're slouching. We wanted something that watches your posture in real time, learns your personal baseline, and only bugs you when it actually matters.
What it does
PosturePal uses your webcam and MediaPipe pose detection to track your posture live and score it 0–100. You calibrate once by sitting in your best posture, which sets a personal baseline, so your camera angle and desk height don't affect the score, only your actual movement does. From there, PosturePal tracks five factors (head drop, forward lean, shoulder tilt, ear tilt, and lateral lean) and alerts you the moment you slip below your custom threshold, with an in-app banner, a sound alert, and an OS push notification that fires even when you're on a different tab. Sessions are saved to your account, you can view your score history and trend chart, and compete on a leaderboard with friends.
How we built it
- Frontend: React + Vite + Tailwind CSS
- Pose detection: MediaPipe Pose loaded via CDN
- Auth & data: Firebase Authentication and Firestore for user accounts, sessions, and the leaderboard
- Alerts: Web Audio API for sound, the browser Notifications API for OS-level push notifications
- Background tab support: A hybrid
requestAnimationFrame/setTimeoutloop with avisibilitychangelistener so detection keeps running at 2fps when you switch tabs - Settings sync: A custom
useLocalStoragehook that dispatches browser events so settings changes propagate instantly across all components without a page reload
Challenges we ran into
Getting MediaPipe to run reliably in the browser was the hardest part. We hit a silent failure where pose detection would stop working entirely, the camera feed showed but no landmarks were detected. It turned out to be a macOS system-level camera permissions issue unrelated to our code, but it cost us hours of debugging. We also had to figure out that requestAnimationFrame completely freezes when a tab is hidden, which meant our background alerting did nothing, the fix required listening to the visibilitychange event to rescue the stalled loop. Wiring settings so they actually affect the running app (not just get saved to localStorage) required building a mini pub/sub system on top of useLocalStorage.
Accomplishments that we're proud of
The calibration system is something we're genuinely proud of. By measuring deviation from the user's own snapshot rather than comparing to a fixed "ideal" posture, PosturePal works for people of all heights, desk setups, and camera positions without any configuration. We're also proud of the alert UX, it fires exactly once when you cross the threshold, clears itself automatically when you recover, and won't re-fire until the next distinct bad episode, so it actually feels helpful rather than annoying.
What we learned
A lot about the browser's media and audio APIs and all the places they behave unexpectedly, camera permissions being an OS-level concern separate from browser permissions, requestAnimationFrame silently dying in background tabs, Web Audio needing to be created after a user gesture. We also learned how to architect real-time state that flows correctly across components, and how quickly a small settings system can get complicated if you don't think carefully about how state propagates.
What's next for PosturePal
- Posture history insights — detecting patterns like "you always slouch after 3pm"
- Custom exercises — short stretch break prompts triggered by sustained bad posture
- Better friend social features — challenges, streaks, and weekly score comparisons
- Offline mode — local-only sessions that sync to the cloud when you reconnect
Built With
- css
- firebase
- html
- javascript
- mediapipe
- react
- tailwind
- vite

Log in or sign up for Devpost to join the conversation.