React Native Package Structure Explained: A Deep Dive into the Monorepo Architecture

React Native organizes its entire framework, tooling, and utilities as a Yarn workspaces monorepo under the packages/ directory, with the core runtime residing in packages/react-native and standalone utilities like Metro configs, Babel presets, and Jest configurations distributed as separate npm modules.

The React Native repository on GitHub (facebook/react-native) follows a monorepo pattern that enables independent versioning of utilities while maintaining tight integration between the core framework and its build toolchain. Understanding this React Native package structure is essential for contributors debugging native code and developers customizing their build pipeline.

Monorepo Architecture Overview

React Native uses Yarn workspaces to manage dependencies across multiple packages from a single root package.json. The workspace configuration declares all sub-packages under the packages/* glob pattern:

// https://github.com/facebook/react-native/blob/main/package.json
{
  "private": true,
  "workspaces": [
    "packages/*"
  ]
}

This setup allows react-native to import react-native-codegen directly during development without publishing to npm first, while still enabling each package to be published independently under the react-native-* scope when appropriate.

Core Package Structure

The Main react-native Package

The primary framework code lives in packages/react-native/. This package contains the JavaScript bridge, native modules, UI components, and platform-specific native implementations for Android and iOS.

Key subdirectories within the core package:

  • ReactAndroid/ – Java and C++ sources for the Android native implementation
  • ReactCommon/ – Shared C++ code used by both Android and iOS native layers
  • Libraries/ – JavaScript source files for components and APIs (e.g., Libraries/Components/Text/Text.js)
  • android/ and ios/ – Platform-specific native module configurations

Native Code Organization

The native architecture separates platform-specific code from shared C++ logic:

  • Android: packages/react-native/ReactAndroid/ contains Java packages (com.facebook.react) and JNI bindings to C++ code
  • iOS: Native code resides in packages/react-native/React/ and packages/react-native/ReactCommon/ (shared with Android via C++)
  • Shared C++: ReactCommon/ houses the TurboModule system, Fabric renderer, and core runtime logic used across both platforms

Tooling and Build Packages

Metro Integration

React Native distributes its Metro bundler configuration as standalone packages:

  • packages/metro-config/ – Default Metro configuration used by all React Native apps, exporting getDefaultConfig() for customization
  • packages/metro-runtime/ – Runtime helpers injected by Metro into the JavaScript bundle during bundling

Developers customize their bundling pipeline by extending the default config:

// metro.config.js – placed at the root of your RN app
const { getDefaultConfig } = require('metro-config');

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts },
  } = await getDefaultConfig();

  return {
    transformer: {
      babelTransformerPath: require.resolve('react-native-babel-transformer'),
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg'],
    },
  };
})();

Babel and Code Generation

The build pipeline relies on specialized Babel and code generation packages:

  • packages/react-native-babel-preset/ – Babel preset compiling RN-specific syntax (JSX, Flow, TypeScript)
  • packages/react-native-babel-transformer/ – Transformer implementation used by Metro
  • packages/react-native-codegen/ – Generates typed native module code from Flow/TypeScript definitions, creating the TurboModule bindings between JavaScript and native code

Testing Infrastructure

React Native provides pre-configured testing utilities:

  • packages/jest-preset/ – Jest preset configured for React Native component testing, including module name mapping and transform settings
  • packages/eslint-plugin-react-native/ – ESLint rules enforcing RN-specific best practices
  • packages/eslint-config-react-native/ – Shareable ESLint configuration

Example Jest configuration:

// jest.config.js
module.exports = {
  preset: 'react-native',
  setupFiles: ['./jest/setup.js'],
  transformIgnorePatterns: [
    'node_modules/(?!(react-native|my-project|react-native-codegen)/)',
  ],
};

Development and Debugging Utilities

Several packages support the development workflow and debugging:

  • packages/dev-middleware/ – Development server middleware handling hot reloading, symbolication, and debugging protocol translation
  • packages/debugger-shell/ – Backend debugger shell used by Flipper and React Native Debugger
  • packages/debugger-frontend/ – Frontend UI components for the debugging interface
  • packages/community-cli-plugin/ – Implements community-driven CLI commands such as react-native-clean-project

Standalone Utility Packages

React Native extracts certain utilities as standalone packages to allow usage without importing the entire framework:

  • packages/virtualized-lists/ – Standalone implementation of FlatList, SectionList, and VirtualizedList that can be consumed independently of the core native bridge

This enables library authors to use React Native's list virtualization logic in web projects or other React environments without pulling in native module dependencies.

Build Process and Code Generation

The React Native package structure supports a sophisticated build pipeline orchestrated through the root scripts/ directory:

  1. Codegen Phasereact-native-codegen scans Flow/TypeScript definitions in packages/react-native/Libraries/ and generates native binding code for TurboModules and Fabric components
  2. Babel Transformationreact-native-babel-transformer compiles modern JavaScript, JSX, and Flow types to ES5 compatible code
  3. Metro Bundlingmetro-config provides the bundler configuration that packages JavaScript and assets for deployment
  4. Package Preparation – Each package's prepare script compiles source code into distribution folders before npm publishing

This modular architecture allows the React Native team to version and release tooling independently from the core framework runtime.

Summary

  • React Native uses a Yarn workspaces monorepo with all publishable code under packages/
  • The core framework resides in packages/react-native/, containing JavaScript libraries (Libraries/), Android native code (ReactAndroid/), and shared C++ code (ReactCommon/)
  • Build tooling is modularized into separate packages: metro-config, react-native-babel-preset, react-native-codegen, and react-native-babel-transformer
  • Testing utilities include jest-preset, eslint-plugin-react-native, and eslint-config-react-native
  • Development workflow packages include dev-middleware, debugger-shell, debugger-frontend, and community-cli-plugin
  • Standalone utilities like virtualized-lists can be consumed independently without the full framework

Frequently Asked Questions

Where is the main React Native source code located?

The main React Native source code is located in packages/react-native/ within the monorepo. This directory contains the JavaScript bridge code in Libraries/, Android-specific native code in ReactAndroid/, and shared C++ code in ReactCommon/ that powers both Android and iOS platforms.

How does React Native organize its native code for Android and iOS?

React Native organizes native code using a split architecture where platform-specific code resides in separate directories while shared logic uses C++. Android code lives in packages/react-native/ReactAndroid/ (Java and JNI bindings), while iOS code is in packages/react-native/React/ and packages/react-native/ReactCommon/ contains the shared C++ TurboModule and Fabric renderer implementations used by both platforms.

Can I use React Native's list components without importing the entire framework?

Yes, you can use React Native's virtualization logic independently through the virtualized-lists package located at packages/virtualized-lists/. This standalone package exports FlatList, SectionList, and VirtualizedList implementations that can be consumed in web projects or other React environments without pulling in the native bridge dependencies required by the core react-native package.

What is the purpose of react-native-codegen in the package structure?

react-native-codegen located in packages/react-native-codegen/ is a build-time tool that generates typed native module bindings from JavaScript type definitions. It reads Flow or TypeScript interface definitions in the core package and automatically generates the C++ and platform-specific code needed for TurboModules and Fabric components, ensuring type safety between JavaScript and native code without manual boilerplate.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →