> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobile-starter.amisi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Variables

> Configure environment variables and secrets for different environments

# Environment Variables

Configure environment variables to manage API keys, endpoints, and environment-specific settings.

## Understanding Environment Variables

The starter uses `EXPO_PUBLIC_` prefixed environment variables that are:

* Validated with Zod schemas
* Available at build time and runtime
* Environment-specific (development, preview, production)

## Environment Variable Schema

All environment variables are defined in `packages/config/src/env.ts`:

```typescript theme={null}
const envSchema = z.object({
  EXPO_PUBLIC_API_URL: z.string().url().default('https://api.example.com'),
  EXPO_PUBLIC_APP_ENV: z
    .enum(['development', 'preview', 'production'])
    .default('development'),
  EXPO_PUBLIC_FIREBASE_API_KEY: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_PROJECT_ID: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_APP_ID: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_EMAIL_CONTINUE_URL: z.string().optional(),
  EXPO_PUBLIC_FIREBASE_AUTH_LINK_DOMAIN: z.string().optional(),
  EXPO_PUBLIC_REVENUECAT_API_KEY: z.string().optional(),
  EXPO_PUBLIC_REVENUECAT_IOS_API_KEY: z.string().optional(),
  EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY: z.string().optional(),
  EXPO_PUBLIC_SENTRY_DSN: z.string().optional(),
  EXPO_PUBLIC_ANALYTICS_ENABLED: z
    .string()
    .transform((val) => val === 'true')
    .default('true'),
  EXPO_PUBLIC_DEBUG_MODE: z
    .string()
    .transform((val) => val === 'true')
    .default('false'),
});
```

## Local Development Setup

### 1. Create .env File

Create a `.env` file in the repository root:

```bash theme={null}
# DO NOT COMMIT THIS FILE
# Add .env to .gitignore

# Environment
EXPO_PUBLIC_APP_ENV=development

# API Configuration
EXPO_PUBLIC_API_URL=http://localhost:3000

# Firebase Configuration (if using Firebase adapter)
EXPO_PUBLIC_FIREBASE_API_KEY=your-api-key
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
EXPO_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
EXPO_PUBLIC_FIREBASE_APP_ID=your-app-id
EXPO_PUBLIC_FIREBASE_EMAIL_CONTINUE_URL=https://amisi-mobile-starter.web.app/verify-email
EXPO_PUBLIC_FIREBASE_AUTH_LINK_DOMAIN=amisi-mobile-starter.web.app

# RevenueCat Configuration (if using RevenueCat adapter)
EXPO_PUBLIC_REVENUECAT_API_KEY=your-universal-key
# OR platform-specific keys:
# EXPO_PUBLIC_REVENUECAT_IOS_API_KEY=your-ios-key
# EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY=your-android-key

# Optional: Sentry
EXPO_PUBLIC_SENTRY_DSN=your-sentry-dsn

# Feature Toggles
EXPO_PUBLIC_ANALYTICS_ENABLED=true
EXPO_PUBLIC_DEBUG_MODE=true
```

### 2. Add to .gitignore

Ensure `.env` is in `.gitignore`:

```
# Environment variables
.env
.env.local
.env.*.local
```

### 3. Restart Development Server

After creating or modifying `.env`:

```bash theme={null}
bun run start:clear
```

## Environment-Specific Configuration

### Development Environment

For local development:

```bash theme={null}
EXPO_PUBLIC_APP_ENV=development
EXPO_PUBLIC_API_URL=http://localhost:3000
EXPO_PUBLIC_DEBUG_MODE=true
```

### Preview Environment

For testing builds:

```bash theme={null}
EXPO_PUBLIC_APP_ENV=preview
EXPO_PUBLIC_API_URL=https://preview-api.example.com
EXPO_PUBLIC_DEBUG_MODE=true
EXPO_PUBLIC_ANALYTICS_ENABLED=true
```

### Production Environment

For production builds:

```bash theme={null}
EXPO_PUBLIC_APP_ENV=production
EXPO_PUBLIC_API_URL=https://api.example.com
EXPO_PUBLIC_DEBUG_MODE=false
EXPO_PUBLIC_ANALYTICS_ENABLED=true
```

## EAS Secrets (Recommended for Production)

For EAS builds, use EAS Secrets instead of committing sensitive values.

### Create Secrets

```bash theme={null}
# Firebase secrets
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_API_KEY --value "your-key"
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN --value "your-domain"
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_PROJECT_ID --value "your-id"
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET --value "your-bucket"
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID --value "your-sender-id"
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_APP_ID --value "your-app-id"

# RevenueCat secrets
eas secret:create --scope project --name EXPO_PUBLIC_REVENUECAT_API_KEY --value "your-key"

# API URL (environment-specific)
eas secret:create --scope project --name EXPO_PUBLIC_API_URL --value "https://api.example.com"
```

### List Secrets

```bash theme={null}
eas secret:list
```

### Delete Secrets

```bash theme={null}
eas secret:delete --name EXPO_PUBLIC_FIREBASE_API_KEY
```

## Build Profile Environment Variables

You can also set environment variables in `eas.json` for each build profile:

```json theme={null}
{
  "build": {
    "production": {
      "env": {
        "APP_ENV": "production",
        "EXPO_PUBLIC_API_URL": "https://api.example.com"
      }
    },
    "preview": {
      "env": {
        "APP_ENV": "preview",
        "EXPO_PUBLIC_API_URL": "https://preview-api.example.com"
      }
    },
    "development": {
      "env": {
        "APP_ENV": "development"
      }
    }
  }
}
```

**Note**: EAS Secrets take precedence over `eas.json` env values.

