CodeVetter · Repo Unpack · Contributor handoff
react/react-native
Start with AGENTS.md — it is the canonical contributor doc (repo layout, commands, gotchas). JS is Flow; expect paired .js/.js.flow files and code split between Libraries/ (legacy) and src/private/ (target). Verify with yarn test / yarn fantom / yarn lint / yarn flow-check; build @react-native/codegen once before Metro works. Never hand-edit generated artifacts — regenerate via yarn featureflags / yarn build-types / codegen and keep index.js in sync with index.js.flow. Respect the committed API snapshots (ReactNativeApi.d.ts, ReactAndroid.api, scripts/cxx-api) and the yarn.lock churn from the preinstall hook.
- AGENTS.md is the authoritative onboarding doc: it maps every top-level dir, lists yarn commands, documents the codegen-build prerequisite and the preinstall yarn.lock dirtying — read it before editing.
- JS edits go in packages/react-native/src/private for new code (Libraries/ is the legacy location being migrated); all JS is Flow-typed (@flow strict/strict-local pragmas) and many public modules have a .js.flow twin that must be kept in sync (e.g. index.js vs index.js.flow).
- Verification ladder for a JS change: yarn test <path> (Jest, -test.js files in __tests__), yarn fantom <path> (integration, -itest.js — first run builds the native tester), yarn lint (zero warnings allowed), yarn flow-check, yarn format-check-javascript.
- Bootstrap trap: Metro cannot bundle until codegen is built once — run `yarn --cwd packages/react-native-codegen build`; every other package runs from source so `yarn build` is otherwise unnecessary for development.
- Generated code rule: never hand-edit generated output — native specs produce bindings at build time; feature flags regenerate via `yarn featureflags`; TS types via `yarn build-types` + snapshot ReactNativeApi.d.ts; C++ API via `yarn cxx-api-build`; Android API surface is committed at ReactAndroid/api/ReactAndroid.api. CI validates all of them.
- Test placement conventions: Jest tests live in __tests__/ dirs as *-test.js; Fantom integration tests use *-itest.js and must live inside packages/react-native (Fantom is scoped to RN internals); benchmarks use *-benchmark-itest.js; prefer public-API imports ('react-native') over internals in Fantom tests.
- Safe edit boundaries: tooling packages (community-cli-plugin, dev-middleware, metro-config, codegen) are self-contained with their own __tests__; runtime JS changes should respect __DEV__ gating and warnOnce/invariant patterns; native changes require the matching platform toolchain (Xcode+CocoaPods for iOS, Android SDK+NDK+Gradle).
- Known traps: `yarn install` dirties yarn.lock (preinstall hermes-compiler rewrite — do not commit); Jest moduleNameMapper aliases exist only for setup-env/react-private-interface/unstable-internals-do-not-use — new subpath exports need mapper entries or Jest resolution breaks.
- Runtime verification loop: `yarn start` serves RNTester via Metro on http://localhost:8081 (RCT_METRO_PORT overrides); `yarn android` builds+installs it; sanity-check the bundler with curl 'http://localhost:8081/js/RNTesterApp.bundle?platform=ios&dev=true'.
- Architecture docs live in __docs__/ directories beside the code they describe (indexed by root __docs__/README.md) — e.g. feature flags, inspector proxy protocol, runtime scheduler event loop, intersection/mutation observers; treat them as reference for the subsystem being edited.
- PR conventions: keep changes focused (no unrelated refactors/formatting), complete the changelog category/type tags in the PR template (CHANGELOG.md is compiled at release from PR descriptions), and state exact test commands run plus screenshots for UI changes.