Developer Guide

App Store Assets

A complete guide to preparing app icons, splash screens, and other visual assets required for publishing your NativePress app to the Apple App Store and Google Play Store. Follow this guide to avoid asset-related rejections on your first submission.

Quick Guide
Replace 5 files, update 3 colors, done.
File Size What It Is
icon.png 1024 x 1024 App icon for both stores
adaptive-icon.png 1024 x 1024 Android adaptive icon foreground layer
splash-icon.png 288 x 288 Splash screen icon (light mode)
splash-icon-dark.png 288 x 288 Splash screen icon (dark mode)
favicon.png 48 x 48 Browser tab icon (web builds only)
1
Design
Create your icon at 1024x1024 and splash icon at 288x288
2
Drop in assets/
Replace all 5 files — names must match exactly, no code changes
3
Update app.json
Set your brand colors for splash background and adaptive icon background
iOS icon: No transparency allowed. Export icon.png as RGB with a solid background — Apple rejects any alpha channel.
Android adaptive icon: Keep your logo in the center 66% of the canvas (676x676 safe zone). Launchers crop the edges into circles, squircles, or rounded squares.
Detailed Reference

Everything above is all you need to get started. The sections below dive deeper into platform requirements, common pitfalls, and design best practices — worth reading before your first submission.

Complete Asset Inventory

Every file in the assets/ directory, with exact specifications for each store.

File Dimensions Format Required By Purpose
icon.png 1024 x 1024 PNG, RGB (no alpha) iOS + Android Master app icon. Expo and Xcode auto-generate all required sizes from this single file. Apple App Store Connect requires exactly 1024x1024.
adaptive-icon.png 1024 x 1024 PNG, RGBA (with alpha) Android only Foreground layer for Android adaptive icons. Transparent background required — the background color comes from app.json.
splash-icon.png 288 x 288 PNG, RGBA (with alpha) iOS + Android Splash screen icon for light mode. Displayed centered over the backgroundColor defined in the expo-splash-screen plugin config.
splash-icon-dark.png 288 x 288 PNG, RGBA (with alpha) iOS + Android Splash screen icon for dark mode. Displayed centered over the dark.backgroundColor. If your logo works on both backgrounds, you can reuse the same file.
favicon.png 48 x 48 PNG, RGB Web only Browser tab icon. Only needed if you ship an Expo Web build. Not required for iOS or Android store submissions.
RGB vs RGBA: RGB (no alpha channel) means the image has no transparency — every pixel has a solid color. RGBA (with alpha channel) supports transparent pixels. Apple requires the app icon to have no alpha channel; Android requires the adaptive icon foreground to have transparency so it can composite over the background layer.

iOS App Icon

Apple Human Interface Guidelines require a single 1024x1024 PNG with no transparency, no rounded corners, and no visual effects baked in.

Requirements

  • Exactly 1024 x 1024 pixels. App Store Connect rejects any other dimension.
  • No alpha channel (no transparency). Export as RGB, not RGBA. This is the single most common rejection reason.
  • No rounded corners. iOS applies its own superellipse mask at every size — if you bake in corners, they will look doubled.
  • No transparency of any kind. Even a single transparent pixel triggers rejection. Fill the entire canvas with a solid background.
  • No gloss, shadows, or overlays. iOS stopped adding gloss effects in iOS 7. The icon should be flat and clean.
  • sRGB color profile. Use sRGB for maximum compatibility. P3 is acceptable but may render differently on older devices.

How Expo Generates All Sizes

You provide a single icon.png at 1024x1024. During the build process, Expo (via @expo/prebuild-config) generates every required variant:

Size (px) Scale Usage
20 x 20 1x, 2x, 3x Notification icon
29 x 29 1x, 2x, 3x Settings icon
40 x 40 1x, 2x, 3x Spotlight search
60 x 60 2x, 3x Home screen icon (iPhone)
76 x 76 1x, 2x Home screen icon (iPad)
83.5 x 83.5 2x Home screen icon (iPad Pro)
1024 x 1024 1x App Store listing
Critical: Your icon renders at 29x29 pixels in the iOS Settings app. If your design has fine details, small text, or thin lines, they will be invisible at that size. Always preview your icon at small sizes before submitting.

Verifying No Alpha Channel

Before building, verify your icon has no alpha channel using the file command:

Terminal
# Check the PNG color type
file assets/icon.png

# GOOD output (no alpha):
assets/icon.png: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced

# BAD output (has alpha — will be rejected):
assets/icon.png: PNG image data, 1024 x 1024, 8-bit/color RGBA, non-interlaced

