Expo
Prerequisites
Create an Expo app.
Expo bundles EXPO_PUBLIC_ values into your app. Encryption protects your .env files in git; it does not make shipped app values private. Keep real secrets on your backend or in build tooling.
Install
Install Dotenvx in your Expo project:
$ npm install @dotenvx/dotenvx
$ pnpm add @dotenvx/dotenvx
Encrypt
Start with a demonstration value in the .env file at your project root:
# .env
EXPO_PUBLIC_HELLO="Secret"
Encrypt it with a single command.
$ npx dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
$ pnpm exec dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
The values become ciphertext and only your private key can unlock them.
# .env
DOTENV_PUBLIC_KEY="0220d830351410598be484f43a7b07097e09851f50426832876e8b5815a1752990"
EXPO_PUBLIC_HELLO="encrypted:BHLTACNJMr00nTG6yXpkCyWFKF/MY0ajN855tg3uVtKopTe2AGzSkQlcPd21pTOT3Ci8IKrdIg2TMZFoq1mDR6yb06QCRvqHXtpkZkAHYCEHfeWqqC8tMFovcYq5JS2uZSrC/qUGDA=="
Commit
Commit your encrypted .env files with your code. It's safe. Now you can securely share secrets through git.
$ git add .env
$ git commit -m "encrypt .env"
Ship
Read the value in a screen. For example, replace your Expo Router home screen with:
// app/index.tsx (or your existing home route)
import { Text, View } from 'react-native';
export default function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Hello {process.env.EXPO_PUBLIC_HELLO}</Text>
</View>
);
}
Use the full process.env.EXPO_PUBLIC_HELLO reference so Expo can inline it. Do not destructure process.env or use bracket notation.
Update these scripts in package.json, keeping your other scripts:
{
"scripts": {
"start": "dotenvx run -e EXPO_NO_DOTENV=1 -f .env --strict -- expo start",
"android": "dotenvx run -e EXPO_NO_DOTENV=1 -f .env --strict -- expo start --android",
"ios": "dotenvx run -e EXPO_NO_DOTENV=1 -f .env --strict -- expo start --ios",
"web": "dotenvx run -e EXPO_NO_DOTENV=1 -f .env --strict -- expo start --web",
"export": "dotenvx run -e EXPO_NO_DOTENV=1 -f .env.production --strict -- expo export"
}
}
The -e flag sets EXPO_NO_DOTENV to disable Expo's own .env loader. Dotenvx loads and decrypts the selected file before Expo starts.
Run your app:
$ npm start
⟐ injected env (3) from .env (022 0D8) via .env.keys
$ pnpm start
⟐ injected env (3) from .env (022 0D8) via .env.keys
Open the app in Expo Go or your development build to see Hello Secret. Restart the command and reload the app after changing .env.
Build-only secrets Alternative →
Share
Have teammates? Share access with Dotenvx Armor ⛨
Log in to Dotenvx.
$ npx dotenvx login
◉ logged in (username)
$ pnpm exec dotenvx login
◉ logged in (username)
Create the Armored Key ⛨
$ npx dotenvx armor up
⛨ armored .env (022 0D8)
$ pnpm exec dotenvx armor up
⛨ armored .env (022 0D8)
Invite your teammate.
$ npx dotenvx armor invite
⛨ invited [email protected] to team
$ pnpm exec dotenvx armor invite
⛨ invited [email protected] to team
Your teammate accepts the invitation, pulls the repository, installs dependencies, and logs in with dotenvx login. They can then run the app:
$ npm start
⟐ injected env (3) from .env (022 0D8) via Armor ⛨
$ pnpm start
⟐ injected env (3) from .env (022 0D8) via Armor ⛨
Open the app to see Hello Secret.
Share a private key Alternative →
Production
Create a .env.production file:
# .env.production
EXPO_PUBLIC_HELLO="Production"
Encrypt it:
$ npx dotenvx encrypt -f .env.production
$ pnpm exec dotenvx encrypt -f .env.production
For a local export, choose Local when prompted and store the key in .env.keys. Keep .env.keys out of git.
Commit the encrypted file:
$ git add -f .env.production
$ git commit -m "encrypt .env.production"
Export the production bundle:
$ npm run export
$ pnpm export
Dotenvx decrypts .env.production on the build machine. Expo embeds the public value in the output under dist. The app does not need Dotenvx or a private key on the device.
This creates bundles, not an installable native app. Continue with EAS Build for a native build or EAS Update for an update to a compatible installed app.
Conclusion
You've encrypted your configuration, shared access with Armor, and loaded production values before Expo bundles your app. Your encrypted files travel with your code; private keys stay on development and build machines.