Configuring your Universal App
import { appConfig } from '@app/config'
- appConfig.ts
This doc will cover the basic of configuring your app:
- App Context Flags
- Environment Variables
- Managing Dependencies
- Mobile App specific config
- Web / next.js specific config
App Context Flags
A good reason to use @app/config
is for context flags.
Your universal app can run in different environments like iOS, a web browser, Android, the server, etc.
Sometimes you want to debug, test or show something only in a specific environment.
For example:
import { appConfig } from '@app/config'
// Platform flags
if (appConfig.isWeb) console.log('Running in the browser')
if (appConfig.isMobile) console.log('Running on a mobile device')
// Runtime flags
if (appConfig.isServer) console.log('Running on the server')
// Framework flags
if (appConfig.isExpo) console.log('Running app with Expo')
if (appConfig.isNext) console.log('Running app with Next.js')
// Debug flags
if (appConfig.isExpoWebLocal) console.log('Running locally on web with Expo')
if (appConfig.isNextWebLocal) console.log('Running locally on web with Next.js')
Managing environment variables
Local env vars
- .env.example
- .env.local ←
- .env.example
- .env.local ←
Local environment variables can be managed in each app’s .env.local
file.
The .env.example
files can be copied into .env.local
using the following command:
npm run env:local
- Use
NEXT_PUBLIC_
to expose your environment variable in your next.js front-end - Use
EXPO_PUBLIC_
to expose your environment variable in your expo front-end
We suggest that for each environment variable you add in these .env.local
files, you also add an entry in appConfig.ts
. For example:
export const appConfig = {
// ...
// - Secrets -
// Don't use NEXT_PUBLIC_ / EXPO_PUBLIC_ prefixes here to make sure these are undefined client-side
appSecret: process.env.APP_SECRET,
// ...
}
Env vars in Next.js
For development, staging & production environments, check the next.js docs:
https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
Note that you should treat environment variables as if they could be inlined in your bundle during builds & deployments This means dynamically retrieving environment variables from e.g.
process.env[someKey]
might not work It also means that you should never prefix withNEXT_PUBLIC_
for sensitive / private keys
Managing secrets
App secrets that should only be available server-side should:
- not be prefixed with
NEXT_PUBLIC_
(this omits then from the client-side) - not be included in Expo’s
.env.local
file (all expo env vars are public and included in bundle by default)
Env vars in Expo
For development, staging & production environments, check the expo docs:
https://docs.expo.dev/guides/environment-variables/
Note that Expo will inline environment variables in your bundle during builds & deployments This means dynamically retrieving environment variables from e.g.
process.env[someKey]
will not work It also means that you should never include sensitive / private keys
Defining endpoints
Your most important environment variables are likely your API endpoints:
## --- General --------------------------------------------------------------------------------- */
## -i- Env vars that should always be present & the same locally, independent of the simulated environment
## --------------------------------------------------------------------------------------------- */
NEXT_PUBLIC_BASE_URL=http://localhost:3000
NEXT_PUBLIC_BACKEND_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:3000/api
NEXT_PUBLIC_GRAPH_URL=http://localhost:3000/api/graphql
Which you can then consolidate in your
appConfig.ts
export const appConfig = {
// ...
// - Server URLs -
baseURL: process.env.NEXT_PUBLIC_BASE_URL || process.env.EXPO_PUBLIC_BASE_URL,
backendURL: process.env.NEXT_PUBLIC_BACKEND_URL || process.env.EXPO_PUBLIC_BACKEND_URL,
apiURL: process.env.NEXT_PUBLIC_API_URL || process.env.EXPO_PUBLIC_API_URL,
graphURL: process.env.NEXT_PUBLIC_GRAPH_URL || process.env.EXPO_PUBLIC_GRAPH_URL,
// ...
}
For the examples above, we’ve already set these up for local use.
Feature and Domain config
- @app-core / package.json
- @some-feature / package.json ←
- @green-stack-core / package.json
- @some-domain / package.json ←
As stated in our project structure docs, workspaces should define their own package.json
file.
That means that each feature or package workspace can have its own dependencies.
This helps keep things modular, portable and colocated so features remain copy-pasteable.
Expo SDK compatible packages
For your Expo mobile app, it’s important to install packages that are compatible with your current Expo SDK.
However, using Expo’s own expo install
command will only install packages in the expo app workspace, which we don’t want.
To help with this, we’ve created a script that will install SDK compatible packages in the correct workspace:
npm run add:dependencies
This will ask you where you’d like to install the package:
>>> Modify "your-project-name" using custom generators
? Which workspace should we install the Expo SDK compatible versions in? (Use arrow keys)
@db/driver
❯ @green-stack/core
@app/registries
@app/core
You can then specify one or multiple packages to have their SDK compatible versions installed.
Managing Expo config
Check the Expo docs for configuring your mobile app with Expo:
- app.json ←
- babel.config.js
- metro.config.js
- package.json
- tsconfig.json
Managing Next.js config
Check the Next.js docs for configuring your web app with Next.js:
- https://nextjs.org/docs/app/building-your-application/configuring
- https://nextjs.org/docs/app/api-reference/next-config-js
- babel.config.js
- next.config.base.cjs ←
- next.config.js
- package.json
- tsconfig.json