Universal App Configuration

Configure your universal app's appearance, behavior, and security settings through config/config.json.


App Name

Set the display name that appears in device launchers, app stores, and system settings.

Configuration

{
"WEBVIEW_CONFIG": {
"android": {
"appName": "My Awesome App"
},
"ios": {
"appName": "My Awesome App"
}
}
}

Platform-Specific Names

{
"WEBVIEW_CONFIG": {
"android": {
"appName": "MyApp for Android"
},
"ios": {
"appName": "MyApp for iOS"
}
}
}

App Icon

Customize app icons for both Android and iOS platforms.

Android Icons

Place density-specific icons in public/android/appIcons/:

DensityFilenameSize (px)
mdpiicon-mdpi.png48 x 48
hdpiicon-hdpi.png72 x 72
xhdpiicon-xhdpi.png96 x 96
xxhdpiicon-xxhdpi.png144 x 144
xxxhdpiicon-xxxhdpi.png192 x 192

Supported formats: PNG, JPG, JPEG

Behavior:

  • Automatically applied during build
  • Missing densities use nearest available resource
  • Falls back to default Catalyst icon if none provided

iOS Icons

Place icons in public/ios/appIcons/ following the pattern: icon-{size}-{scale}.{ext}

FilenameSize (px)Purpose
icon-20x20-2x.png40×40iPhone Notification
icon-20x20-3x.png60×60iPhone Notification
icon-29x29-2x.png58×58iPhone Settings
icon-29x29-3x.png87×87iPhone Settings
icon-40x40-2x.png80×80iPhone Spotlight
icon-40x40-3x.png120×120iPhone Spotlight
icon-60x60-2x.png120×120iPhone App
icon-60x60-3x.png180×180iPhone App
icon-1024x1024-1x.png1024×1024App Store

Supported formats: PNG, JPG, JPEG

File Structure

your-project/
├── public/
│ ├── android/appIcons/
│ │ ├── icon-mdpi.png
│ │ ├── icon-hdpi.png
│ │ ├── icon-xhdpi.png
│ │ ├── icon-xxhdpi.png
│ │ └── icon-xxxhdpi.png
│ └── ios/appIcons/
│ ├── icon-20x20-2x.png
│ ├── icon-20x20-3x.png
│ ├── icon-29x29-2x.png
│ ├── icon-29x29-3x.png
│ ├── icon-40x40-2x.png
│ ├── icon-40x40-3x.png
│ ├── icon-60x60-2x.png
│ ├── icon-60x60-3x.png
│ └── icon-1024x1024-1x.png

Splashscreen

Configure a custom splashscreen displayed during app startup.

Configuration

{
"WEBVIEW_CONFIG": {
"splashScreen": {
"duration": 2000,
"backgroundColor": "#ffffff",
"imageWidth": 120,
"imageHeight": 120,
"cornerRadius": 20
}
}
}

Options

PropertyTypeDefaultDescription
durationnumber1000Display time in milliseconds. Ignored when an HTML splash is used
minDurationnumber0Minimum time in milliseconds the HTML splash stays on screen
backgroundColorstring"#ffffff"Background color (hex)
imageWidthnumber120Image width in dp/px
imageHeightnumber120Image height in dp/px
cornerRadiusnumber20Corner radius (0 for square)

Custom Images

Android: Place image at public/android/splashscreen.{png|jpg|webp}

  • Supported: PNG, JPG, WebP
  • Fallback: App launcher icon

iOS: Place image at public/ios/splashscreen.{png|jpg|jpeg}

  • Recommended: PNG, 512x512px
  • File size: Under 1MB
  • Fallback: Progress bar with loader

HTML Splash

To show an animation while the app loads, add public/splashscreen.html. It goes at the root of public/, not in public/android or public/ios, and both platforms use the same file. It only takes effect when splashScreen is set in the config.

On launch the app shows the native splash image, then the HTML splash, and then the app once its first page has loaded. Set minDuration to keep the animation on screen for at least that many milliseconds, even when the page loads sooner. If the page takes longer than 10 seconds, the HTML splash is dismissed anyway. duration is ignored in this mode.