# If you need to strip alpha, use ImageMagick:
convert assets/icon.png -alpha off assets/icon.png

# Or on macOS with sips:
sips -s format png -s formatOptions noalpha assets/icon.png --out assets/icon.png

Android Adaptive Icon

Android 8.0+ (API 26) introduced adaptive icons with separate foreground and background layers, allowing each launcher to apply its own shape mask.

Two-Layer Architecture

An adaptive icon is composed of two distinct layers that are rendered independently:

  • Foreground layer — Your adaptive-icon.png file. Contains the logo/symbol on a transparent background. This is what you design.
  • Background layer — A solid color defined by android.adaptiveIcon.backgroundColor in app.json. Alternatively, this can be an image, but NativePress uses a solid color for simplicity.

Both layers are 108dp x 108dp (1024x1024 at the asset level). The system renders the background first, then composites the foreground on top, then applies the launcher’s chosen mask shape.

The Safe Zone

Different Android launchers crop adaptive icons into different shapes: circles, squircles (rounded squares), rounded rectangles, and more. To guarantee your logo is never clipped, all important content must fit within the safe zone — the center 66% of the canvas.

1024 x 1024 canvas
┌──────────────────────────────────┐
│                                  │
│    DANGER ZONE (may be clipped)    │
│                                  │
│    ┌────────────────────────┐    │
│    │                        │    │
│    │    SAFE ZONE          │    │
│    │    676 x 676 px        │    │
│    │    (center 66%)        │    │
│    │                        │    │
│    └────────────────────────┘    │
│                                  │
└──────────────────────────────────┘
174px padding on each side • Logo must fit inside the inner box

How Different Launchers Mask Icons

Launcher Shape Notes
Pixel Launcher Circle Most aggressive crop — clips to a perfect circle. The 66% safe zone is designed for this.
Samsung One UI Squircle Rounded square with continuous-curvature corners. Slightly more forgiving than circle.
OnePlus / OxygenOS Various Users can choose circle, square, squircle, or teardrop in system settings.
Xiaomi MIUI Rounded square Large corner radius. Content near corners will be clipped.
Stock AOSP Circle Same as Pixel Launcher.
Parallax effect: Android also uses the two-layer structure for a subtle parallax animation when you long-press or drag an adaptive icon. The foreground shifts slightly relative to the background. This is why both layers are 108dp even though only 72dp (66%) is visible — the extra area allows movement without revealing edges.

NativePress app.json Configuration

app.json (excerpt)
{
  "android": {
    "adaptiveIcon": {
      "foregroundImage": "./assets/adaptive-icon.png",
      "backgroundColor": "#0073aa"
    }
  }
}

Splash Screen

NativePress uses the modern expo-splash-screen plugin approach, which is required for Android 12+ and provides consistent behavior across both platforms.

Legacy vs Modern Approach

Older Expo projects used a splash key in app.json with a full-screen image (e.g., 1284x2778). This approach is deprecated and does not work on Android 12+, which introduced a system-level splash screen that apps cannot override.

NativePress uses the modern expo-splash-screen plugin, configured in the plugins array of app.json. Instead of a full-screen image, you provide a small icon that is displayed centered over a solid background color.

Aspect Legacy (splash key) Modern (expo-splash-screen plugin)
Config location expo.splash expo.plugins[["expo-splash-screen", {...}]]
Image type Full-screen image (multiple resolutions) Small centered icon (single resolution)
Android 12+ Broken — system ignores custom splash Works — integrates with system splash API
Dark mode Not supported Full support via dark config
Asset count 3-6 images at different resolutions 1-2 small icons

How imageWidth Works

The imageWidth property controls the display size of your splash icon in logical pixels (not physical pixels). The default in NativePress is 200, which means the icon will render at 200 logical pixels wide on screen, regardless of the device’s pixel density.

Your source image (splash-icon.png) is 288x288 pixels, which provides enough resolution for high-DPI screens (3x Retina displays render 200 logical pixels as 600 physical pixels — 288px source is sufficient for up to ~1.4x, and the system handles downscaling cleanly for larger displays).

Why 288px? At imageWidth: 200, a 3x display would ideally want 600px. However, the splash icon is a simple logo/mark, not a photograph — downscaling from 288px produces clean results. If you want pixel-perfect rendering at 3x, you can increase the source image to 600x600 and set imageWidth: 200.

