Configuration API
Catalyst reads runtime and build configuration from config/config.json. This page covers the contract that the framework expects. For a guided walkthrough, see Configuration.
Top-Level Configuration
These keys are part of the core web runtime:
| Key | Type | Required | Purpose |
|---|---|---|---|
NODE_SERVER_HOSTNAME | string | Yes | Hostname for the Node SSR server |
NODE_SERVER_PORT | number | Yes | Port for the Node SSR server |
BUILD_OUTPUT_PATH | string | Yes | Output directory for production assets |
PUBLIC_STATIC_ASSET_PATH | string | Yes | Public mount path for static assets |
PUBLIC_STATIC_ASSET_URL | string | Yes | Base URL for emitted static assets |
CLIENT_ENV_VARIABLES | string[] | Yes | Variables that should be exposed to the client bundle |
Application-specific values such as API_URL can also live in this file. They are available on the server through process.env.
Client-Exposed Environment Variables
Catalyst does not expose every config key to browser code automatically. Add the keys you want available on the client to CLIENT_ENV_VARIABLES.
{"API_URL": "https://api.example.com","ANALYTICS_ID": "UA-123456","DATABASE_URL": "postgresql://internal-db","CLIENT_ENV_VARIABLES": ["API_URL", "ANALYTICS_ID"]}
In this example:
process.env.API_URLis available on both server and client.process.env.ANALYTICS_IDis available on both server and client.process.env.DATABASE_URLstays server-only.
Keep this list small. Any key included here becomes visible in the client bundle.
WEBVIEW_CONFIG
Universal app settings live under WEBVIEW_CONFIG inside the same file.
{"WEBVIEW_CONFIG": {"port": "3005","LOCAL_IP": "192.168.XX.XX","appInfo": "android-5Feb2026-v2.1.0","useHttps": false,"profiler": {"enabled": false},"android": {"appName": "My App","packageName": "com.example.myapp","buildType": "debug","sdkPath": "/Users/yourname/Library/Android/sdk","emulatorName": "Pixel_5_API_30"},"ios": {"appName": "My App","appBundleId": "com.example.myapp","buildType": "Debug","simulatorName": "iPhone 17 Pro"},"accessControl": {"enabled": true,"allowedUrls": ["*.yourdomain.com*","http://localhost:*"]},"splashScreen": {"duration": 2000,"minDuration": 0,"backgroundColor": "#ffffff","imageWidth": 400,"imageHeight": 200,"cornerRadius": 20}}}
Required Universal App Fields
Shared fields
| Key | Required | Notes |
|---|---|---|
WEBVIEW_CONFIG.port | Yes | Port the native WebView should load |
WEBVIEW_CONFIG.LOCAL_IP | Yes | Use your LAN IP, not localhost |
WEBVIEW_CONFIG.appInfo | Yes | Build identifier used by native tooling |
WEBVIEW_CONFIG.useHttps | No | Defaults to false |
WEBVIEW_CONFIG.profiler.enabled | No | Enables the debug-only Catalyst Profiler; defaults to false |
Android fields
| Key | Required | Notes |
|---|---|---|
WEBVIEW_CONFIG.android.sdkPath | Yes | Absolute path to the Android SDK |
WEBVIEW_CONFIG.android.emulatorName | Yes for debug | Required for emulator-based debug builds |
WEBVIEW_CONFIG.android.buildType | No | debug or release |
WEBVIEW_CONFIG.android.keystoreConfig | Yes for release | Needed to sign release output |
WEBVIEW_CONFIG.android.buildOptimisation | No | Enables Android build optimisation |
iOS fields
| Key | Required | Notes |
|---|---|---|
WEBVIEW_CONFIG.ios.appBundleId | Required for distribution | Set this explicitly for release builds |
WEBVIEW_CONFIG.ios.buildType | No | Must be Debug or Release, case-sensitive |
WEBVIEW_CONFIG.ios.simulatorName | No | Used for simulator builds |
WEBVIEW_CONFIG.ios.deviceUDID | No | For physical device builds |
WEBVIEW_CONFIG.ios.developmentTeam | Required with deviceUDID | Apple team ID for signing |
WEBVIEW_CONFIG.ios.cachePattern | No | Array of glob-style URL patterns (e.g. ["*.css", "*.js"]) the native WebView cache should match — a single string is treated as one literal pattern, not comma-split; when unset, no pattern-based caching is enabled (offline-route caching can still apply) |
Access Control
Use WEBVIEW_CONFIG.accessControl to whitelist outbound URLs used by the WebView and native request flows.
{"WEBVIEW_CONFIG": {"accessControl": {"enabled": true,"allowedUrls": ["*.yourdomain.com*","https://api.example.com/*","http://localhost:*"]}}}
If you enable access control, make sure every required API, CDN, and localhost URL is included.
Splash Screen
The splash screen configuration belongs inside WEBVIEW_CONFIG.splashScreen, not at the top level of config.json.
| Key | Type | Notes |
|---|---|---|
backgroundColor | string | Defaults to white |
duration | number | Primarily relevant on iOS. Ignored when public/splashscreen.html exists |
minDuration | number | Minimum time in ms the HTML splash stays on screen. Defaults to 0 |
imageWidth | number | Width of the splash asset |
imageHeight | number | Height of the splash asset |
cornerRadius | number | iOS rounded corners |
Place splash assets at:
public/android/splashscreen.{png|jpg|jpeg|gif|bmp|webp}public/ios/splashscreen.{png|jpg|jpeg}public/splashscreen.html(optional, shared by both platforms)
When splashScreen is set and public/splashscreen.html exists, the app shows the native image first, then the HTML splash, and switches to the app once its first page has loaded and minDuration has passed. The HTML splash is dismissed after 10 seconds even if the page is still loading. The file must be self-contained, with inline CSS and JavaScript and images as data: URIs. It has no access to the native bridge and should not make network requests, which Android blocks. Remove the file to go back to the image-only splash. See Universal App Configuration for the full rules and an example.
Validation Notes
- Missing required top-level config keys cause startup failures.
- Using
CLIENT_ENV_KEYSis outdated. The current key isCLIENT_ENV_VARIABLES. - iOS build types are case-sensitive: use
DebugorRelease. LOCAL_IPshould be a reachable LAN IP for emulator or device builds.WEBPACK_DEV_SERVER_HOSTNAME,WEBPACK_DEV_SERVER_PORT, andANALYZE_BUNDLEare no longer required or read, so you can delete them or leave them in place.