{
"WEBVIEW_CONFIG": {
"splashScreen": {
"backgroundColor": "#ffffff",
"minDuration": 1200
}
}
}

The file has a few rules:

  • Keep it to one self-contained file. Put CSS and JavaScript inline and embed images as data: URIs.
  • Paint your own opaque, full-screen background. The native image sits underneath.
  • Do not make network requests. Android blocks them.
  • The page has no access to the native bridge.
  • Prefer CSS transform and opacity animations. The splash runs while the app is loading, so heavy JavaScript competes with it.
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
html, body { margin: 0; height: 100%; background: #ffffff; }
body { display: flex; align-items: center; justify-content: center; }
.dot {
width: 48px; height: 48px; border-radius: 50%; background: #3b5bdb;
animation: pulse 1s ease-in-out infinite alternate;
}
@keyframes pulse {
from { transform: scale(0.6); opacity: 0.4; }
to { transform: scale(1); opacity: 1; }
}
</style>
</head>
<body>
<div class="dot"></div>
</body>
</html>

Delete the file to go back to the image-only splash.

Examples

Basic Splashscreen

{
"WEBVIEW_CONFIG": {
"splashScreen": {
"duration": 2000,
"backgroundColor": "#ffffff"
}
}
}

Circular Icon

{
"WEBVIEW_CONFIG": {
"splashScreen": {
"duration": 2000,
"backgroundColor": "#1a1a1a",
"imageWidth": 150,
"imageHeight": 150,
"cornerRadius": 75
}
}
}

Auto-Dismiss (iOS Only)

{
"WEBVIEW_CONFIG": {
"splashScreen": {
"backgroundColor": "#ffffff"
}
}
}

Omitting duration on iOS auto-dismisses when WebView loads.

Platform Differences

iOS:

  • Auto-dismiss when duration is omitted
  • Smooth fade-out animation

Android:

  • Theme support (adapts to light/dark mode)

Best Practices

App Load TimeRecommendation
< 1 secondAuto-dismiss (iOS) or 1000ms
1-3 seconds2000-3000ms
> 3 secondsAuto-dismiss (iOS) or 3000ms

Performance Profiler

Enable the Catalyst Profiler for a debug build:

{
"WEBVIEW_CONFIG": {
"profiler": {
"enabled": true
}
}
}

Use Performance Profiling for the Android Chrome DevTools workflow, iOS trace export, captured signals, and the window.CatalystPerf API.

The profiler is disabled by default and only runs in debug builds. Rebuild the native app after changing the setting.


Edge-to-Edge

Let the WebView draw behind the status bar and navigation bar.

{
"WEBVIEW_CONFIG": {
"edgeToEdge": {
"enabled": true,
"statusBarStyle": "auto"
}
}
}

Options

PropertyTypeDefaultDescription
enabledbooleanfalseDraw page content behind the system bars on Android and iOS
statusBarStylestring"auto"System bar icon colour. Android only for now

statusBarStyle accepts these values:

  • auto follows the system light or dark theme.
  • dark-content uses dark icons, for light pages.
  • light-content uses light icons, for dark pages.

When edge-to-edge is enabled, the app is responsible for keeping content clear of the system bars. Read the insets with useSafeArea() and apply them as padding. The values are in CSS pixels on both platforms. On Android they also update when the insets change, for example when the user switches navigation mode. When edge-to-edge is disabled, the insets are 0.

On Android 10 (API 29) and later the system bars are fully transparent. Below API 29 the navigation bar keeps a translucent scrim.


Whitelisting

Control network access and navigation through URL whitelisting.

Configuration

{
"WEBVIEW_CONFIG": {
"accessControl": {
"enabled": true,
"allowedUrls": [
"https://api.example.com/*",
"*.example.com",
"https://cdn.example.com/assets/*"
]
}
}
}

Options

PropertyTypeDefaultDescription
enabledbooleanfalseEnable URL whitelisting
allowedUrlsstring[][]Permitted URL patterns

Behavior:

  • enabled: true - Only whitelisted URLs accessible (default deny)
  • enabled: false - All URLs accessible (no restrictions)

URL Patterns

Exact Match

{
"allowedUrls": [
"https://api.example.com/users",
"https://cdn.example.com/logo.png"
]
}

Wildcard Match

{
"allowedUrls": [
"https://api.example.com/*",
"https://*.example.com/api/*"
]
}

Subdomain Match

{
"allowedUrls": [
"*.example.com",
"*.cdn.example.com"
]
}

Examples

API Endpoints

{
"accessControl": {
"enabled": true,
"allowedUrls": [
"https://api.myapp.com/auth/*",
"https://api.myapp.com/users/*",
"https://api.myapp.com/data/*"
]
}
}

CDN Resources

{
"accessControl": {
"enabled": true,
"allowedUrls": [
"https://cdn.jsdelivr.net/*",
"*.cloudfront.net"
]
}
}

Third-Party Services

{
"accessControl": {
"enabled": true,
"allowedUrls": [
"https://maps.googleapis.com/*",
"https://api.stripe.com/*",
"*.analytics.google.com"
]
}
}

How It Works

  1. All network requests blocked by default when enabled
  2. External links open in system browser
  3. URLs matched against patterns in order
  4. First matching pattern allows the request
  5. No match = request blocked

Security Benefits

  • Default deny - Secure baseline blocks all unknown requests
  • Explicit allow - Only whitelisted URLs accessible
  • Navigation control - External links handled by system browser

Protocol Configuration

Control whether the webview uses HTTP or HTTPS protocol.

Configuration

{
"WEBVIEW_CONFIG": {
"useHttps": true
}
}
PropertyTypeDefaultDescription
useHttpsbooleanfalseUse HTTPS protocol

Behavior:

  • true - Uses HTTPS protocol
  • false - Uses HTTP protocol

Example: Development vs Production

{
"WEBVIEW_CONFIG": {
"useHttps": false, // HTTP for local development
"accessControl": {
"enabled": false
}
}
}
{
"WEBVIEW_CONFIG": {
"useHttps": true, // HTTPS for production
"accessControl": {
"enabled": true,
"allowedUrls": ["https://api.myapp.com/*"]
}
}
}

Complete Configuration Example

config/config.json
{
"WEBVIEW_CONFIG": {
"port": "3005",
"LOCAL_IP": "192.168.XX.XX",
"appInfo": "android-v2.1.0",
"useHttps": true,
"profiler": {
"enabled": false
},
"android": {
"appName": "My Awesome App",
"packageName": "com.example.myawesomeapp",
"buildType": "debug",
"sdkPath": "/Users/yourname/Library/Android/sdk",
"emulatorName": "Pixel_5_API_30",
"cachePattern": "*.css,*.js"
},
"ios": {
"appName": "My Awesome App",
"appBundleId": "com.example.myawesomeapp",
"buildType": "Debug",
"simulatorName": "iPhone 17 Pro",
"cachePattern": "*.css,*.js"
},
"accessControl": {
"enabled": true,
"allowedUrls": [
"https://api.myapp.com/*",
"https://cdn.myapp.com/*",
"*.cloudfront.net"
]
},
"splashScreen": {
"duration": 2000,
"minDuration": 0,
"backgroundColor": "#ffffff",
"imageWidth": 120,
"imageHeight": 120,
"cornerRadius": 20
},
"notifications": {
"enabled": true
}
}
}

Configuration Tips

  1. App Names - Keep under 30 characters for best display
  2. Icons - Provide all required sizes for professional appearance
  3. Splashscreen - Match duration to actual load time
  4. Whitelisting - Start with minimal URLs, add as needed
  5. Protocol - Always use HTTPS in production
  6. Testing - Test configuration on both platforms before release
  7. iOS Build Type - Use Debug or Release with exact casing when you add WEBVIEW_CONFIG.ios.buildType

See Also