Android 12+ Constraints

  • No full-screen splash. Android 12 introduced SplashScreen API that shows only a centered icon on a solid background. You cannot display a full-bleed branded image.
  • Icon is circular by default. On Android 12+, the system may mask your splash icon into a circle. Keep important content centered.
  • Background color only. You cannot use a gradient or image as the splash background on Android 12+.
  • System controls duration. The system determines how long the splash screen is visible. Your app can extend it slightly via SplashScreen.preventAutoHideAsync(), but cannot shorten it.

Plugin Configuration

app.json (excerpt)
[
  "expo-splash-screen",
  {
    "backgroundColor": "#0073aa",           // Light mode background
    "image":           "./assets/splash-icon.png",
    "imageWidth":      200,                   // Logical pixels
    "dark": {
      "backgroundColor": "#1a1a2e",         // Dark mode background
      "image":           "./assets/splash-icon-dark.png"
    }
  }
]

Dark Mode Support

NativePress ships with full dark mode splash screen support out of the box. The system automatically switches between light and dark variants based on the user's device settings.

How It Works

The expo-splash-screen plugin accepts a dark configuration object that mirrors the light mode config. When the device is in dark mode (as reported by the system UIUserInterfaceStyle on iOS or Configuration.uiMode on Android), the dark variant is shown instead.

Device Mode Background Color Icon File
Light Mode #0073aa splash-icon.png
Dark Mode #1a1a2e splash-icon-dark.png

When to Use Different Icons

  • White or light-colored logo: Works on both dark backgrounds. You can use the same PNG for both splash-icon.png and splash-icon-dark.png.
  • Dark or black logo: The light mode version (on #0073aa) will be visible, but the dark mode version (on #1a1a2e) will be nearly invisible. Create a white/light variant for splash-icon-dark.png.
  • Colorful logo: Test on both backgrounds. If contrast is sufficient on both, reuse the same file. If not, create a lighter variant for dark mode.
Testing dark mode: On iOS Simulator, go to Settings > Developer > Dark Appearance. On Android Emulator, go to Settings > Display > Dark theme. Toggle and cold-launch your app to see the splash screen switch.

Web Favicon

The favicon.png is only used when building for Expo Web. It is not required for iOS or Android store submissions.

  • Dimensions: 48 x 48 pixels.
  • Format: PNG, RGB.
  • Usage: Displayed in the browser tab next to the page title.
  • When needed: Only if you run npx expo start --web or deploy a web build. If you are only targeting iOS and Android, you can ignore this file.
app.json (excerpt)
{
  "web": {
    "favicon": "./assets/favicon.png"
  }
}

Step-by-Step Replacement Guide

Follow these steps in order to replace the placeholder NativePress assets with your own brand assets.

1

Design Your App Icon

Create a 1024x1024 pixel design in your preferred tool (Figma, Sketch, Illustrator, Photoshop, Affinity Designer). Use a solid background color that fills the entire canvas. Place your logo/symbol centered, with generous padding so it is recognizable at 29x29 pixels.

Do not add rounded corners, drop shadows, gloss effects, or any transparency.

2

Export icon.png (RGB, No Alpha)

Export as PNG with no transparency. In Figma: select the frame, File > Export, choose PNG, ensure the background is included. In Photoshop: Save As PNG, uncheck “Transparency.”

Verify with: file assets/icon.png — it must say RGB, not RGBA.

3

Export adaptive-icon.png (RGBA, Transparent Background)

Export the same logo/symbol at 1024x1024 but with a transparent background. The logo must be centered within the 66% safe zone (a 676x676 area in the center). Content outside this area may be clipped by launcher masks.

Verify with: file assets/adaptive-icon.png — it should say RGBA.

4

Design Splash Icons (288x288)

Create your splash screen icon at 288x288 pixels with a transparent background. This should be a simplified version of your logo — just the mark/symbol, no wordmark.

Export two versions: splash-icon.png (for light mode, visible on the light background color) and splash-icon-dark.png (for dark mode, visible on the dark background color). If your logo works on both backgrounds, use the same file for both.

5

Create Favicon (48x48) — Optional

If you plan to ship a web build, create a 48x48 PNG favicon. A simple downscaled version of your app icon works well. If you are only targeting iOS and Android, skip this step.

6

Drop Files Into assets/

Replace every file in the assets/ directory. File names must match exactly:

icon.pngadaptive-icon.pngsplash-icon.pngsplash-icon-dark.pngfavicon.png

No code changes are required at this step — the file names and paths are already configured in app.json.

7

Update Colors in app.json

Open app.json and update the color values to match your brand. See the Color Customization section below for the exact keys.

8

Build and Test

Run a development build to verify your assets render correctly:

npx expo run:ios — check the app icon on the home screen and the splash screen on launch.
npx expo run:android — check the adaptive icon shape and splash screen.
For production, run an EAS Build: eas build --platform all --profile preview

Color Customization

All asset-related color values live in app.json. Here is every color you may want to change and where to find it.

Color Default app.json Path Purpose
Splash background (light) #0073aa plugins["expo-splash-screen"].backgroundColor Background color behind the splash icon in light mode.
Splash background (dark) #1a1a2e plugins["expo-splash-screen"].dark.backgroundColor Background color behind the splash icon in dark mode.
Adaptive icon background #0073aa android.adaptiveIcon.backgroundColor Background layer color for Android adaptive icons. Visible behind the transparent foreground layer.
Consistency tip: Many apps use the same color for the splash background and the adaptive icon background. This creates a cohesive feel across the launch sequence. If your brand uses a dark color, consider making the splash background match the adaptive icon background.

Full app.json Asset Reference

Every asset-related key in app.json, in one view. Values marked with a comment are the ones you should customize.

app.json (asset-related keys only)
{
  "expo": {
    "icon": "./assets/icon.png",                   // ← Replace this file

    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png", // ← Replace this file
        "backgroundColor": "#0073aa"               // ← Your brand color
      }
    },

    "web": {
      "favicon": "./assets/favicon.png"               // ← Replace this file (web only)
    },

    "plugins": [
      [
        "expo-splash-screen",
        {
          "backgroundColor": "#0073aa",             // ← Your brand color (light)
          "image": "./assets/splash-icon.png",         // ← Replace this file
          "imageWidth": 200,                         // Adjust if icon looks too small/large
          "dark": {
            "backgroundColor": "#1a1a2e",           // ← Your dark brand color
            "image": "./assets/splash-icon-dark.png"    // ← Replace this file
          }
        }
      ]
    ]
  }
}

