Home › Android / Kotlin › Android Jetpack Compose Windsurf rules
Android Jetpack Compose Windsurf rules
Windsurf rules for Android apps in Kotlin and Jetpack Compose: state hoisting, ViewModel + StateFlow, Material 3, navigation, Hilt and Compose UI tests.
WindsurfAndroid / Kotlin
How to use
Save this as .windsurf/rules/compose.md in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
Note: Review and test before use. Provided as is, without warranty. See Terms.
.windsurf/rules/compose.mdDownload ---
trigger: glob
globs: **/*.kt,**/*.kts
---
# Android + Jetpack Compose
- Build: `./gradlew assembleDebug`, `./gradlew lint`, `./gradlew test`, `./gradlew connectedAndroidTest` (when a device/emulator is available). Versions live in `gradle/libs.versions.toml`; use the Compose BOM.
- Architecture: UI (composables) → `ViewModel` → repository → data sources. ViewModels expose `StateFlow<UiState>` (one immutable data class or sealed interface per screen) and take events as functions.
- Collect state with `collectAsStateWithLifecycle()`. No `LiveData` in new code.
- Composables are stateless where possible: hoist state, pass values and lambdas (`onClick: () -> Unit`). Screen-level composables get the ViewModel; inner ones don't.
- Every composable that emits UI takes `modifier: Modifier = Modifier` as its first optional parameter and applies it to the root.
- `remember`/`rememberSaveable` for UI-only state; side effects with `LaunchedEffect(key)`, `DisposableEffect`, never in the composition body.
- Use Material 3 components and `MaterialTheme` tokens (colors, typography); support dark theme and dynamic color. No hard-coded colors or sp sizes outside the theme.
- Navigation with type-safe Navigation Compose routes (`@Serializable` destinations) if the project's version supports it.
- DI with Hilt (`@HiltViewModel`, `hiltViewModel()`) if present; coroutines via `viewModelScope` with injected dispatchers.
- Lists use `LazyColumn` with stable `key`s; avoid unstable lambdas/objects causing recomposition.
- Accessibility: `contentDescription` for meaningful icons, 48dp touch targets.
- Add `@Preview` for each screen state.
## Tests
ViewModel unit tests with `kotlinx-coroutines-test` and Turbine; UI tests with `createComposeRule()` using semantics, not text coordinates.