## Accessing Environment Variables

### In Code

Import from `@amisi/config`:

```typescript theme={null}
import { env, getApiUrl, isDevelopment } from '@amisi/config';

// Direct access
const apiUrl = env.EXPO_PUBLIC_API_URL;
const firebaseKey = env.EXPO_PUBLIC_FIREBASE_API_KEY;

// Helper functions
const url = getApiUrl();
const isDev = isDevelopment();
```

### Available Helpers

```typescript theme={null}
// Environment checks
isDevelopment(): boolean
isPreview(): boolean
isProduction(): boolean

// Configuration getters
getApiUrl(): string
isDebugMode(): boolean
isAnalyticsEnabled(): boolean
```

## Required Variables by Adapter

### Firebase Adapter

Required when using `auth.adapter: "firebase"`:

```bash theme={null}
EXPO_PUBLIC_FIREBASE_API_KEY=required
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=required
EXPO_PUBLIC_FIREBASE_PROJECT_ID=required
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=required
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=required
EXPO_PUBLIC_FIREBASE_APP_ID=required
EXPO_PUBLIC_FIREBASE_EMAIL_CONTINUE_URL=recommended for verify email deep links
EXPO_PUBLIC_FIREBASE_AUTH_LINK_DOMAIN=recommended for firebase auth link domain
```

### RevenueCat Adapter

Required when using `subscriptions.adapter: "revenuecat"`:

```bash theme={null}
# Option 1: Universal key
EXPO_PUBLIC_REVENUECAT_API_KEY=required

# Option 2: Platform-specific keys
EXPO_PUBLIC_REVENUECAT_IOS_API_KEY=required
EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY=required
```

### Mock Adapters

No environment variables required when using mock adapters.

## Validation

Environment variables are validated on app startup using Zod schemas.

### Validation Errors

If validation fails, you'll see detailed error messages:

```
❌ Invalid environment variables:
  - EXPO_PUBLIC_API_URL: Invalid url
  - EXPO_PUBLIC_FIREBASE_API_KEY: Required
```

### Adding New Variables

To add a new environment variable:

1. **Update schema** in `packages/config/src/env.ts`:

```typescript theme={null}
const envSchema = z.object({
  // ... existing variables
  EXPO_PUBLIC_MY_NEW_VAR: z.string().optional(),
});
```

2. **Update TypeScript types** (automatic from Zod):

```typescript theme={null}
export type Env = z.infer<typeof envSchema>;
```

3. **Add to .env**:

```bash theme={null}
EXPO_PUBLIC_MY_NEW_VAR=my-value
```

4. **Access in code**:

```typescript theme={null}
import { env } from '@amisi/config';
const myVar = env.EXPO_PUBLIC_MY_NEW_VAR;
```

## Security Best Practices

### 1. Never Commit Secrets

* Add `.env` to `.gitignore`
* Use EAS Secrets for sensitive values
* Use `.env.example` for documentation

### 2. Use EAS Secrets for Production

```bash theme={null}
# Good: Use EAS Secrets
eas secret:create --scope project --name EXPO_PUBLIC_FIREBASE_API_KEY --value "key"

# Bad: Hardcode in eas.json
{
  "env": {
    "EXPO_PUBLIC_FIREBASE_API_KEY": "hardcoded-key"
  }
}
```

### 3. Restrict API Keys

* Use Firebase API key restrictions
* Use RevenueCat environment-specific keys
* Rotate keys regularly

### 4. Environment Separation

* Use different Firebase projects for dev/prod
* Use different RevenueCat projects for dev/prod
* Never use production keys in development

## Example .env.example

Create `.env.example` for documentation:

```bash theme={null}
# Environment Configuration Example
# Copy this file to .env and fill in your values

# Environment
EXPO_PUBLIC_APP_ENV=development

# API Configuration
EXPO_PUBLIC_API_URL=http://localhost:3000

# Firebase Configuration (optional - only if using Firebase adapter)
EXPO_PUBLIC_FIREBASE_API_KEY=
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=
EXPO_PUBLIC_FIREBASE_PROJECT_ID=
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
EXPO_PUBLIC_FIREBASE_APP_ID=
EXPO_PUBLIC_FIREBASE_EMAIL_CONTINUE_URL=https://amisi-mobile-starter.web.app/verify-email
EXPO_PUBLIC_FIREBASE_AUTH_LINK_DOMAIN=amisi-mobile-starter.web.app

# RevenueCat Configuration (optional - only if using RevenueCat adapter)
EXPO_PUBLIC_REVENUECAT_API_KEY=

# Feature Toggles
EXPO_PUBLIC_ANALYTICS_ENABLED=true
EXPO_PUBLIC_DEBUG_MODE=true
```

## Troubleshooting

### Variables Not Loading

**Solution**: Restart the development server:

```bash theme={null}
bun run start:clear
```

### Validation Errors

**Solution**: Check that all required variables are set and match the schema format.

### EAS Build Missing Variables

**Solution**: Ensure variables are either:

1. Set as EAS Secrets, OR
2. Defined in `eas.json` env block

### Variables Undefined at Runtime

**Solution**: Ensure variables have `EXPO_PUBLIC_` prefix for client-side access.

## Official Documentation

* [Expo Environment Variables](https://docs.expo.dev/guides/environment-variables/)
* [EAS Build Environment Variables](https://docs.expo.dev/build-reference/variables/)
* [EAS Secrets](https://docs.expo.dev/build-reference/variables/#using-secrets-in-environment-variables)

## Next Steps

* [Configure Adapters](/configuration/adapters)
* [Set Up Firebase](/configuration/firebase-setup)
* [Learn about Config Package](/packages/config)