Common App Store Rejection Reasons

Asset-related rejections are the most common reason for first-time submission failures. Here is every known rejection scenario, the exact error message you will see, and how to fix it.

Issue Store Error Message Fix
Alpha channel in icon Apple “The app icon set ‘AppIcon’ has an unassigned child... Icons with alpha channel are not allowed.” Re-export icon.png as RGB (not RGBA). Use convert icon.png -alpha off icon.png or sips -s formatOptions noalpha.
Transparency in icon Apple “ERROR ITMS-90717: Invalid App Store Icon. The App Store Icon in the asset catalog in ‘YourApp.app’ can’t be transparent nor contain an alpha channel.” Same as above. Even a fully opaque RGBA image (all pixels at 255 alpha) will be rejected. The format itself must be RGB.
Wrong icon dimensions Apple “ERROR ITMS-90022: Missing required icon file. The bundle does not contain an app icon for iPhone / iPad...” Ensure icon.png is exactly 1024x1024 pixels. Expo will not generate sub-sizes correctly from a non-square or wrong-dimension source.
Rounded corners baked in Apple Not a hard rejection, but the icon will look wrong — doubled rounded corners with a visible artifact. Remove any corner rounding from the icon. Export a square image filling the entire 1024x1024 canvas. iOS applies its own superellipse mask.
Adaptive icon clipped Google No error message — but your icon will look broken on Pixel and Samsung devices with parts of the logo cut off. Move all important content into the center 66% safe zone (676x676 area centered on the 1024x1024 canvas). Test with a circular mask preview.
Splash blank on Android 12+ Google Users see a solid color screen with no icon on Android 12+ devices. Already handled by NativePress — the expo-splash-screen plugin is correctly configured. If you see this, ensure you did not revert to the legacy splash key in app.json.
Icon too complex at small sizes Both Not a rejection, but results in poor user experience — icon is unrecognizable in notification center, settings, and search results. Simplify your icon. Use a single bold symbol or letter. Avoid text, thin lines, photographic detail, or gradients with subtle transitions.
Placeholder assets Both Apple: “Guideline 2.3.7 — Your app icon and/or screenshots do not sufficiently reflect your app in use.” Replace all placeholder NativePress assets with your own branded assets before submitting. The default blue “NP” icon is for development only.
Icon has embedded ICC profile Apple “WARNING ITMS-90032: The app icon set contains an icon with an embedded ICC profile.” Strip the ICC profile: sips -d profile --deleteColorManagementProperties icon.png. Or re-export from your design tool with “Embed color profile” unchecked.
Corrupted PNG Both Build fails with “Unable to read image” or “Invalid PNG file” Re-export the image from your design tool. Avoid renaming a JPEG to .png — the file format must actually be PNG. Verify with file assets/icon.png.

