android-compose-ui
Compose UI patterns for Android/KMP - stability, recomposition, side effects, lazy lists, animations, previews, accessibility, modifier extensions, and design…
Skill by kvithayathil
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/kvithayathil-android-compose-ui
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: design, backend, writing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/android-compose-ui
What's inside
- Skill name
android-compose-ui- Description
- Compose UI patterns for Android/KMP - stability, recomposition, side effects, lazy lists, animations, previews, accessibility, modifier extensions, and design system composables. Use this skill whenever writing or reviewing composables, optimizing recomposition, adding animations, creating previews, writing custom modifiers, structuring a design system, or making any Compose UI decision beyond the MVI/ViewModel layer. Trigger on phrases like "composable", "recomposition", "LaunchedEffect", "Modifier", "LazyColumn", "preview", "animation", "design system", "stability", "contentDescription", "graphicsLayer", "slot API", or "Compose performance".
- License
- AGPL-3.0
- Instructions
- 242 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Android / KMP Compose UI Patterns
## Core Principle
The UI is dumb. Composables render state and forward user actions — nothing more. All state lives in the ViewModel. All logic lives in the ViewModel, domain, or data layer. Compose code should contain zero business logic, zero data transformation, and minimal side effects.
---
## Stability & Recomposition
Strong skipping mode is enabled by default in modern Compose — no explicit opt-in needed.
Only annotate a state data class with `@Stable` when it contains fields the Compose compiler considers unstable (e.g., `List`, `Map`, `Set`, interfaces, or abstract types). If all fields are primitive types, `String`, or other stable types, no annotation is needed.
```kotlin
// Needs @Stable — contains a List (unstable by default)
@Stable
data class NoteListState(
val notes: List<NoteUi> = emptyList(),
val isLoading: Boolean = false
)
// No annotation needed — all fields are stable
data class NoteDetailState(
val title: String = "",
val body: String = "",
val isSaving: Boolean = false
)
```
---
## State Ownership
All state lives in the ViewModel. Do not use `remember` or `rememberSaveable` for application state — that belongs in the ViewModel's `StateFlow` and is surfaced via `collectAsStateWithLifecycle()`.
The only exception is Compose-internal state that the framework requires you to hold in composition, such as `LazyListState`, `ScrollState`, or `PagerState`. For these, use `remember*` as needed:
```kotlin
// Acceptable — Compose-owned UI state
val lazyListState = rememberLazyListState()
// Reacting to Compose-owned state with derivedStateOf
val showScrollToTop by remember {
derivedStateOf { lazyListState.firstVisibleItemIndex > 5 }
}
```
`derivedStateOf` should only be used in these rare scenarios where Compose-internal state drives a derived value. If the derivation can happen in the ViewModel, it should.
Always collect ViewModel state with lifecycle awareness:
```kotlin
val state by viewModel.state.collectAsStateWithLifecycle()
```
---
## Side Effects
Side effects should be avoided when possible. If something can be handled by the ViewModel through an Action, do that instead of using a side effect in a composable.
When a side effect is truly necessary (e.g., interacting with Android lifecycle APIs that have no ViewModel equivalent), extract it into a dedicated composable to keep the Screen composable clean:
```kotlin
// Extracted into its own composable
@Composable
fun ObserveLifecycle(onStart: () -> Unit, onStop: () -> Unit) {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_START -> onStart()
Lifecycle.Event.ON_STOP -> onStop()
else -> Unit
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}
}
```
`LaunchedEffect` is acceptable when genuinely needed, but question whether the work belongs in the ViewModel first. Do not use custom `CompositionLocal`s.
---
## Lazy Layouts
Add `key` to lazy list items when there is an obvious unique identifier available. Don't force it if it's unclear which property is unique:
```kotlin
LazyColumn {
items(
items = state.notes,
key = { it.id } // id is clearly unique
) { note ->
NoteItem(note = note, onClick = { onAction(OnNoteClick(note.id)) })
}
}
```
---
## Animations
Avoid animations that cause recompositions. Prefer approaches that animate below the recomposition layer:
- **`graphicsLayer`** — for alpha, scale, rotation, translation
- **Offset lambda** — for position changes (`offset { ... }`)
- **`Canvas`** — for custom drawing that animates
- **`animateFloatAsState` + `graphicsLayer`** — animate a float, apply in graphicsLayer
```kotlin
// Good — animates without recomposition
val alpha by animateFloatAsState(if (state.isVisible) 1f else 0f)
Box(
modifier = Modifier.graphicsLayer { this.alpha = alpha }
)From kvithayathil/agent-resources, AGPL-3.0.
More from kvithayathil/agent-resources
- 0.544score
design-an-interface
mattpocock
Generate multiple radically different interface designs for a module using parallel sub-agents.
SkillAFreshness: AClaude Code +9 - 0.539score
grill-me
mattpocock
Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree.
SkillAFreshness: AClaude Code +9 - 0.479score
modern-git-patterns
kvithayathil
Use when working with git commands, planning git workflows, advising on git best practices, or needing version-aware git guidance.
SkillCFreshness: CClaude Code +9 - 0.414score
android-layouts
kvithayathil
Android layout best practices for XML/Views and Jetpack Compose.
SkillDFreshness: DClaude Code +9 - 0.414score
design-md
kvithayathil
Create, consume, and validate DESIGN.md files — the open format for describing visual identity to coding agents.
SkillDFreshness: DClaude Code +9 - 0.410score
provenance-tracking
kvithayathil
Ensures every remote-installed skill has a references/ folder citing its upstream source and can be checked for updates against that source.
SkillDFreshness: DClaude Code +9 - 0.409score
android-error-handling
kvithayathil
Generic Result wrapper, error types, and extension helpers for Android/KMP - Result<T, E>, DataError, EmptyResult, map, onSuccess, onFailure.
SkillDFreshness: DClaude Code +9 - 0.409score
android-module-structure
kvithayathil
Module layout, dependency rules, and Gradle convention plugins for Android and Kotlin Multiplatform (KMP) projects.
SkillDFreshness: DClaude Code +9 - 0.409score
android-navigation
kvithayathil
Type-safe Compose Navigation for Android/KMP - route objects, feature nav graphs, cross-feature callbacks, and wiring in :app.
SkillDFreshness: DClaude Code +9 - 0.409score
android-presentation-mvi
kvithayathil
MVI presentation layer for Android/KMP - State, Action, Event, ViewModel, Root/Screen composable split, UI models, UiText error mapping, and process death…
SkillDFreshness: DClaude Code +9 - 0.409score
android-di-koin
kvithayathil
Koin dependency injection setup for Android/KMP - module definitions per layer, ViewModel injection, assembling modules in :app, and koinViewModel() in…
SkillDFreshness: DClaude Code +9 - 0.409score
android-data-layer
kvithayathil
Data layer patterns for Android/KMP - data sources, repositories, DTOs, mappers, Room entities, Ktor HttpClient, safe call helpers, token storage, and…
SkillDFreshness: DClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 1
- Last commit (this folder)
- Apr 14, 2026 (6 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- AGPL-3.0
- Repository
- github.com/kvithayathil/agent-resources
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from kvithayathil
- 0.479score
modern-git-patterns
kvithayathil
Use when working with git commands, planning git workflows, advising on git best practices, or needing version-aware git guidance.
SkillCFreshness: CClaude Code +9 - 0.414score
design-md
kvithayathil
Create, consume, and validate DESIGN.md files — the open format for describing visual identity to coding agents.
SkillDFreshness: DClaude Code +9 - 0.414score
android-layouts
kvithayathil
Android layout best practices for XML/Views and Jetpack Compose.
SkillDFreshness: DClaude Code +9 - 0.410score
provenance-tracking
kvithayathil
Ensures every remote-installed skill has a references/ folder citing its upstream source and can be checked for updates against that source.
SkillDFreshness: DClaude Code +9 - 0.409score
android-di-koin
kvithayathil
Koin dependency injection setup for Android/KMP - module definitions per layer, ViewModel injection, assembling modules in :app, and koinViewModel() in…
SkillDFreshness: DClaude Code +9 - 0.409score
android-error-handling
kvithayathil
Generic Result wrapper, error types, and extension helpers for Android/KMP - Result<T, E>, DataError, EmptyResult, map, onSuccess, onFailure.
SkillDFreshness: DClaude Code +9
Cite this page
android-compose-ui skill. Agent Mart. https://agentmart.dev/skills/kvithayathil-android-compose-ui (last updated 2026-10-24)