java-junit
JUnit 5 best practices for standard and data-driven unit testing with practical patterns.
kotlin-multiplatform
KMP/CMP shared business logic, Compose Multiplatform, expect/actual, Ktor, SQLDelight, and platform-specific implementations. Use when building cross-platform Kotlin applications for Android, iOS, desktop, or web.
Full skill instructions
Shared business logic and optional shared UI across Android, iOS, desktop, and web.
project/
├── composeApp/ # Shared Compose UI (if using CMP)
│ └── src/
│ ├── commonMain/ # Shared UI code
│ ├── androidMain/ # Android-specific UI
│ ├── iosMain/ # iOS-specific UI
│ └── desktopMain/ # Desktop-specific UI
├── shared/ # Shared business logic (KMP)
│ └── src/
│ ├── commonMain/ # Shared code
│ │ └── kotlin/
│ │ ├── data/ # Repositories, data sources
│ │ ├── domain/ # Use cases, models
│ │ └── platform/ # expect declarations
│ ├── androidMain/ # actual implementations
│ ├── iosMain/ # actual implementations
│ └── commonTest/ # Shared tests
├── androidApp/ # Android entry point
├── iosApp/ # iOS entry point (Xcode project)
├── build.gradle.kts
└── settings.gradle.kts
// commonMain - expect declaration
expect class PlatformContext
expect fun getPlatformName(): String
expect fun createHttpClient(): HttpClient
// androidMain - actual implementation
actual class PlatformContext(val context: android.content.Context)
actual fun getPlatformName(): String = "Android ${Build.VERSION.SDK_INT}"
actual fun createHttpClient(): HttpClient = HttpClient(OkHttp) {
install(ContentNegotiation) { json() }
}
// iosMain - actual implementation
actual class PlatformContext
actual fun getPlatformName(): String = UIDevice.currentDevice.systemName()
actual fun createHttpClient(): HttpClient = HttpClient(Darwin) {
install(ContentNegotiation) { json() }
}
| Library | Purpose | Multiplatform? |
|---|---|---|
| Ktor | HTTP client | Yes |
| kotlinx.serialization | JSON parsing | Yes |
| kotlinx.coroutines | Async/concurrency | Yes |
| SQLDelight | Local database | Yes |
| Koin | Dependency injection | Yes |
| Compose Multiplatform | Shared UI | Yes |
| kotlinx.datetime | Date/time | Yes |
| Napier | Logging | Yes |
// commonMain
class ApiClient(private val httpClient: HttpClient) {
suspend fun getUsers(): List<User> {
return httpClient.get("https://api.example.com/users").body()
}
suspend fun createUser(input: CreateUserInput): User {
return httpClient.post("https://api.example.com/users") {
contentType(ContentType.Application.Json)
setBody(input)
}.body()
}
}
@Serializable
data class User(
val id: String,
val name: String,
val email: String,
)
-- src/commonMain/sqldelight/com/example/UserQueries.sq
CREATE TABLE user (
id TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
cached_at INTEGER NOT NULL
);
selectAll:
SELECT * FROM user ORDER BY name;
insertOrReplace:
INSERT OR REPLACE INTO user (id, name, email, cached_at)
VALUES (?, ?, ?, ?);
deleteById:
DELETE FROM user WHERE id = ?;
// commonMain - Shared composable
@Composable
fun UserListScreen(viewModel: UserListViewModel) {
val users by viewModel.users.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
Scaffold(
topBar = { TopAppBar(title = { Text("Users") }) }
) { padding ->
if (isLoading) {
CircularProgressIndicator(modifier = Modifier.padding(padding))
} else {
LazyColumn(modifier = Modifier.padding(padding)) {
items(users) { user ->
UserRow(user = user, onClick = { viewModel.onUserClick(user.id) })
}
}
}
}
}
// iosApp - Using shared Kotlin code from Swift
import shared
class UserViewController: UIViewController {
private let viewModel = UserListViewModel()
override func viewDidLoad() {
super.viewDidLoad()
viewModel.users.collect(collector: FlowCollector { users in
// Update UI with users
})
}
}
// build.gradle.kts
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
cocoapods {
summary = "Shared module"
homepage = "https://example.com"
ios.deploymentTarget = "16.0"
framework { baseName = "shared" }
}
}
// commonTest
class UserRepositoryTest {
private val fakeApi = FakeApiClient()
private val repository = UserRepository(fakeApi)
@Test
fun fetchUsersReturnsListFromApi() = runTest {
fakeApi.setUsers(listOf(User("1", "Alice", "[email protected]")))
val users = repository.getUsers()
assertEquals(1, users.size)
assertEquals("Alice", users.first().name)
}
}
expect/actual sparingly — prefer interfaces with platform implementations via DIcommonTest — it runs on all targets~/.claude/skills/android-development/SKILL.md - Android patterns~/.claude/skills/ios-development/SKILL.md - iOS patterns~/.claude/agents/flutter-developer.md - Alternative cross-platformShare logic, respect platforms. KMP gives you the best of both worlds.
JUnit 5 best practices for standard and data-driven unit testing with practical patterns.
Upgrades React Native apps to newer versions by applying rn-diff-purge template diffs, updating package.json dependencies, migrating native iOS and Android configuration, resolving CocoaPods and Gradle changes, and handling breaking API updates. Use when upgrading React Native, bumping RN version, updating from RN 0.x to 0.y, or migrating Expo SDK alongside a React Native upgrade.
Javadoc best practices for documenting Java types, methods, and members.
Spring Boot development patterns and idioms tailored for Kotlin applications.
Generate a Spring Boot 3.4.5 project skeleton with PostgreSQL, Redis, MongoDB, and Docker Compose.
Java method extraction refactoring for improved readability and maintainability.
Refactoring using Remove Parameter in Java Language
Generate production-ready MCP servers in Java with the official SDK, Maven or Gradle, and reactive streams.
Generate a Spring Boot Kotlin project skeleton with pre-configured databases and development services.
Automate GraalVM native image configuration, build, and error resolution for Java applications.
Generate production-ready Kotlin MCP server projects with Gradle, official SDK, and typed tools.
spring boot engineer
Opus.ai: Revolutionize Your Web Experience
Build a no-code AI app in minutes.
An IDE for code migration from legacy to modern frameworks through coding agents.
Automate CGI animation in live-action scenes
Branded artistic QR-code concepts
Launch a website in seconds with AI.
Streamline Your Coding Experience with AI Code Helper
Convert any screenshot or design to clean code.