Skip to content

Multiplatform Workflows

Storytale provides dedicated runner tasks for Desktop, Web (Wasm), Android, and iOS.


1. Desktop (JVM)

The Desktop runner launches a native desktop window directly from Gradle.

./gradlew :composeApp:desktopStoriesRun

Storytale Desktop Gallery Storytale Desktop Gallery

Highlights

  • Runs directly from Gradle without creating intermediate emulator devices.
  • Supports macOS, Linux, and Windows hosts.
  • Re-executes instantaneously for quick UI iteration.

2. Web (WebAssembly / Wasm)

Storytale compiles directly to WebAssembly (wasmJs), allowing you to publish interactive storybook galleries to any static website, CDN, or GitHub Pages.

Storytale Web Wasm Gallery Storytale Web Wasm Gallery

Development Server

./gradlew :composeApp:wasmJsBrowserStoriesRun
Starts a local development server with live reload.

Production Static Distribution

./gradlew :composeApp:wasmJsBrowserStoriesProductionExecutableDistribution

The compiled output is emitted to:

build/dist/wasmJs/productionExecutable/
├── index.html
├── skiko.wasm
└── <module-name>.wasm

You can deploy these static files to GitHub Pages, Cloudflare Pages, Vercel, or AWS S3.


3. Android (Device & Emulator)

Storytale supports both Android Applications (com.android.application) and modern Android Multiplatform Libraries (com.android.kotlin.multiplatform.library / com.android.library).

./gradlew :composeApp:androidStoriesRun

Storytale running on Android Device

Self-Contained Library Runner

When applied to a library module (such as :composeApp or :shared): 1. Device Test Wiring: Automatically configures the Android deviceTest target and generates a synthetic AndroidManifest.xml registering StorytaleAppActivity. 2. Deterministic Installation: Packages the test APK (<module>-androidTest.apk) and installs it onto the active device via adb install -r. 3. Activity Launch: Immediately invokes am start -n <package>.test/<package>.test.StorytaleAppActivity. 4. App Coexistence: Because the stories APK runs under the test package suffix (.test), it coexists concurrently with your main host application (androidApp) on the same physical phone or emulator without namespace collision.

Android SDK Configuration

When using Kotlin backtick identifiers with spaces (e.g. val `Primary Button State` by story), Kotlin generates synthetic delegate fields with spaces in their names.

To ensure the Android D8 desugarer and dexer can package these identifiers, configure your minSdk to 30 (Android 11) or higher:

android {
  defaultConfig {
    minSdk = 30
  }
}

Android DEX Format 040

Android DEX format 040 (introduced in API 30) fully supports spaces and arbitrary UTF-8 characters in simple identifier names. If your app must target minSdk < 30, use simple identifiers without spaces (e.g. val PrimaryButtonState by story).


4. iOS (Simulator)

Storytale includes built-in iOS simulator synthesis and runner tasks:

./gradlew :composeApp:iosSimulatorArm64StoriesRun
./gradlew :composeApp:iosX64StoriesRun

Storytale running on iOS Simulator

Resilient Simulator Resolution

The Storytale Gradle plugin automatically queries xcrun simctl to discover currently booted or available simulators (such as an iPhone 16 or iPad Pro). If an active simulator is already open, Storytale reuses it directly without creating duplicate devices.

You can also specify a specific simulator device ID via Gradle property:

./gradlew :composeApp:iosX64StoriesRun -Pstorytale.ios.simulator.id=<device-udid>

What the Task Does

  1. Resolves the active simulator UUID and target architecture (arm64 or x86_64).
  2. Compiles the Kotlin/Native debug framework (StorytaleFramework.framework).
  3. Generates the wrapper Xcode project with proper Info.plist bundle identifiers.
  4. Builds the .app bundle using xcodebuild targeting iphonesimulator.
  5. Installs the app via xcrun simctl install.
  6. Launches the gallery app in the simulator via xcrun simctl launch.

Target Matrix Summary

Platform Gradle Task Runtime Environment Output Artifact
Desktop (JVM) :desktopStoriesRun JVM Window JVM Process
Web (Wasm) :wasmJsBrowserStoriesRun Browser (Wasm GC) Static .wasm & .html
Android :androidStoriesRun Device / Emulator via ADB <module>-androidTest.apk
iOS :iosSimulatorArm64StoriesRun / :iosX64StoriesRun iOS Simulator via simctl iOS .app bundle

Next Steps