Inspiration

We've all been there — standing in the gym parking lot at 6am, debating whether to go in or just drive to McDonald's instead. The difference between a great workout and skipping? Having someone waiting for you inside.

Most fitness apps focus on tracking reps and calories. None of them solve the actual problem: gym loneliness. RatClub was born from that frustration — the idea that accountability shouldn't require a $100/hour personal trainer. It should just require finding your rat pack.


What It Does

RatClub matches gym-goers with real training partners nearby, based on:

  • 📍 Location & gym
  • 🕐 Schedule compatibility
  • 🏋️ Workout style & goals
  • ⚡ A match score (because data > vibes)

Think Tinder for gains — except nobody ghosts you, because you literally have to show up to the same gym.


How We Built It

Frontend: SwiftUI (iOS) — built screen by screen from a Figma prototype, with a custom design system (smGoldSoft, smBlack, the whole rat aesthetic).

Backend & Database: Supabase (PostgreSQL) — handling auth, real-time chat, user profiles, workout logs, and the buddy-matching logic.

Navigation: A custom AppRouter using ObservableObject + NavigationPath to manage the full app flow from onboarding to the main feed.

Key screens:

  • Matching Map — find training partners near you in real time
  • GymNet — your local gym social feed
  • Workout Logger — track sets, reps, and PRs
  • Chat — coordinate sessions with your matches

Challenges We Faced

1. Xcode hates you (until it doesn't)

Moving files from Cursor into Xcode broke everything — 17 compiler errors on day one, mostly because Xcode silently drops files from the build target when you drag them in. Lesson learned: always check Target Membership.

2. AppRouter: the glue that kept falling apart

Every view depended on AppRouter, but building it incrementally meant the whole project broke every time a new view expected a property that didn't exist yet. We rebuilt it three times before it stuck.

3. import Combine — two words, one hour lost

@Published requires Combine. Swift doesn't tell you that clearly. The error message (does not conform to ObservableObject) sends you in completely the wrong direction.

4. SwiftUI + MapKit dark mode

Getting the map to look good under a dark overlay without the gradient clipping interactive elements took way more ZStack manipulation than any human should endure.


What We Learned

  • Ship the navigation skeleton first. Everything else depends on it.
  • Supabase Row-Level Security is powerful but needs to be set up before you write any data, not after.
  • A good design system (Color+Theme.swift) saves hundreds of lines across 10+ views.
  • The gap between "it compiles" and "it works" is where most of the real work lives.

What's Next

  • [ ] Apple Sign-In
  • [ ] Push notifications for match requests
  • [ ] HealthKit integration
  • [ ] Gym check-in via geofencing
  • [ ] PR leaderboards within your rat pack

Built With

Share this project:

Updates