Skip to main content

mobile-patterns

Use when working in apps/mobileAppYC. Covers React Native architecture, navigation, Redux Toolkit state management, and mobile-specific conventions.

Quellinformationen

Repository
YosemiteCrew/Yosemite-Crew
Letzte Quellaktivität
26. August 2026 um 02:18
Erkannte Sprache von SKILL.md
Englisch
Sterne
2.019
Forks
84

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
mobile-patterns
description
Use when working in apps/mobileAppYC. Covers React Native architecture, navigation, Redux Toolkit state management, and mobile-specific conventions.
# Mobile App Patterns — Yosemite Crew ## Description Use this skill when working on apps/mobileAppYC. Covers React Native architecture, navigation, Redux state management, and mobile-specific conventions. TRIGGER: any task in apps/mobileAppYC — screens, components, navigation, state, or native integrations. --- ## Architecture ``` apps/mobileAppYC/ src/ app/ ← Redux store.ts + typed hooks.ts features/ ← feature slices: <domain>/{screens,components,hooks,services,<domain>Slice.ts,selectors.ts} shared/ ← cross-feature components, screens, stores, services, utils navigation/ ← React Navigation config localization/ ← translation files (i18next) theme/ ← design tokens and theming config/ ← environment/config values context/ ← React contexts types/ ← shared TS types assets/ ← images, fonts ``` New code follows the feature-slice pattern: put screens, components, and services inside the owning `src/features/<domain>/` directory, not in global folders. --- ## State Management **Redux Toolkit** (not Zustand — that's frontend only). Redux Persist is enabled. ```ts // Define a slice import { createSlice } from '@reduxjs/toolkit'; const appointmentSlice = createSlice({ name: 'appointments', initialState, reducers: { ... }, }); ``` Never mix Redux and local `useState` for the same piece of data. Local state is for ephemeral UI state (modal open, input focus). Shared/persisted state goes in Redux. --- ## Navigation **React Navigation 7** with bottom tabs + native stack + drawer. ```ts // Type your navigation params type RootStackParamList = { Home: undefined; AppointmentDetail: { appointmentId: string }; }; ``` Never navigate with bare strings — always use typed route names. --- ## Forms **react-hook-form + Yup** for all forms. ```tsx const schema = yup.object({ name: yup.string().required() }); const { control, handleSubmit } = useForm({ resolver: yupResolver(schema) }); ``` --- ## Internationalisation All user-visible strings must go through **i18next**. ```tsx import { useTranslation } from 'react-i18next'; const { t } = useTranslation(); <Text>{t('appointments.title')}</Text>; ``` Never hardcode English strings in components. ### UI copy normalization - Never render raw backend enums or role acronyms directly in UI text (example: `PAYMENT_AT_CLINIC`, `VET`). - Map technical values to user-friendly labels before rendering. - Avoid `Actor` as a user-facing label; prefer contextual labels (`Lead`, `Support`) or neutral `Updated by`. --- ## Authentication SuperTokens is the mobile auth provider (email OTP + social through the provider; `supertokens-react-native` manages sessions). Firebase remains for push notifications only. Never bypass the SuperTokens session layer for core auth. --- ## Payments `@stripe/stripe-react-native` — use the SDK's pre-built UI sheets where possible. Never build custom card input from scratch. --- ## Testing - **Jest 30** + Testing Library for React Native. Jest 30 renamed the targeting flag to `--testPathPatterns` (plural) - the old singular form errors. - **Detox** for E2E (run separately, not part of standard CI). - Target tests: `pnpm --filter mobileAppYC run test -- --testPathPatterns="path/to/file"` - Never run the full suite without `--testPathPatterns`. ### Coverage Mandate — Non-Negotiable **Target: ≥ 95% Statements, Branches, Functions, Lines across `apps/mobileAppYC`. Every change must move coverage upward, never downward.** #### Rules that apply to every task — add, modify, remove 1. **Any file you touch must finish with equal or higher coverage than you found it.** Run the targeted test and confirm before handoff. 2. **Any file you create must hit ≥ 90% Statements, Branches, Functions on first commit.** New code with no tests is a blocker — do not declare the task done. 3. **When you delete code**, delete the corresponding test code too. Dead test scaffolding inflates noise and hides real gaps. 4. **When you modify behaviour** (rename, refactor, add a branch, change a conditional), update every existing test covering the changed path AND add new cases for new branches. 5. **Snapshot tests count but do not substitute** for behavioural assertions. Every logical branch needs at least one assertion that validates the outcome. #### Test types required — use all of them, not just one | Layer | Tool | When required | | --------- | ---------------------------- | ---------------------------------------------------------------------------------- | | Unit | Jest | Every service, Redux slice, hook, utility, helper | | Component | React Testing Library for RN | Every screen and reusable component — render + interaction + conditional rendering | | Snapshot | Jest `toMatchSnapshot` | Stable UI layouts — complement behavioural tests, never replace them | | E2E | Detox | Auth flows, booking, checkout, payment, any critical user journey | All four layers must grow together. Do not add unit tests while leaving Detox untouched for critical flows, and vice versa. #### Coverage enforcement workflow ```bash # After every change, run coverage for the touched file(s): pnpm --filter mobileAppYC run test -- --testPathPatterns="<YourFile>" --coverage --collectCoverageFrom="src/path/to/YourFile.tsx" # Check — if Statements/Branches/Functions dropped vs what you started with, add tests before declaring done. ``` --- ### New code = new tests (mandatory) **Every new module, screen, service, hook, slice, or utility added to `apps/mobileAppYC` must ship with tests in the same batch. No exceptions.** | What you add | What you must also add | | ------------------------------------------- | -------------------------------------------------------------- | | Service function / API call | Jest unit: success + all error branches | | Redux slice | Jest: every reducer, action creator, selector, and async thunk | | Custom hook | `renderHook` covering all return values and state branches | | Utility function | Jest unit with full branch coverage | | Screen component | Jest + Testing Library render + key interaction | | E2E-critical flow (auth, booking, checkout) | Detox test | **Coverage bar for any new file you author: Statements ≥ 90%, Branches ≥ 90%, Functions ≥ 90%.** Never leave an existing file in a worse coverage state than you found it. ### Mandatory pre-commit checks (run in order, never skip) ```bash npx tsc --noemit # from apps/mobileAppYC/ pnpm --filter mobileAppYC run lint pnpm --filter mobileAppYC run test -- --testPathPatterns="<YourFile>" ``` --- ## App Store Submission Full reference: [`docs/guide/mobile-app-submission-guide.md`](../../../docs/guide/mobile-app-submission-guide.md) ### Pre-Submission Checklist Before every submission run these checks — **do not bump versions mid-review**: 1. **Production config** — `src/config/variables.local.ts`: - `USE_DEV_API = false` - `UI_FEATURE_FLAGS.forceLiquidGlassBorder = false` - `MOBILE_CONFIG_BEHAVIOR.overrides.forceLiquidGlassBorder = false` 2. **Silence console output** - nothing to do. The console-silencing block in `App.tsx` is guarded by `if (!__DEV__)`, so a release build is quiet and a Debug build keeps its logs (search for `const noop` to confirm it is intact): ```ts if (!__DEV__) { const noop = () => {}; console.log = noop; console.info = noop; console.debug = noop; console.trace = noop; } ``` It used to run unconditionally, which muted Debug builds too and is why a token-expiry bug warned on every call for a whole release without anyone seeing it. Do not remove the `__DEV__` guard to "make release quieter" - it already is. 3. **Version bumps** (only for a new submission or after rejection): | Platform | File | Field | | -------- | --------------------------------- | ------------------------- | | Android | `android/app/build.gradle` | `versionCode` | | Android | `android/app/build.gradle` | `versionName` | | iOS | `mobileAppYC.xcodeproj` (pbxproj) | `MARKETING_VERSION` | | iOS | `mobileAppYC.xcodeproj` (pbxproj) | `CURRENT_PROJECT_VERSION` | Read the current values from those files and bump by one — never trust a hardcoded version table in docs; they go stale after every release. ### Android Build ```bash # From apps/mobileAppYC/android/ — clean first rm -rf app/build build .cxx .gradle && ./gradlew clean # APK (testing/sideload) ./gradlew assembleRelease # Output: android/app/build/outputs/apk/release/app-release.apk # AAB (Play Store) ./gradlew bundleRelease # Output: android/app/build/outputs/bundle/release/app-release.aab ``` Keystore `my-release-key.keystore` must be at `android/app/` and `android/gradle.properties` must have `YC_RELEASE_STORE_FILE`, `YC_RELEASE_STORE_PASSWORD`, `YC_RELEASE_KEY_ALIAS`, `YC_RELEASE_KEY_PASSWORD`. ### iOS Build ```bash # From apps/mobileAppYC/ios/ — clean first rm -rf Pods build Podfile.lock ~/Library/Developer/Xcode/DerivedData/* pod deintegrate && pod install ``` Archive in Xcode: 1. Open `ios/mobileAppYC.xcworkspace` (**not** `.xcodeproj`). 2. Select a physical device or "Any iOS Device (arm64)" — **not** a Simulator. 3. **Product → Clean Build Folder** (`⇧⌘K`) → **Product → Archive**. 4. In Organizer: **Distribute App** → upload to both **Preflight** and **App Store Connect**. ### Post-Approval After both stores go live, update `README.md`: - **Current production releases** table with new versions. - **Release history** table — add a row per platform with version + feature summary. ### Common Pitfalls - Opening `.xcodeproj` instead of `.xcworkspace` — Pods will not be linked. - Forgetting `pod install` after cleaning — build fails with missing headers. - `USE_DEV_API = true` left on — app hits dev backend in production. - Wrong keystore signing AAB — Play Store upload rejected. - Bumping version mid-review — Apple treats it as a new binary and restarts review. --- ## Gotchas - `react-native-permissions` requires explicit permission requests before accessing camera, location, contacts — never assume granted. - `react-native-fs` paths differ between iOS and Android — use `RNFS.DocumentDirectoryPath` not hardcoded paths. - Redux Persist can cause stale state after schema changes — bump the persist version key when changing slice shape. - `@gorhom/bottom-sheet` requires `GestureHandlerRootView` at app root — it's already there, don't remove it. - Reactotron is dev-only — guard with `__DEV__` checks. - i18n resource files are in `src/localization/` (there is no `src/i18n/`) — add new keys there before using `t()`.
Auf GitHub ansehen