Jetpack Compose
Communityahmed3elshaer
Jetpack Compose patterns for declarative UI, state management, theming, animations, and performance optimization.
Overview
- Repository
- ahmed3elshaer/everything-claude-code-mobile
- Publisher
- ahmed3elshaer
- Stars
- 66
- Forks
- 18
- Bundled files
- 0
- License
- MIT
- Updated
- Jun 14, 2026
Installation
tmp=$(mktemp -d)
git clone --depth 1 https://github.com/ahmed3elshaer/everything-claude-code-mobile.git "$tmp"
mkdir -p ~/.claude/skills
cp -R "$tmp/skills/jetpack-compose" ~/.claude/skills/jetpack-compose
rm -rf "$tmp"tmp=$(mktemp -d)
git clone --depth 1 https://github.com/ahmed3elshaer/everything-claude-code-mobile.git "$tmp"
mkdir -p ~/.codex/skills
cp -R "$tmp/skills/jetpack-compose" ~/.codex/skills/jetpack-compose
rm -rf "$tmp"Install the Jetpack Compose agent skill from https://github.com/ahmed3elshaer/everything-claude-code-mobile/tree/main/skills/jetpack-compose into this project's skills folder.Instructions
Jetpack Compose Patterns
Modern declarative UI patterns for Android.
State Management
State Hoisting
// ✅ CORRECT: Stateless composable
@Composable
fun Counter(
count: Int,
onIncrement: () -> Unit,
modifier: Modifier = Modifier
) {
Row(modifier = modifier) {
Text("Count: $count")
Button(onClick = onIncrement) {
Text("+")
}
}
}
// Parent owns state
@Composable
fun CounterScreen() {
var count by rememberSaveable { mutableStateOf(0) }
Counter(
count = count,
onIncrement = { count++ }
)
}Remember Variants
// remember - Survives recomposition
val alpha by remember { mutableStateOf(1f) }
// rememberSaveable - Survives config change
var count by rememberSaveable { mutableStateOf(0) }
// remember with key - Resets on key change
val animation = remember(itemId) { Animatable(0f) }
// derivedStateOf - Computed, updates only when result changes
val isValid by remember {
derivedStateOf { email.isNotBlank() && password.length >= 8 }
}Composition Patterns
Slot API
@Composable
fun AppBar(
title: @Composable () -> Unit,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {}
) {
TopAppBar(
title = { title() },
navigationIcon = { navigationIcon() },
actions = actions
)
}
// Usage
AppBar(
title = { Text("Home") },
navigationIcon = { IconButton(onClick = {}) { Icon(Icons.Default.Menu, null) } },
actions = {
IconButton(onClick = {}) { Icon(Icons.Default.Search, null) }
}
)Modifier Pattern
@Composable
fun CustomButton(
onClick: () -> Unit,
modifier: Modifier = Modifier, // First optional parameter
enabled: Boolean = true,
content: @Composable RowScope.() -> Unit
) {
Button(
onClick = onClick,
modifier = modifier, // Apply modifier first
enabled = enabled,
content = content
)
}Side Effects
LaunchedEffect
@Composable
fun HomeScreen(viewModel: HomeViewModel) {
// Runs once
LaunchedEffect(Unit) {
viewModel.loadData()
}
// Runs when key changes
LaunchedEffect(userId) {
viewModel.loadUser(userId)
}
}DisposableEffect
@Composable
fun LifecycleObserver(onResume: () -> Unit) {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) onResume()
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}Theming
Material 3
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}
// Usage
val backgroundColor = MaterialTheme.colorScheme.surface
val textStyle = MaterialTheme.typography.bodyLargeLists
LazyColumn
LazyColumn {
items(
items = users,
key = { it.id } // Critical for performance
) { user ->
UserItem(user = user)
}
}Animations
Animate Values
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = tween(durationMillis = 300)
)
val size by animateDpAsState(
targetValue = if (expanded) 200.dp else 100.dp
)AnimatedContent
AnimatedContent(
targetState = state,
transitionSpec = {
fadeIn() togetherWith fadeOut()
}
) { targetState ->
when (targetState) {
is Loading -> LoadingContent()
is Success -> SuccessContent(targetState.data)
is Error -> ErrorContent()
}
}Remember: Compose is declarative. Describe the UI, don't command it.
FAQ
What does Jetpack Compose do?
Jetpack Compose patterns for declarative UI, state management, theming, animations, and performance optimization.
Who made Jetpack Compose?
ahmed3elshaer (a community member) publishes it in the ahmed3elshaer/everything-claude-code-mobile repository on GitHub.
Is Jetpack Compose free?
Yes. Jetpack Compose is open source, published by ahmed3elshaer under the MIT license.
What comes with Jetpack Compose?
Just its instructions. Everything the agent needs is in one SKILL.md file.
Which agents can use Jetpack Compose?
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.