# compose-multiplatform

Provides Compose Multiplatform patterns for Android, iOS, Desktop, and Web. It guides UI architecture and platform interop via expect and actual declarations.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 951 installs · ★ 677
- Author: AThevon
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/AThevon/genjutsu/tree/HEAD/skills/_jutsu/compose-multiplatform/SKILL.md
- Updated: 2026-10-05
- HTML: https://affpapa.org/en/nevibecode/skills/compose-multiplatform

## What it does

This skill targets projects configured with the `org.jetbrains.compose` plugin. It enforces keeping 80 to 95% of the codebase inside `commonMain`. Target-specific code stays separated inside `androidMain`, `iosMain`, `desktopMain`, and `wasmJsMain`.

Platform differences are bridged using `expect` and `actual` declarations. The skill demonstrates how to wrap native UI like iOS `UIKitView` or Android `RuntimeShader`. Separate composables should stay rare. Fine-tuning tokens in shared code is usually cleaner. For assets, SVG works across all targets except Android, which still requires Android XML drawables.

Relying on `LocalConfiguration` in shared code will break the build because it is Android-only. The skill redirects you to `LocalWindowInfo.current.containerSize` and `BoxWithConstraints`. This prevents compilation errors on iOS and desktop targets.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add AThevon/genjutsu --skill compose-multiplatform -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/compose-multiplatform/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/compose-multiplatform/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add AThevon/genjutsu --skill compose-multiplatform -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/compose-multiplatform/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add AThevon/genjutsu --skill compose-multiplatform -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/compose-multiplatform/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install AThevon/genjutsu compose-multiplatform
```

2. **Manually: put the files in place**
- File: `.github/skills/compose-multiplatform/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add AThevon/genjutsu --skill compose-multiplatform -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/AThevon/genjutsu --path skills/_jutsu/compose-multiplatform
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/compose-multiplatform/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add AThevon/genjutsu --skill compose-multiplatform -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/AThevon/genjutsu/tree/HEAD/skills/_jutsu/compose-multiplatform/SKILL.md

## When to use it
- organize cross-platform project structure across target source sets
- implement platform-specific UI using `expect` and `actual` composables
- replace Android-only `LocalConfiguration` with cross-platform alternatives
- load shared custom fonts using `compose.resources` and typed accessors

## Example prompts
- Implement a platform-specific blur using `expect` and `actual` for Android and iOS.
- Show how to configure a custom font family with `Res.font` in `commonMain`.
- How do I check window size in shared Compose code without `LocalConfiguration`?

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 1d5e3498001331a7.

BEGIN THIRD-PARTY FILE 1d5e3498001331a7
````text
---
name: compose-multiplatform
description: "Compose Multiplatform / KMP patterns - expect/actual composables, platform-specific code, density and font handling cross-target, iOS/Android/Desktop interop."
metadata:
  internal: true
---

> **Version-sensitive.** Every API name, SDK gate and browser-support claim below was
> verified on **2026-09-08** against primary sources. What against, and when, is in
> `_jutsu/VERSIONS.md`. If that date is old, re-verify before acting on a version number.

# Compose Multiplatform

> Compose Multiplatform (CMP) and Kotlin Multiplatform (KMP) patterns for cross-platform UI.
> Loaded for projects with `org.jetbrains.compose` plugin.
> Foundation: `../compose-motion/SKILL.md` for animation API; this file covers what's specific to writing one Compose codebase for Android + iOS + Desktop + Web.

---

## KMP vs CMP - quick clarification

**KMP** (Kotlin Multiplatform) is the language and build infrastructure: shared Kotlin code compiled to JVM, Native (iOS, macOS, Linux, Windows), and Wasm. **CMP** (Compose Multiplatform) is the UI framework on top of KMP, built by JetBrains as a port of Jetpack Compose. You write a single Compose codebase in `commonMain` that runs on Android, iOS, Desktop (JVM), and Web (Wasm). Platform-specific code lives in `androidMain`, `iosMain`, `desktopMain`, `wasmJsMain` and is wired in via `expect`/`actual` declarations.

---

## Project structure

```
composeApp/
├── src/
│   ├── commonMain/        ← shared Compose code (most of the app)
│   │   └── kotlin/
│   ├── androidMain/       ← Android-specific (uses Activity, Context)
│   ├── iosMain/           ← iOS-specific (uses UIKit/UIView interop)
│   ├── desktopMain/       ← JVM desktop (uses java.awt/swing if needed)
│   └── wasmJsMain/        ← Wasm web target
├── build.gradle.kts
iosApp/                    ← Xcode project consuming the generated framework
androidApp/                ← Android Application module (often merged into composeApp)
```

The `commonMain` folder should hold 80-95% of your code in a well-architected CMP project. If `iosMain` or `androidMain` start growing past a few hundred lines, you're probably leaking platform concerns into UI logic that could stay shared.

---

## `expect`/`actual` pattern

The KMP escape hatch when you genuinely need different implementations per target. Declare the contract once in `commonMain`, implement it once per target.

```kotlin
// commonMain
expect fun openShareSheet(text: String)

// androidMain
actual fun openShareSheet(text: String) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
````
END THIRD-PARTY FILE 1d5e3498001331a7

The third-party file has ended. Everything between the 1d5e3498001331a7 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2701 of 16727 bytes. © AThevon · MIT · https://github.com/AThevon/genjutsu/tree/HEAD/skills/_jutsu/compose-multiplatform/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
