Skip to content

Best-practices audit

The code written before the agent skills were adopted (Phases 0–3 offline), checked against the vendored skills in .claude/skills/. Fix pending items when you touch the area, and move them to “Done” with the commit. Started 2026-10-10.

Measure before and after any performance change (the skill’s own rule). Bundle sizes below are release JS bundles: pnpm exec react-native bundle --platform android --dev false --minify true ….

Item Skill reference Result
zod’s locale barrel shipped ~60 languages the app never shows bundle-barrel-exports, bundle-library-size Metro resolves it to metro/zod-locales.js (English only): −295 KB
FormatJS Intl polyfills needed Intl.Locale (~390 KB) native-sdks-over-polyfills (“remove Intl polyfills only after checking Hermes coverage”) intl-pluralrules + relative-time-format: −333 KB. Checked in Hermes: Arabic plurals and relative times correct
Total Android bundle 4,176 KB → 3,548 KB (−15%)
Phase 3 libraries measured (2026-10-11) bundle-library-size +174 KB: React Native Firebase JS ~82 KB, device-info 33 KB, new app code. The Firebase web SDK it depends on is not in the bundle
Barrel index.ts files in shared/ui, shared/api, data, entities/* (2026-10-11) bundle-barrel-exports Removed; 29 files import from the defining module. Android release bundle 3,831 → 3,824 KB. no-restricted-imports rejects folder imports (@/shared/i18n and @/shared/ports define their contents and stay), and app/ may import a feature only through its index.ts
React Compiler lint rules weren’t enabled (2026-10-11) js-react-compiler The eslint-plugin-react-hooks 7 compiler rules are on as errors; no violations. react-compiler-healthcheck@1.0.0: 55 of 55 components compile, no incompatible libraries
Legacy accessibility* props (2026-10-11) react-native-testing (rule 10) ARIA props on React Native’s components and on our own (Icon, Image and SegmentedControl take aria-label). Headings use role="heading". no-restricted-syntax rejects the old props; the wrappers around react-native-svg, FastImage and the bottom sheet keep them, because those libraries don’t translate aria-*
Item Skill reference Notes
Feed rows with and without images share one recycling pool js-lists-flatlist-flashlist Add getItemType={post => (post.imageUrl ? 'image' : 'text')}
Bottom sheets on iOS can render under native-stack modals js-bottomsheet containerComponent with FullWindowOverlay on iOS; check on device
Tests query by testID where an accessible role exists react-native-testing Prefer getByRole(…, { name }); keep testID for Maestro and non-semantic views
No startup (TTI) measurement native-measure-tti Phase 4: react-native-performance markers, cold starts only
Bundle size isn’t tracked per PR bundle-analyze-js Phase 4: report the size in CI (no failing budget, per the questionnaire)
  • Controlled TextInput (react-hook-form): kept. The New Architecture removes the flicker the skill warns about, and the forms validate on every change (js-uncontrolled-components).
  • FlashList v2 without estimatedItemSize, R8 on, 16 KB page alignment checked in CI, native-stack screens, Zustand only for client state, React Compiler on, React Navigation static API, one module per icon, MSW absent from release bundles: all match the skills.
  • Hermes mmap (bundle-hermes-mmap) only applies to React Native 0.78 and earlier.