Library / SDK
react-native-config/react-native-config avatar
react-native-config/react-native-config

react-native-config: .env variables for React Native on iOS, Android, macOS and Windows

Bring some 12 factor love to your mobile apps!

4,955 stars657 forksRubyMIT

At a glance

What is it?
react-native-config reads a .env file at build time and exposes the values as a native module, so JavaScript reads Config.API_URL instead of bundling a JSON file. The trade-off is a native build step and zero secret protection.
Who is it for?
Adopt react-native-config if you already build separate iOS and Android targets and want per-environment API URLs and keys selected at build time, with the same .env file feeding both platforms. Do not adopt it if you need secrets hidden from users, since the README states the module does not obfuscate or encrypt them, or if you ship through Expo Go without a native build.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 20 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What react-native-config solves, and for whom

Mobile builds need different values per environment. A staging build points at a staging API host; a production build points at the production host. The usual workaround is a JavaScript constants file plus a conditional on __DEV__, which means the production URL still ships inside the bundle and the native side has no idea which environment it is. react-native-config takes the twelve-factor config idea and applies it to mobile: one .env file at the project root, values read at build time, and a native module that hands them to JavaScript as Config.API_URL.

The audience is teams with a real native build pipeline. The repository ships android/, ios/, windows/ and codegen/ directories, a podspec, and two example apps (Example/ and Example.windows/), so the intended user is someone running pod install and Gradle, not someone tapping around inside Expo Go. The README states the current version is tested with React Native 0.87 on the New Architecture, and with react-native-windows 0.79 on Windows. It also carries a sponsorship note for Open Collective, which is worth reading as a signal about who is expected to fund maintenance work across new React Native releases.

How the native module and codegen fit together

The package.json declares a codegenConfig block with the name RNCConfigSpec, type modules, jsSrcsDir ./codegen, and an Android javaPackageName of com.lugg.RNCConfig. That is the New Architecture path: the JavaScript spec in codegen/ is what TurboModule bindings are generated from, and on iOS the config names the class RNCConfigModule. The JavaScript entry point is index.js with types in index.d.ts, both listed in the published files array next to android/, ios/, windows/, codegen/ and the podspec.

Data flow is one direction and happens at build time. The .env file is parsed by the platform tooling (the Android side through dotenv.gradle, iOS and macOS through the podspec and Xcode build phases), the values are compiled into the native artifact, and JavaScript reads them synchronously from the module. Nothing watches .env at runtime. Change a value, and you rebuild. That is also why the README's warning about autolinking matters: on React Native 0.60 and above, autolinking is what registers the native module and generates the TurboModule bindings, and the README says adding include ':react-native-config' to android/settings.gradle instead does neither, leaving the module resolving to null at runtime.

Installing react-native-config and reading your first value

Add the package with Yarn, then create a .env at the root of the app. The README's example uses API_URL and GOOGLE_MAPS_API_KEY; any key you put there becomes a property on the imported Config object.

bash
yarn add react-native-config

On React Native 0.60 and above there is no link step, because the library is autolinked. The README says to rebuild the app so the native side is picked up, and on iOS or macOS to install the pod first.

bash
(cd ios; pod install)

Android needs one more line, applied as the second line of android/app/build.gradle. The README also mentions that npx react-native-integrate react-native-config can apply the extra steps automatically.

bash
npx react-native-integrate react-native-config

If you apply it by hand, the plugin line looks like this:

code
// 2nd line, add a new apply:
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

Then write the .env file and read it from JavaScript. The README gives this exact shape.

js
import Config from "react-native-config";

Config.API_URL; // 'https://myapi.com'
Config.GOOGLE_MAPS_API_KEY; // 'abcdefgh'

If the config arrives in JavaScript as an empty object, the README points at logcat: look for ReactConfig: Could not find BuildConfig class, and the message lists every package that was tried.

Android BuildConfig resolution and the namespace trap

The Android advanced setup is the part most likely to bite. BuildConfig is generated in a module's namespace, which is not always the same as its applicationId. An applicationIdSuffix or a per-flavor applicationId changes the latter and leaves the former alone. The library resolves this by looking for BuildConfig in the package declaring your Application class, which is the namespace, before falling back to the applicationId. Common variant setups therefore need no extra configuration.

When BuildConfig lives somewhere neither of those points at, you name the package explicitly in android/app/build.gradle. The README notes this value takes priority over the automatic resolution.

code
defaultConfig {
    ...
    resValue "string", "build_config_package", "YOUR_NAMESPACE"
}

YOUR_NAMESPACE has to match the namespace in android/app/build.gradle. On React Native 0.72 and older, the README says to use the package attribute of <manifest> in AndroidManifest.xml instead. Two constraints are documented and worth repeating: react-native-config v1.6.0 and above requires React Native 0.74 or higher on Android, and manual linking is only for React Native below 0.60 or react-native-windows below 0.63. The README explicitly warns against manual linking on 0.60 and above, and against disabling autolinking in react-native.config.js.

The secrets problem react-native-config does not solve

