A custom mobile & web UI for Social Boulder β track your climbing sessions, explore gym boulders, and follow your progress.
Built with β€οΈ by climbers, for climbers. Connects directly to the Social Boulder backend via the DDP (Meteor.js WebSocket) protocol.
- πΊοΈ Browse boulders by gym, grade, and color β immersive card feed with full-width photos
- π Sign in with your Social Boulder account β or browse as a guest
- ποΈ Multi-gym support β onboarding picker, switch gym from the header, search by name or city
- πΌοΈ Full-width boulder photos with holds color badge and label dot
- π Mini gym floor plan on each card with the boulder's zone highlighted
- π¬ Play beta videos full-screen on boulder detail (Mux HLS, works on iOS/Android/web)
- β Log sends and flashes β buttons adapt to your current status (sent/flashed)
- β€οΈ Like boulders β floating heart button, fills instantly
- π¬ View user comments and beta videos on each boulder
- β³ See the planned teardown date for each boulder
- π’ Cards show your personal status (sent β, flashed β‘, liked β₯) at a glance
- π Stats update instantly on action (optimistic updates)
- π Multi-language support (French & English)
- π€ Profile page β avatar, stats per gym (total sends incl. dismounted boulders, best grade, last send date)
- π Light & dark mode
| Layer | Technology |
|---|---|
| Framework | Expo + Expo Router |
| Styling | NativeWind v4 (Tailwind CSS) |
| UI components | react-native-reusables + lucide-react-native |
| Backend | DDP over WebSocket (simpleddp) |
| Auth | expo-secure-store (keychain) + expo-crypto (SHA-256) |
| Video | expo-video (native) + hls.js (web) |
| i18n | i18next + expo-localization |
| Design system | French Rose #e35f8d Γ Teal #2aab7e Β· Outfit + DM Sans |
| Storybook | @storybook/react-native |
- Node.js 18+
- Expo Go on your device, or an iOS/Android simulator
npm installCopy .env.example to .env and fill in your credentials:
cp .env.example .env# iOS
npm run ios
# Android
npm run android
# Web
npm run webExplore the design system components interactively:
npm run storybook# Lint
npm run lint
# Auto-fix lint issues
npm run lint:fix
# Format with Prettier
npm run format
# Check formatting
npm run format:checkapp/ β Expo Router screens
login.tsx β Login screen (email/password + guest mode)
onboarding.tsx β Gym selection on first launch (or when no gym selected)
profile.tsx β Profile screen (avatar, gym stats, logout)
components/
Avatar.tsx β Circular user avatar with initials fallback
GymAvatar.tsx β Gym logo avatar (S3 logo + initials fallback)
GymPickerModal.tsx β Bottom-sheet gym switcher with search + sections
GymStatsCard.tsx β Gym stats card (sends incl. dismounted, best grade, last send)
design-system/ β Storybook stories
ui/ β react-native-reusables components
lib/
auth/ β AuthProvider, useAuth(), secure storage
i18n/ β Translations (fr, en)
known-gyms.ts β Static GymInfo list + getGymLogoUrl() + getGymDisplayName()
theme.ts β Design tokens
utils.ts β cn() helper
hooks/ β Custom React hooks
use-current-user.ts β Subscribe users.single β current user profile
use-gyms-list.ts β Dynamic gym list from _gyms.list DDP, merged with KNOWN_GYMS
use-selected-gym.ts β AsyncStorage-backed selected gym (null β redirect to onboarding)
use-user-sends-count.ts β _boulders.count for a user (incl. closed boulders)
exploration/ β DDP reference scripts (Node.js)
Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
You are free to use, share, and adapt this project for non-commercial purposes, as long as you give appropriate credit. Commercial use is not permitted.