xref: /expo/docs/pages/workflow/configuration.mdx (revision 7c3fd962)
1---
2title: Configuration with app.json/app.config.js
3description: Learn about what is Expo config and how you can dynamically use it by customizing it.
4---
5
6import PossibleRedirectNotification from '~/components/plugins/PossibleRedirectNotification';
7import { Terminal } from '~/ui/components/Snippet';
8import { Collapsible } from '~/ui/components/Collapsible';
9
10<PossibleRedirectNotification newUrl="/versions/latest/config/app/" />
11
12The Expo config (**app.json**, **app.config.js**, **app.config.ts**) is used for configuring how a project loads in [Expo Go](/workflow/expo-go), [Expo Prebuild](/workflow/prebuild) generation, and the OTA update manifest. You can think of this as an `index.html` but for React Native apps.
13
14It must be located at the root of your project, next to the **package.json**. Here is a bare-minimum example:
15
16```json
17{
18  "expo": {
19    "name": "My app",
20    "slug": "my-app"
21  }
22}
23```
24
25Most configuration from the Expo config is accessible at runtime from the JavaScript code using [`Constants.expoConfig`](/versions/latest/sdk/constants/#nativeconstants--properties). Sensitive information such as secret keys are removed.
26
27## Properties
28
29The Expo config configures many things such as app name, icon, splash screen, deep linking scheme, API keys to use for some services and so on. For a complete list of available properties, see [app.json/app.config.js reference](/versions/latest/config/app/).
30
31> **info** Do you use Visual Studio Code? If so, we recommend that you install the [vscode-expo](https://marketplace.visualstudio.com/items?itemName=byCedric.vscode-expo) extension to get auto-completion of properties in **app.json** files.
32
33## Extending configuration
34
35Library authors can extend the Expo config by using [Expo Config plugins](/guides/config-plugins).
36
37> **info** Config plugins are mostly used to configure the [`npx expo prebuild`](/workflow/prebuild) command.
38
39## Dynamic configuration
40
41For more customization, you can use the JavaScript or [TypeScript](#using-typescript-for-configuration-appconfigts-instead-of) (**app.config.js**, or **app.config.ts**). These configs have the following properties:
42
43- Comments, variables, and single quotes.
44- Importing/requiring other JavaScript files. Using import/export syntax in external files is not supported. All imported files must be transpiled to support your current version of Node.js.
45- TypeScript support with nullish coalescing and optional chaining.
46- Updated whenever Metro bundler reloads.
47- Provide environment information to your app.
48- Does not support Promises.
49
50For example, you can export an object to define your custom config:
51
52```js app.config.js
53const myValue = 'My App';
54
55module.exports = {
56  name: myValue,
57  version: process.env.MY_CUSTOM_PROJECT_VERSION || '1.0.0',
58  // All values in extra will be passed to your app.
59  extra: {
60    fact: 'kittens are cool',
61  },
62};
63```
64
65The `"extra"` key allows passing arbitrary configuration data to your app. The value of this key is accessed using [`expo-constants`](/versions/latest/sdk/constants/):
66
67```js App.js
68import Constants from 'expo-constants';
69
70Constants.expoConfig.extra.fact === 'kittens are cool';
71```
72
73<Collapsible summary="Using SDK 45 or below?">
74
75The `extra` property is available on the `Constants.manifest` property.
76
77</Collapsible>
78
79You can access and modify incoming config values by exporting a function that returns an object. This is useful if your project also has an **app.json**. By default, Expo CLI will read the **app.json** first and send the normalized results to the **app.config.js**. This functionality is disabled when the `--config` is used to specify a custom config.
80
81> **warning** The `--config` flag is deprecated. For more information, see [Migration from `--config` in Expo CLI](https://expo.fyi/config-flag-migration).
82
83For example, your **app.json** could look like this:
84
85```json app.json
86{
87  "expo": {
88    "name": "My App"
89  }
90}
91```
92
93And in your **app.config.js**, you are provided with that configuration in the arguments to the exported function:
94
95```js app.config.js
96module.exports = ({ config }) => {
97  console.log(config.name); // prints 'My App'
98  return {
99    ...config,
100  };
101};
102```
103
104### Switching configuration based on the environment
105
106It's common to have some different configuration in development, staging, and production environments, or to swap out configuration entirely in order to white label an app. To accomplish this, you can use **app.config.js** along with environment variables.
107
108```js app.config.js
109module.exports = () => {
110  if (process.env.MY_ENVIRONMENT === 'production') {
111    return {
112      /* your production config */
113    };
114  } else {
115    return {
116      /* your development config */
117    };
118  }
119};
120```
121
122To use this configuration with Expo CLI commands, set the environment variable either for specific commands or in your shell profile. To set environment variables for specific commands, prefix the command with the variables and values as shown in the example:
123
124<Terminal cmd={['$ MY_ENVIRONMENT=production eas update']} />
125
126This is not anything unique to Expo CLI. On Windows you can approximate the above command with:
127
128<Terminal cmd={['$ npx cross-env MY_ENVIRONMENT=production eas update']} />
129
130Or you can use any other mechanism that you are comfortable with for environment variables.
131
132### Using TypeScript for configuration: app.config.ts instead of app.config.js
133
134You can use autocomplete and doc-blocks with an Expo config in TypeScript. Create an **app.config.ts** with the following contents:
135
136```ts app.config.ts
137import { ExpoConfig, ConfigContext } from 'expo/config';
138
139export default ({ config }: ConfigContext): ExpoConfig => ({
140  ...config,
141  slug: 'my-app',
142  name: 'My App',
143});
144```
145
146If you want to import other TypeScript files or customize the language features, we recommend using `ts-node` as described in [Using TypeScript](/guides/typescript#appconfigjs).
147
148### Configuration Resolution Rules
149
150There are two different types of configs: static (**app.config.json**, **app.json**), and dynamic (**app.config.js**, **app.config.ts**). Static configs can be automatically updated with CLI tools, whereas dynamic configs must be manually updated by the developer.
151
1521. The static config is read if **app.config.json** exists (falls back to **app.json**). If no static config exists, then default values are inferred from the **package.json** and your dependencies.
1532. The dynamic config is read if either **app.config.ts** or **app.config.js** exist. If both exist, then the TypeScript config is used.
1543. If the dynamic config returns a function, then the static config is passed to the function with `({ config }) => ({})`. This function can then mutate the static config values. Think of this like middleware for the static config.
1554. The return value from the dynamic config is used as the final config. It cannot have any promises.
1565. All functions in the config are evaluated and serialized before any tool in the Expo ecosystem uses it. The config must be a JSON manifest when it is hosted.
157