$npx -y skills add anhvt52/jetpack-compose-skills --skill modern-jetpack-composeGuides writing, reviewing, and reasoning about modern Android UI code using Jetpack Compose. Covers best practices for state management, side effects, recomposition, navigation, Material 3 design, accessibility, and performance. Use when reading, writing, or reviewing any Jetpack
| 1 | Review or generate Jetpack Compose code for correctness, modern API usage, |
| 2 | and adherence to Android best practices. Report only genuine issues — do not |
| 3 | nitpick style unless it contradicts a clear rule. |
| 4 | |
| 5 | ## Review / Generation Process |
| 6 | |
| 7 | When reviewing existing code, follow these steps in order: |
| 8 | |
| 9 | 1. Check for deprecated or outdated APIs → `references/api.md` |
| 10 | 2. Review composable structure and composition patterns → `references/composables.md` |
| 11 | 3. Validate state management and data flow → `references/state.md` |
| 12 | 4. Validate side-effect usage → `references/effects.md` |
| 13 | 5. Check recomposition stability → `references/recomposition.md` |
| 14 | 6. Validate navigation implementation → `references/navigation.md` |
| 15 | 7. Check Material 3 / Expressive design compliance → `references/design.md` |
| 16 | 8. Validate accessibility → `references/accessibility.md` |
| 17 | 9. Check performance → `references/performance.md` |
| 18 | 10. Quick Kotlin code review → `references/kotlin.md` |
| 19 | 11. Final code hygiene check → `references/hygiene.md` |
| 20 | |
| 21 | When **generating** new code, load the relevant reference files for the feature |
| 22 | being built before writing any code, so output is idiomatic from the start. |
| 23 | |
| 24 | For partial reviews or targeted generation, load only the relevant reference files. |
| 25 | |
| 26 | |
| 27 | ## Core Instructions |
| 28 | |
| 29 | - Target Compose BOM 2024.x by default. Note where BOM 2025.x (Material Expressive) |
| 30 | introduces new components or APIs. |
| 31 | - Use Material 3. Do not use Material 2 unless the project already uses it. |
| 32 | - Architecture: MVVM with unidirectional data flow (UDF). ViewModel + StateFlow |
| 33 | for screen state. Compose UI observes state, emits events. |
| 34 | - Target Kotlin with modern language features (sealed interfaces, coroutines, Flow). |
| 35 | - Do not introduce third-party libraries without asking first. |
| 36 | - Each composable should live in its own file for non-trivial components. |
| 37 | - Organize by feature, not by technical layer (screens/home/, screens/settings/, etc.). |
| 38 | |
| 39 | |
| 40 | ## Output Format |
| 41 | |
| 42 | Organize findings by file. For each issue: |
| 43 | |
| 44 | 1. State the file and relevant line(s). |
| 45 | 2. Name the rule being violated. |
| 46 | 3. Show a brief before/after Kotlin snippet. |
| 47 | |
| 48 | Skip files with no issues. End with a prioritized summary of the most impactful |
| 49 | changes to make first. |
| 50 | |
| 51 | **Example output:** |
| 52 | |
| 53 | ### HomeScreen.kt |
| 54 | |
| 55 | **Line 14: Use `collectAsStateWithLifecycle()` instead of `collectAsState()`.** |
| 56 | |
| 57 | ```kotlin |
| 58 | // Before |
| 59 | val uiState by viewModel.uiState.collectAsState() |
| 60 | |
| 61 | // After |
| 62 | val uiState by viewModel.uiState.collectAsStateWithLifecycle() |
| 63 | ``` |
| 64 | |
| 65 | **Line 42: Provide `key` in LazyColumn for stable item identity.** |
| 66 | |
| 67 | ```kotlin |
| 68 | // Before |
| 69 | LazyColumn { |
| 70 | items(books) { book -> |
| 71 | BookItem(book) |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | // After |
| 76 | LazyColumn { |
| 77 | items(books, key = { it.id }) { book -> |
| 78 | BookItem(book) |
| 79 | } |
| 80 | } |
| 81 | ``` |
| 82 | |
| 83 | **Line 67: Image missing contentDescription — required for accessibility.** |
| 84 | |
| 85 | ```kotlin |
| 86 | // Before |
| 87 | Image(painter = painterResource(R.drawable.cover), contentDescription = null) |
| 88 | |
| 89 | // After — if decorative: |
| 90 | Image(painter = painterResource(R.drawable.cover), contentDescription = null) // OK if truly decorative |
| 91 | |
| 92 | // After — if meaningful: |
| 93 | Image( |
| 94 | painter = painterResource(R.drawable.cover), |
| 95 | contentDescription = stringResource(R.string.book_cover_description) |
| 96 | ) |
| 97 | ``` |
| 98 | |
| 99 | ### Summary |
| 100 | |
| 101 | 1. **State (high):** `collectAsState()` on line 14 does not respect lifecycle — replace with `collectAsStateWithLifecycle()`. |
| 102 | 2. **Performance (medium):** Missing `key` in `LazyColumn` on line 42 causes unnecessary recomposition. |
| 103 | 3. **Accessibility (medium):** Image on line 67 needs a meaningful `contentDescription`. |
| 104 | |
| 105 | --- |
| 106 | |
| 107 | ## References |
| 108 | |
| 109 | - `references/api.md` — deprecated APIs and their modern replacements. |
| 110 | - `references/composables.md` — composable structure, naming, and composition patterns. |
| 111 | - `references/state.md` — state management, ViewModel, StateFlow, and data flow. |
| 112 | - `references/effects.md` — side effects: LaunchedEffect, DisposableEffect, SideEffect. |
| 113 | - `references/recomposition.md` — recomposition stability, @Stable/@Immutable, derivedStateOf. |
| 114 | - `references/navigation.md` — Navigation Compose, type-safe nav, nested graphs. |
| 115 | - `references/design.md` — Material 3 / Expressive theming, adaptive layouts. |
| 116 | - `references/accessibility.md` — TalkBack, semantics, content descriptions, touch targets. |
| 117 | - `references/performance.md` — LazyList optimization, remember, scope of state reads. |
| 118 | - `references/kotlin.md` — modern Kotlin patterns for Android. |
| 119 | - `references/hygiene.md` — code hygiene, testing, lint. |