Testing Your Assets

Verify every asset before submitting to the stores. These checks take less than five minutes and can prevent days of back-and-forth with App Review.

1. Verify File Format with file Command

Terminal
# Run this for every asset in assets/
file assets/icon.png
# Expected: PNG image data, 1024 x 1024, 8-bit/color RGB, non-interlaced

file assets/adaptive-icon.png
# Expected: PNG image data, 1024 x 1024, 8-bit/color RGBA, non-interlaced

file assets/splash-icon.png
# Expected: PNG image data, 288 x 288, 8-bit/color RGBA, non-interlaced

file assets/splash-icon-dark.png
# Expected: PNG image data, 288 x 288, 8-bit/color RGBA, non-interlaced

file assets/favicon.png
# Expected: PNG image data, 48 x 48, 8-bit/color RGB, non-interlaced

2. Preview in Simulator

  • iOS Simulator: Run npx expo run:ios. After install, check the home screen icon. Go to Settings to see the 29x29 rendering. Cold-launch the app to check the splash screen.
  • Android Emulator: Run npx expo run:android. Long-press the icon on the home screen to see the adaptive icon with parallax. Check different launcher shapes if available.
  • Dark mode: Toggle dark mode in device settings and cold-launch to verify the dark splash variant.

3. EAS Build Preview

For the most accurate test before submission, run an EAS preview build. This generates the same binary that would be uploaded to the stores.

Terminal
# Build a preview APK/IPA for testing
eas build --platform ios --profile preview
eas build --platform android --profile preview

# Install on a physical device or simulator
eas build:run --platform ios
eas build:run --platform android

4. Adaptive Icon Shape Test

To verify your adaptive icon looks correct across all launcher shapes, use Android Studio’s built-in preview tool or overlay your adaptive-icon.png with circular, squircle, and rounded-square masks in your design tool.

Quick manual test: on an Android emulator, open the app launcher, long-press your app icon, and drag it slightly. You should see the parallax effect between the foreground and background layers.

Design Tips

Practical guidance for creating app icons and splash screens that look professional and pass review on the first submission.

Icon Design

  • Keep it simple. The best app icons use a single bold shape or letter. Your icon renders at 29x29 on iOS Settings — fine details disappear entirely.
  • Use a distinct silhouette. Users recognize apps by shape, not by reading text. Your icon should be identifiable even when blurred.
  • Avoid text in the icon. Text is unreadable at small sizes and creates localization issues. If your brand is text-based, use a single letter or monogram.
  • Test on both light and dark home screens. iOS and Android support dark home screen backgrounds. Your icon should have enough contrast to stand out on both white and black backgrounds.
  • Avoid photographs. Photos lose all detail at small sizes. Use flat, geometric designs with solid colors.
  • Choose colors intentionally. Bold, saturated colors stand out on the home screen. Avoid light pastels and grays that blend into the background.
  • Match your splash icon to your app icon. The splash icon should be the same symbol/mark from your app icon, just without the background. This creates a smooth visual transition from splash to app.

Common Mistakes

Mistake Why It Is a Problem What to Do Instead
Full wordmark in icon Text is unreadable at 29x29. Looks cluttered. Use the first letter or a symbol from your brand.
Thin lines / fine details Disappear at small sizes. Look blurry on 1x screens. Use bold strokes (4px+ at 1024x1024). Test at 29x29.
Baked-in rounded corners iOS applies its own mask, resulting in double rounding. Export a perfect square filling the entire canvas.
Logo touching canvas edges On Android, launcher masks clip the edges. On iOS, the superellipse clips corners. Keep at least 10% padding on iOS. On Android, stay within the 66% safe zone.
Gradient-heavy design Subtle gradients become flat/banded at small sizes. Use solid colors or bold gradients with high contrast stops.
White icon on white background Invisible on light-themed home screens and in Settings. Use a colored background or add a subtle border in your design.
Quick sanity test: Zoom out your design to 29x29 pixels (or 3% zoom in Figma). If you can still tell what the icon is, your design is ready. If it looks like a colored blob, simplify further.
Before submitting: Double-check that you have replaced every placeholder file in assets/. Both Apple and Google will reject apps that ship with placeholder/developer artwork. The default NativePress blue “NP” icon is for development use only.