Files
SwimBuddy/AGENTS.md
T

3.1 KiB

SwimBuddy

Swimming workout tracker with Apple Watch companion app. Expo 57 + React Native 0.86 + NativeWind v5 + Drizzle ORM + Swift Watch target.

Commands

npx expo start              # Dev server
npx expo run:ios            # Build & run on iOS
npx expo prebuild -p ios    # Regenerate ios/ dir (safe — targets/ persists)
npx drizzle-kit generate    # Regenerate SQL migrations after schema changes

No npm test or lint scripts exist yet. No babel.config.js — NativeWind v5 uses CSS-first config.

Project Structure

src/
  features/<name>/screens/   # Screen components (registered in navigators)
  features/<name>/components/# Feature-specific UI
  features/<name>/hooks/     # Feature-specific hooks
  components/                # Shared UI primitives (flat)
  hooks/                     # Shared hooks
  navigation/                # React Navigation (RootNav, TabNav, feature stacks)
  db/                        # Drizzle schema, client, relations, operations
  providers/                 # DatabaseProvider, SettingsProvider (MMKV)
  utils/                     # formatTime, calculateSwolf, etc.
  constants/                 # strokes, poolLengths, colors
  types/                     # workout.ts, common.ts
  modules/watch-connectivity/# Expo native module bridging WCSession
targets/watch/               # Apple Watch app (Swift/SwiftUI) — survives prebuild

Key Conventions

  • Path aliases: @/, @features/, @components/, @db/, etc. (tsconfig.json)
  • Feature-based folder structure with type-based shared layer
  • NativeWind v5: className prop, no babel config, CSS-first. Use className not StyleSheet
  • className types: nativewind-env.d.ts at root — don't delete
  • lightningcss pinned to 1.30.1 in package.json overrides — required by NativeWind v5

Watch Target

  • Lives in targets/watch/, NOT in ios/ — survives expo prebuild --clean
  • Config: targets/watch/expo-target.config.js
  • Build: open ios/SwimBuddy.xcworkspace in Xcode, select Watch scheme
  • Uses App Groups (group.nl.guido-it.swimbuddy) for data sharing via UserDefaults
  • WCSession for real-time messaging, transferUserInfo for reliable offline sync
  • HealthKit for swim workout tracking (indoor swimming)
  • Swift types StoredWorkout, StoredSet, CompletedLap in WorkoutManager.swift

Database

  • expo-sqlite + Drizzle ORM (SQLite dialect, expo driver)
  • Schema: src/db/schema.ts — 4 tables: templates, workouts, sets, laps
  • Relations: src/db/relations.ts
  • CRUD: src/db/operations.ts
  • Client: src/db/client.ts — exports db and DATABASE_NAME
  • Migrations in drizzle/ — generated by npx drizzle-kit generate

Gotchas

  • metro.config.js has .sql in sourceExts — required for Drizzle migration imports
  • expo prebuild clears and regenerates ios/ by default. Use --no-clean to preserve
  • Watch target compiles as separate Xcode target — not a RN module
  • react-native-css is a NativeWind v5 peer dependency — don't remove
  • @bacons/apple-targets plugin must be in app.json plugins array

Expo Docs

Expo SDK 57: https://docs.expo.dev/versions/v57.0.0/