Mobile development often starts with a choice: begin a new project from scratch or merge React Native into your existing app. The second approach, known as a brownfield setup, is especially useful when a native app is already in production but needs to gain the flexibility and speed of React Native.Expo has traditionally been viewed as a tool for greenfield apps — projects created entirely with React Native from day one. However, it now provides solutions for brownfield development as well, making it possible to integrate React Native features directly into native environments without sacrificing existing infrastructure.Let’s explore how brownfield development works with Expo, the differences between integrated and isolated approaches, and why an integrated setup offers the best balance of flexibility and developer experience. We’ll focus on practical aspects, using Android as the primary example.Understanding brownfield vs. greenfieldIn mobile development, the choice between greenfield and brownfield sets the direction for the entire project. While greenfield offers a fresh start, brownfield unlocks unique advantages for teams managing existing native applications.Greenfield in shortA greenfield project begins with a completely new app. It provides freedom, clean architecture, and no legacy code to worry about. But it also demands more time, resources, and effort, since every part of the app must be written from scratch.For an established business, this often turns into a challenge that is almost impossible to justify. Picture a large e commerce company with millions of active users. Its native app has been growing for years, layer upon layer of features: secure payments, product recommendations, loyalty programs, and push notifications that drive daily engagement. The app works, customers rely on it, and revenue flows through it every single day.Now imagine telling that company to stop everything and rebuild the app. Development of new features would slow down or even pause. Two separate versions of the app would need to be maintained until the rewrite was ready, doubling the workload. And when the new app finally launched, it would need to perfectly replicate years of refinements just to catch up with what already existed. The risk of bugs, regressions, and unhappy users would be enormous.Why brownfield mattersA brownfield project allows React Native to be integrated directly into an existing native app. Instead of throwing away years of development, brownfield builds on top of what is already in production. This approach creates several important advantages:Parts of the app can be rewritten one by one, without forcing a risky, all at once rewrite. For example, a single flow like onboarding or checkout can move to React Native, while the rest of the app stays native.A native app with millions of users cannot simply be replaced overnight. Brownfield makes it possible to modernize without disrupting users.Reuse of existing code, core features that already work well in native can stay unchanged, while React Native handles the parts where flexibility and speed matter the most.Instead of maintaining two fully separate codebases, teams can incrementally share more and more logic across platforms.When does brownfield development make sense?Brownfield is especially useful in case of:Large native apps with complex infrastructure, where rewriting everything would take years.Businesses that need to keep shipping updates to production while modernizing their stack.Teams interested in React Native but not prepared to fully migrate their app.Companies looking to speed up development for certain parts of the app, while leaving performance critical features in native code.In short, brownfield bridges the gap between existing stability and modern flexibility. It provides a safe path for adopting React Native in mature apps, letting teams innovate faster without starting over.Integrated vs. isolatedWhen setting up a brownfield app with React Native, you can choose between two main architectural approaches: integrated and isolated. Both aim to bring React Native into an existing native environment, but they differ in how deeply the frameworks are connected and how the codebases communicate with each other.The isolated approachIn the isolated setup, React Native lives in its own sandbox. It’s added to the native app as a separate module or “island” that runs independently. Each React Native screen or feature is bundled separately and loaded only when needed. This keeps the native and React Native parts of the app loosely coupled — they share minimal dependencies and communicate primarily through explicit bridges or deep links.This approach is often chosen when:React Native is used for a limited part of the app, such as a single experimental feature.The native infrastructure or build system should remain untouched.The team wants to evaluate React Native without major structural changes.The isolated model provides safety and control. Native and React Native can evolve independently, and failures in one don’t directly affect the other.However, this separation comes at a cost, managing multiple bundles, navigation contexts, and shared state between native and RN components quickly becomes complex. Each integration point requires custom bridging, which reduces the speed benefits React Native is known for.The integrated approachIn the integrated setup, React Native becomes a first class citizen of the app. Instead of being an isolated module, it’s embedded more tightly into the native environment, sharing build tools, navigation, analytics, and configuration with the rest of the project. The native and React Native layers communicate seamlessly, often using shared routing and dependency injection systems.In practice, this means:The same navigation stack can transition smoothly between native and React Native screens.Shared state, configuration, and analytics are consistent across the app.The app can share one unified bundle, reducing complexity and improving startup performance.Integrated architecture is particularly effective when React Native powers multiple screens or critical user flows. It creates a cohesive developer experience — teams can use the same tooling, debugging, and CI/CD pipelines across native and RN code. It also makes it easier to gradually expand React Native’s footprint over time.For this article we chose the integrated approach because it offers the best balance between maintainability and developer experience. It allows us to leverage Expo’s modern toolchain while keeping full compatibility with native infrastructure, a combination that makes hybrid development feel truly unified rather than patched together.Implementing brownfield on AndroidStep 1: Project setupBefore integrating React Native into an existing native environment, we first need a clean Expo project configured for the brownfield setup.Start by creating a new typescript based Expo app:npx create expo app@latest template blank typescriptFor this guide, we’ll name our project expo brownfield:Once the project is created, navigate to the directory and prebuild it for Android:cd expo brownfield && npx expo prebuild platform android cleanThis command generates the native Android directory structure and config files required for integration. The clean flag ensures that everything starts fresh, avoiding potential conflicts from previous builds.Step 2: Integrating a native entry pointNow that the Expo project is prebuilt, we can simulate a realistic brownfield environment by adding native Activity. This will serve as a standalone native screen that can later launch a React Native view, just like in a production hybrid app.This Activity represents a typical native screen — it could be a dashboard, onboarding flow, or any part of an existing app that later transitions to React Native:// android/app/src/main/java/com/dawidmatyjasikswm/expobrownfield/NativeActivity.kt