Taking Over a React Native Codebase: Our Audit Checklist

In this article
  1. Can it be built?
  2. Dependency health
  3. Structure and state
  4. Native code
  5. Crashes and performance
  6. Security basics
  7. Tests and release process
  8. Store compliance
  9. Deciding what to do

A React Native app arrives with no documentation, a previous team that has moved on, and a backlog of complaints: crashes on some Android phones, a build that only works on one developer's laptop, a store listing that was rejected last month. The client needs it fixed and then extended. This is a common starting point for us, and over the years it has produced a checklist.

The checklist exists because the first instinct, to start fixing the loudest problem, is usually wrong. The loudest problem is rarely the most important one, and fixing it without understanding the codebase often creates two new ones. An audit comes first. It takes a week or less, and it tells you whether to stabilise, refactor or rebuild.

Can it be built?

Before reading any code we try to produce a release build for both platforms on a clean machine. This single exercise reveals more than any review: missing environment variables, undocumented native patches, pinned dependencies that no longer install, signing certificates nobody can find. If the app cannot be built reproducibly, nothing else can be fixed safely, so this is always the first thing we repair.

Dependency health

We list every dependency with its version, its latest version, and whether it is still maintained. React Native moves quickly, and libraries that have not been updated in two years are liabilities, especially native ones. The React Native version itself matters most. An app several versions behind faces a multi-step upgrade before it can use current libraries, and that upgrade has to be planned, not improvised.

Structure and state

We look for the shape of the application. Is there a clear separation between screens, components, business logic and API access, or does every screen talk to the network directly? How is global state handled, and is it one approach or three? Is there TypeScript, and if so, how much of the code is typed as "any"? None of these are fatal, but together they predict how expensive each future feature will be.

Native code

Many inherited apps contain custom native modules or patched libraries that nobody remembers writing. We catalogue every piece of native code, work out what it does and whether a maintained library now does the same job. Native code that no current team member understands is the most common source of mysterious crashes.

Crashes and performance

If crash reporting is in place, we read it. If it is not, adding it is the first improvement we ship, because a week of real crash data is worth more than any amount of speculation. We also check the obvious performance problems: lists that render every item at once, images loaded at full resolution, and effects that re-run on every render.

Security basics

API keys and secrets committed to the repository, tokens stored in plain preferences, no certificate pinning on apps that handle money, and debug endpoints left in production builds. These are quick to find and important to fix before any new feature work.

Tests and release process

We count the tests and check whether they run. We check how releases happen: by hand from a laptop, or through a pipeline. An app with no tests and a manual release is not unusual, but it changes the plan, because the first few sprints have to build the safety net that lets later sprints move fast.

Store compliance

We read the last few store review outcomes and check the app against current App Store and Google Play requirements: privacy declarations, data safety forms, permissions that are requested but not used, and SDK versions that will soon be rejected. Store rejections stop releases entirely, so they rank high.

Deciding what to do

The audit produces a written report with three parts: what we found, what we would fix first, and whether the codebase is worth keeping. The last point is the one clients care about most, and the answer is usually yes. Most inherited React Native apps are salvageable, and a stabilise-first plan gets them to a reliable state in a few sprints. We recommend a rebuild only when the structure is beyond repair or the React Native version is so old that upgrading costs more than starting over.

Whatever the answer, you get it before spending anything on feature work. If you have an app in this situation, our React Native practice covers codebase rescue, and an audit is free to scope.

Working on Something Similar?

Tell us what you are building. Scoping is free, and we will say plainly what we would and would not do.

Get Free Consultation