Kotlin UI Compose Multiplatform
Communitymmiani
Use when designing, implementing, or reviewing shared UI in Compose Multiplatform projects, including state-driven architecture, composable decomposition, layout/modifier discipline, adaptive behavior, and previewable shared UI in common source sets.
Overview
- Repository
- mmiani/kotlin-kmp-claude-agent-skills
- Publisher
- mmiani
- Stars
- 93
- Forks
- 9
- Bundled files
- 0
- License
- Not stated
- Updated
- Aug 15, 2026
Installation
tmp=$(mktemp -d)
git clone --depth 1 https://github.com/mmiani/kotlin-kmp-claude-agent-skills.git "$tmp"
mkdir -p ~/.claude/skills
cp -R "$tmp/skills/kotlin-ui-compose-multiplatform" ~/.claude/skills/kotlin-ui-compose-multiplatform
rm -rf "$tmp"tmp=$(mktemp -d)
git clone --depth 1 https://github.com/mmiani/kotlin-kmp-claude-agent-skills.git "$tmp"
mkdir -p ~/.codex/skills
cp -R "$tmp/skills/kotlin-ui-compose-multiplatform" ~/.codex/skills/kotlin-ui-compose-multiplatform
rm -rf "$tmp"Install the Kotlin UI Compose Multiplatform agent skill from https://github.com/mmiani/kotlin-kmp-claude-agent-skills/tree/main/skills/kotlin-ui-compose-multiplatform into this project's skills folder.Instructions
Compose Multiplatform UI
Use this skill when designing, implementing, or reviewing shared UI in a Compose Multiplatform project.
This skill is intentionally strict. Its purpose is to keep shared UI declarative, state-driven, decomposed, adaptive, previewable, and cleanly separated from business logic and platform entry concerns.
Primary goals
The UI design should optimize for:
- state-driven rendering
- clear composable decomposition
- business logic outside composables
- layout structure that remains understandable
- modifier usage that is intentional and explainable
- adaptive behavior across different window sizes
- previewability in common code
- clean separation between shared UI and platform-specific startup or OS integration
Do not treat Compose UI as just “screens and widgets”. Treat it as part of app architecture.
Official defaults to prefer
Unless the project has a strong reason not to, prefer:
- UI driven from immutable state
- state hoisting when multiple composables need to coordinate state
- side effects handled deliberately rather than embedded in rendering paths
- composables focused on rendering and interaction, not business rules
- shared UI in
commonMainwhen valid across targets - platform-specific UI bootstrapping and OS integration in platform source sets
- adaptive layouts driven by structured window-size reasoning
- previewable shared UI with
@Previewwhere useful
KMP project-structure expectations
Compose Multiplatform projects typically place shared Compose code in a shared source set such as composeApp/src/commonMain/kotlin, with platform-specific code in source sets such as androidMain and iosMain.
Review expectations:
- shared composables, shared UI state models, and reusable UI components belong in shared source sets when they are valid across targets
- platform entry points, startup wiring, and OS-specific integrations stay in platform-specific source sets
- UI architecture does not assume Android-only behavior as the default model for shared code
Flag as a concern when:
- shared UI is duplicated across targets without a real platform difference
- platform-specific assumptions leak into shared composables
- common UI code depends on platform-only APIs
Review dimensions
1. State-driven UI
Compose guidance treats state management as foundational.
Check whether:
- UI renders from explicit immutable state
- rendering is driven by state instead of imperative mutation
- state ownership is clear
- composables are not reaching into dependencies ad hoc
Flag as a concern when:
- composables fetch or mutate state from many unrelated places
- UI is driven by scattered booleans rather than a coherent model
- rendering depends on hidden mutable state
2. State hoisting
Compose explicitly documents state hoisting as a core design tool.
Check whether:
- state is hoisted when multiple composables need to coordinate it
- local state remains local when it is truly local
- app- or screen-level state is not trapped in leaf composables
- callbacks and state ownership are easy to trace
Flag as a concern when:
- sibling composables coordinate through hidden shared state
- screen-critical state lives in leaf components
- hoisting is skipped and duplication appears across the tree
3. State lifespans and saveability
Compose docs distinguish state lifespans and saving UI state.
Check whether:
- ephemeral UI state is distinguished from longer-lived screen state
- saveable UI state is used intentionally where needed
- business-critical state is not confused with short-lived widget state
KMP platform note: rememberSaveable with Bundle-based serialization is Android-specific. On iOS, desktop, and web KMP targets, the state-restoration mechanism differs or may not exist in the same form. If a project expects state restoration across process recreation on non-Android targets, verify that the chosen state-persistence mechanism is platform-appropriate rather than assuming rememberSaveable behavior is universal.
Flag as a concern when:
- important UI state is lost unnecessarily on any target
- trivial widget state is elevated too far
- long-lived state is modeled as disposable local widget state
rememberSaveablewith Android-specific serializers is used in shared code without a non-Android fallback
4. Side-effect discipline
Compose explicitly treats side effects as a distinct design concern.
Check whether:
- side effects are isolated and deliberate
- recomposition does not accidentally retrigger important actions
- navigation, analytics, toasts, and one-off actions are not embedded casually in rendering branches
- rendering stays as pure as practical
Flag as a concern when:
- side effects are triggered directly from unstable composable paths
- repeated recomposition can duplicate work
- business or navigation effects are hard to reason about
5. UI architecture and layering
Android’s Compose docs place UI architecture, architectural layering, and navigation alongside state guidance.
Check whether:
- composables focus on rendering and interaction
- state holders or orchestration layers sit between UI and lower layers
- business logic is not embedded in UI
- UI models are shaped for presentation instead of mirroring raw transport/data models
Flag as a concern when:
- UI calls repositories directly
- DTOs or persistence models reach rendering code directly
- screen composables own orchestration, data parsing, and business rules inline
6. Composable decomposition
Check whether:
- large screens are broken into meaningful subcomposables
- reusable UI pieces are extracted where repetition exists
- component boundaries are understandable
- destination-level composables do not become monoliths
Flag as a concern when:
- one screen file owns all structure, state, and rendering inline
- reusable visual patterns are duplicated broadly
- composable boundaries do not reflect ownership clearly
7. Layout structure
Kotlin’s layout docs identify Rows, Columns, Boxes, lazy lists, and related primitives as the main layout building blocks.
Check whether:
- layout structure is readable
- containers are chosen intentionally
- layout nesting is not excessive without reason
- lists and grids are used where scrolling collections exist
- app shells and screen bodies remain understandable under growth
Flag as a concern when:
- layout structure is overly tangled
- wrong container choices create brittle UI
- scrolling/content structure is improvised instead of modeled clearly
8. Modifier discipline
Modifier order and combination matter.
Check whether:
- modifier chains are readable
- modifier order is intentional
- sizing, padding, click handling, offsets, scrolling, and semantics are combined in a way that is explainable
- adaptive or interaction behavior is not hidden in long opaque chains
Flag as a concern when:
- modifier order causes accidental behavior
- layout understanding depends on trial and error
- giant modifier chains obscure ownership and behavior
9. Adaptive layout readiness
Kotlin's adaptive-layout docs support window-size-driven adaptation.
This skill reviews whether shared UI is structurally ready for adaptive behavior — composed cleanly enough that adaptive variations can be added without a full rewrite. For deep guidance covering canonical layouts, multi-window support, list-detail patterns, supporting-pane behavior, and the full adaptive review framework, use the kotlin-ui-adaptive-resources skill.
Check whether:
- shared UI can adapt between compact, medium, and expanded layouts where appropriate
- layout decisions can respond to window size rather than one fixed phone assumption
- screen structure can evolve into multi-pane or wider layouts without a rewrite
- adaptive concerns are considered early rather than retrofitted as an afterthought
Flag as a concern when:
- UI is designed only for one narrow window shape with no structural flexibility
- larger layouts just stretch phone UI without meaningful structural adaptation
- adaptation would require tearing apart the entire screen composable tree
10. Window-size-driven UI decisions
Adaptive docs provide structured size-class APIs (rememberWindowAdaptiveInfo(), WindowWidthSizeClass) for layout decisions. For full guidance on these APIs and canonical adaptive patterns, use the kotlin-ui-adaptive-resources skill. This section reviews structural readiness in shared UI.
Check whether:
- major shell/layout decisions can be expressed through structured window-size reasoning, not hardcoded dp breakpoints
- adaptive branching is centralized enough to stay maintainable — one place to read window size, not scattered per-screen
- width-driven changes preserve the same feature mental model across sizes
Flag as a concern when:
- arbitrary pixel/dp breakpoints are used instead of the structured size-class API
- adaptive behavior differs inconsistently from screen to screen without a reason
- layout branches are too fragmented to understand centrally
11. Previewability
Compose Multiplatform previews support @Preview in common code when configured with ui-tooling-preview in commonMain.
Check whether:
- reusable components are previewable independently
- screen states can be previewed without full app bootstrapping
- adaptive variants are previewed where useful
- previews are practical enough to support iteration
Flag as a concern when:
- every UI change requires running the app
- screens are too entangled to preview meaningfully
- key visual states are difficult to inspect in isolation
12. Accessibility and semantics
Compose UI quality should account for semantics and user interaction clarity.
Check whether:
- content structure is understandable for accessibility services (TalkBack on Android, VoiceOver on iOS via Compose Multiplatform semantics bridge)
- icon-only buttons and image-only interactive elements expose a
contentDescription clearAndSetSemanticsis used intentionally — it removes all child semantics, which silences descendant content for screen readerssemantics { }merging behavior is explicit when composable groups are used as single logical units- focus ordering makes sense when adaptive layout rearranges components spatially
- text contrast and touch target sizes remain acceptable across compact and expanded window states
Flag as a concern when:
- icon buttons or decorative-looking interactive elements have no
contentDescription clearAndSetSemantics {}is applied broadly without auditing what it silences- adaptive layout changes create focus traps or confusing reading order
- visible structure and semantic structure drift apart (e.g., a single logical card reads as multiple unrelated elements)
- semantics are omitted entirely from screens that change significantly with window size
13. Shared-vs-platform UI boundary
Check whether:
- shared composables remain platform-agnostic
- platform-specific startup, window integration, and OS hooks remain outside shared screen code
- the common UI layer does not own Android/iOS entry responsibilities
Flag as a concern when:
- platform bootstrapping logic leaks into
commonMain - shared UI depends on platform-specific APIs
- platform-specific visuals or lifecycle details shape common UI unnecessarily
14. Testability
UI architecture should support testing and inspection.
Check whether:
- shared UI behavior can be validated in common tests where appropriate
- composables are decomposed enough to test behavior or semantics
- state-holder behavior is validated outside UI when possible
- previewability and testability reinforce each other
Flag as a concern when:
- UI correctness can only be validated through full manual runs
- composables are too monolithic to test meaningfully
- state behavior is only inferred through large end-to-end paths
Severity framework
High severity
Likely to cause architectural drift or broken UI behavior.
Examples:
- business logic embedded in composables
- no clear state owner
- side effects triggered from unstable rendering paths
- platform-only APIs in shared UI
- UI built only for one narrow window size
Medium severity
Workable, but likely to create maintenance cost.
Examples:
- weak state hoisting
- oversized screen composables
- tangled layout structure
- modifier order causing brittle behavior
- adaptive behavior present but inconsistent
- poor previewability
Low severity
Structurally acceptable but worth improving.
Examples:
- composable boundaries could be cleaner
- preview coverage could be broader
- modifier chains could be simplified
- adaptive branches could be centralized more clearly
Required output format
When performing the review, respond with:
UI summary
- state model
- composable structure
- layout/modifier approach
- adaptive strategy
- preview strategy
- shared/platform boundary
What is structurally sound
- concrete strengths only
Issues by review dimension
- state-driven UI
- state hoisting
- state lifespans/saveability
- side effects
- UI architecture/layering
- composable decomposition
- layout structure
- modifier discipline
- adaptive readiness
- window-size-driven decisions
- previewability
- accessibility/semantics
- shared-vs-platform boundary
- testability
Severity for each issue
- high / medium / low
Concrete recommendations
- exact restructuring steps
- what state should be hoisted
- what should move out of composables
- how layout/modifier structure should be simplified
- where adaptive branches should live
- what should become previewable/testable
Suggested target structure
- proposed screen / component / state / preview split if useful
Open risks
- migration cost
- visual/regression risk
- platform-specific constraints still to validate
Tone
Be direct and practical. Do not praise UI just because it renders. If the design is weak, say why clearly.
Anti-patterns to flag aggressively
- business logic in composables
- hidden mutable state driving rendering
- poor or absent state hoisting
- side effects triggered from unstable composable paths
- giant screen composables
- long opaque modifier chains
- layouts designed for one phone size only
- shared UI coupled to platform-specific APIs
- UI that cannot be previewed meaningfully
- tests forced to validate simple UI behavior only through large integration paths
References
- Jetpack Compose documentation: https://developer.android.com/develop/ui/compose/documentation
- Compose Multiplatform: Create your first app: https://kotlinlang.org/docs/multiplatform/compose-multiplatform-create-first-app.html
- Compose Multiplatform: Layout basics: https://kotlinlang.org/docs/multiplatform/compose-layout.html
- Compose Multiplatform: Modifiers: https://kotlinlang.org/docs/multiplatform/compose-layout-modifiers.html
- Compose Multiplatform: Adaptive layouts: https://kotlinlang.org/docs/multiplatform/compose-adaptive-layouts.html
- Compose Multiplatform: Previews: https://kotlinlang.org/docs/multiplatform/compose-previews.html
- Android: Compose state and Jetpack: https://developer.android.com/develop/ui/compose/state
- Android: Accessibility in Compose: https://developer.android.com/develop/ui/compose/accessibility
FAQ
What does Kotlin UI Compose Multiplatform do?
Use when designing, implementing, or reviewing shared UI in Compose Multiplatform projects, including state-driven architecture, composable decomposition, layout/modifier discipline, adaptive behavior, and previewable shared UI in common source sets.
Who made Kotlin UI Compose Multiplatform?
mmiani (a community member) publishes it in the mmiani/kotlin-kmp-claude-agent-skills repository on GitHub.
Is Kotlin UI Compose Multiplatform free?
Kotlin UI Compose Multiplatform is public on GitHub, but its repository has no license, so check with mmiani before reusing it in your own work.
What comes with Kotlin UI Compose Multiplatform?
Just its instructions. Everything the agent needs is in one SKILL.md file.
Which agents can use Kotlin UI Compose Multiplatform?
Any coding agent that reads SKILL.md files, including Claude Code, Codex, Cursor, GitHub Copilot and Gemini CLI. The agent loads the skill when a task matches its description.
What are agent skills?
An agent skill is a folder with a SKILL.md file: instructions that teach a coding agent how to do one kind of task, and optionally files it can read while it works. The agent keeps only the skill's name and description in mind and reads the rest when a task calls for it.
How are agent skills different from MCP servers?
An MCP server gives an agent new tools to call, code that runs somewhere and returns results. A skill gives it knowledge: how to approach a task with the tools it already has. Many agents use both.
How can my agent test my Android app?
Robomori lets coding agents create, start and control Android emulators and devices from one command, so they can install your app, take screenshots and check dark mode, font sizes and languages.