This is where the project is honest and where many adopters are not. The README states plainly that the module does not obfuscate or encrypt secrets for packaging, and that you should not store sensitive keys in .env. It links to an external write-up on hiding secrets in Android apps and concludes that preventing users from reverse engineering mobile app secrets is basically impossible, so the app and its APIs should be designed with that in mind.

That is not a defect in react-native-config; it is a property of shipping a value inside a binary. If your threat model includes a motivated user extracting an API key from an APK or an IPA, .env is the wrong container regardless of which library parses it. The practical split is: public configuration (API base URLs, map keys restricted by bundle identifier, feature flags, build numbers) belongs in .env, and anything that grants privileged access belongs behind a server that holds the real credential. The second limitation is build-time coupling. Because values are compiled in, switching environments means switching builds, not switching a runtime setting. Teams that want one binary to point at different backends at runtime will find the model a poor fit.

react-native-config compared with react-native-dotenv and Expo config

react-native-dotenv is the closest alternative and takes a different route: it is a Babel transform, so .env values are replaced inline in the JavaScript bundle at transform time. There is no native module, no pod install, no Gradle plugin, and nothing to autolink, which makes it easy to drop into a project that has no native build step. The cost is that the values exist only in JavaScript. Native code cannot read them, so a value needed in an Android manifest placeholder, an iOS Info.plist, or a Gradle build config is out of reach. react-native-config, by contrast, puts the values where native tooling can reach them, which is why it needs the dotenv.gradle apply line and the pod install.

For Expo projects the split is similar. Expo's own config and environment variable handling works within the managed workflow, where you are not editing native projects, but it does not give you a native module that iOS and Android build scripts can consume. If you have ejected or use a development build with native directories present, react-native-config becomes viable; if you are staying in the managed workflow, it is not the tool you want. The deciding question is whether anything outside JavaScript needs the value.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-10. Releases v1.7.0, v1.7.1 and v1.7.2 all landed in late August 2026, with v1.7.2 on 2026-08-28, so the project is receiving changes. Maintenance is partly funded through Open Collective, and the README frames sponsorship as paying for the work that keeps the library working across new React Native releases. That framing is worth taking literally: the recurring cost of this dependency is tracking React Native's native module changes, especially the New Architecture codegen, not reading .env files.

Upgrade cost concentrates in three places. The Android floor moved to React Native 0.74 at v1.6.0, so older apps are pinned to older releases. The codegenConfig in package.json ties the package to the TurboModule spec, so a React Native upgrade that changes codegen conventions reaches you through this library. And the Windows target tracks react-native-windows, which the README notes is at 0.79 as the newest version it supports. The licence is MIT, which permits commercial and closed-source use; the repository's LICENSE file is the authoritative text and nothing here is legal advice. The practical implication of MIT combined with Open Collective funding is that you can use the package freely, and if your release cycle depends on it, the maintenance question is a business decision rather than a licensing one.

Editorial conclusion

Adopt react-native-config if you already build separate iOS and Android targets and want per-environment API URLs and keys selected at build time, with the same .env file feeding both platforms. Do not adopt it if you need secrets hidden from users, since the README states the module does not obfuscate or encrypt them, or if you ship through Expo Go without a native build. Before committing, verify the Android plugin line in android/app/build.gradle, confirm the build_config_package resValue matches your namespace when BuildConfig lives elsewhere, and check that the module is not manually linked on React Native 0.60 or above.

Frequently asked questions

How do I install react-native-config?

Run yarn add react-native-config. On React Native 0.60 and above there is no link step because the library is autolinked, but you must rebuild the app, and on iOS or macOS run (cd ios; pod install) first. Android additionally needs the dotenv.gradle apply line in android/app/build.gradle, or npx react-native-integrate react-native-config to apply the extra steps automatically.

How do I set up react-native-config on Android?

Add the line apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" as the second line of android/app/build.gradle. If BuildConfig lives outside both the namespace and the applicationId, set resValue "string", "build_config_package", "YOUR_NAMESPACE" in defaultConfig. If the config arrives in JavaScript as {}, check logcat for ReactConfig: Could not find BuildConfig class.

What is react-native-config used for?

It exposes variables from a .env file at the root of a React Native app to JavaScript, so code reads Config.API_URL instead of hardcoding values. The README describes it as bringing twelve-factor config to mobile apps, and it supports iOS, Android, macOS and Windows.

How do I use react-native-config in JavaScript?

Import the default export and read properties off it: import Config from "react-native-config", then Config.API_URL. The property names match the keys in your .env file, and the values are read at build time rather than at runtime.

react-native-config vs dotenv: what is the difference?

react-native-dotenv is a Babel transform that inlines .env values into the JavaScript bundle, so it needs no native module or pod install but the values are unavailable to native build tooling. react-native-config ships a native module, which is why it requires the Android dotenv.gradle line and a pod install, and why native code can read the same values.

Official sources

  1. Issues
  2. License: MIT
  3. react-native-config/react-native-config on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/react-native-config-react-native-config.svg)](https://hysenlabs.com/projects/react-native-config-react-native-config)