# Expo

## Prerequisites

Create an [Expo app](https://docs.expo.dev/get-started/create-a-project/).

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**

```console
$ npm install @dotenvx/dotenvx
```

**pnpm**

```console
$ pnpm add @dotenvx/dotenvx
```

## Encrypt

Start with a demonstration value in the .env file at your project root:

```dotenv
# .env
EXPO_PUBLIC_HELLO="Secret"
```

Encrypt it with a single command.

**npm**

```console
$ npx dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
```

**pnpm**

```console
$ pnpm exec dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
```

The values become ciphertext and only your private key can unlock them.

```dotenv
# .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.

```console
$ git add .env
$ git commit -m "encrypt .env"
```

## Ship

Read the value in a screen. For example, replace your Expo Router home screen with:

```tsx
// 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:

**package.json**

```json
{
  "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**

```console
$ npm start
⟐ injected env (3) from .env (022 0D8) via .env.keys
```

**pnpm**

```console
$ 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 →](https://dotenvx.com/docs/expo/build-secrets.md)

## Share

Have teammates? Share access with Dotenvx Armor ⛨

Log in to Dotenvx.

**npm**

```console
$ npx dotenvx login
◉ logged in (username)
```

**pnpm**

```console
$ pnpm exec dotenvx login
◉ logged in (username)
```

Create the Armored Key ⛨

**npm**

```console
$ npx dotenvx armor up
⛨ armored .env (022 0D8)
```

**pnpm**

```console
$ pnpm exec dotenvx armor up
⛨ armored .env (022 0D8)
```

Invite your teammate.

**npm**

```console
$ npx dotenvx armor invite
⛨ invited person@example.com to team
```

**pnpm**

```console
$ pnpm exec dotenvx armor invite
⛨ invited person@example.com 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**

```console
$ npm start
⟐ injected env (3) from .env (022 0D8) via Armor ⛨
```

**pnpm**

```console
$ pnpm start
⟐ injected env (3) from .env (022 0D8) via Armor ⛨
```

Open the app to see Hello Secret.

[**Share a private key** Alternative →](https://dotenvx.com/docs/expo/share-private-key.md)

## Production

Create a .env.production file:

```dotenv
# .env.production
EXPO_PUBLIC_HELLO="Production"
```

Encrypt it:

**npm**

```console
$ npx dotenvx encrypt -f .env.production
```

**pnpm**

```console
$ 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:

```console
$ git add -f .env.production
$ git commit -m "encrypt .env.production"
```

Export the production bundle:

**npm**

```console
$ npm run export
```

**pnpm**

```console
$ 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.

[**EAS Build** Alternative →](https://dotenvx.com/docs/expo/eas-build.md)

[**EAS Update** Alternative →](https://dotenvx.com/docs/expo/eas-update.md)

## 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.
