Awesome-omni-skill moai-lang-kotlin
Kotlin 2.0+ development specialist covering Ktor, coroutines, Compose Multiplatform, and Kotlin-idiomatic patterns. Use when building Kotlin server apps, Android apps, or multiplatform projects.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/backend/moai-lang-kotlin-majiayu000" ~/.claude/skills/diegosouzapw-awesome-omni-skill-moai-lang-kotlin && rm -rf "$T"
skills/backend/moai-lang-kotlin-majiayu000/SKILL.mdQuick Reference (30 seconds)
Kotlin 2.0+ Expert - K2 compiler, coroutines, Ktor, Compose Multiplatform with Context7 integration.
Auto-Triggers: Kotlin files (
.kt, .kts), Gradle Kotlin DSL (build.gradle.kts, settings.gradle.kts)
Core Capabilities:
- Kotlin 2.0: K2 compiler, coroutines, Flow, sealed classes, value classes
- Ktor 3.0: Async HTTP server/client, WebSocket, JWT authentication
- Exposed 0.55: Kotlin SQL framework with coroutines support
- Spring Boot (Kotlin): Kotlin-idiomatic Spring with WebFlux
- Compose Multiplatform: Desktop, iOS, Web, Android UI
- Testing: JUnit 5, MockK, Kotest, Turbine for Flow testing
Implementation Guide (5 minutes)
Kotlin 2.0 Features
Coroutines and Flow:
// Structured concurrency with async/await suspend fun fetchUserWithOrders(userId: Long): UserWithOrders = coroutineScope { val userDeferred = async { userRepository.findById(userId) } val ordersDeferred = async { orderRepository.findByUserId(userId) } UserWithOrders(userDeferred.await(), ordersDeferred.await()) } // Flow for reactive streams fun observeUsers(): Flow<User> = flow { while (true) { emit(userRepository.findLatest()) delay(1000) } }.flowOn(Dispatchers.IO)
Sealed Classes and Value Classes:
sealed interface Result<out T> { data class Success<T>(val data: T) : Result<T> data class Error(val exception: Throwable) : Result<Nothing> data object Loading : Result<Nothing> } @JvmInline value class UserId(val value: Long) { init { require(value > 0) { "UserId must be positive" } } } @JvmInline value class Email(val value: String) { init { require(value.contains("@")) { "Invalid email format" } } }
Ktor 3.0 Server
Application Setup:
fun main() { embeddedServer(Netty, port = 8080, host = "0.0.0.0") { configureKoin() configureSecurity() configureRouting() configureContentNegotiation() }.start(wait = true) } fun Application.configureKoin() { install(Koin) { modules(appModule) } } val appModule = module { single<Database> { DatabaseFactory.create() } single<UserRepository> { UserRepositoryImpl(get()) } single<UserService> { UserServiceImpl(get()) } } fun Application.configureSecurity() { install(Authentication) { jwt("auth-jwt") { realm = "User API" verifier(JwtConfig.verifier) validate { credential -> if (credential.payload.audience.contains("api")) JWTPrincipal(credential.payload) else null } } } } fun Application.configureContentNegotiation() { install(ContentNegotiation) { json(Json { prettyPrint = true; ignoreUnknownKeys = true }) } }
Routing with Authentication:
fun Application.configureRouting() { val userService by inject<UserService>() routing { route("/api/v1") { post("/auth/register") { val request = call.receive<CreateUserRequest>() val user = userService.create(request) call.respond(HttpStatusCode.Created, user.toDto()) } authenticate("auth-jwt") { route("/users") { get { val page = call.parameters["page"]?.toIntOrNull() ?: 0 val size = call.parameters["size"]?.toIntOrNull() ?: 20 call.respond(userService.findAll(page, size).map { it.toDto() }) } get("/{id}") { val id = call.parameters["id"]?.toLongOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest) userService.findById(id)?.let { call.respond(it.toDto()) } ?: call.respond(HttpStatusCode.NotFound) } } } } } }
Exposed SQL Framework
Table and Entity:
object Users : LongIdTable("users") { val name = varchar("name", 100) val email = varchar("email", 255).uniqueIndex() val passwordHash = varchar("password_hash", 255) val status = enumerationByName<UserStatus>("status", 20) val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp()) } class UserEntity(id: EntityID<Long>) : LongEntity(id) { companion object : LongEntityClass<UserEntity>(Users) var name by Users.name var email by Users.email var passwordHash by Users.passwordHash var status by Users.status var createdAt by Users.createdAt fun toModel() = User(id.value, name, email, passwordHash, status, createdAt) }
Repository with Coroutines:
class UserRepositoryImpl(private val database: Database) : UserRepository { override suspend fun findById(id: Long): User? = dbQuery { UserEntity.findById(id)?.toModel() } override suspend fun save(user: User): User = dbQuery { UserEntity.new { name = user.name email = user.email passwordHash = user.passwordHash status = user.status }.toModel() } private suspend fun <T> dbQuery(block: suspend () -> T): T = newSuspendedTransaction(Dispatchers.IO, database) { block() } }
Spring Boot with Kotlin
WebFlux Controller:
@RestController @RequestMapping("/api/users") class UserController(private val userService: UserService) { @GetMapping suspend fun listUsers( @RequestParam(defaultValue = "0") page: Int, @RequestParam(defaultValue = "20") size: Int ): Flow<UserDto> = userService.findAll(page, size).map { it.toDto() } @GetMapping("/{id}") suspend fun getUser(@PathVariable id: Long): ResponseEntity<UserDto> = userService.findById(id)?.let { ResponseEntity.ok(it.toDto()) } ?: ResponseEntity.notFound().build() @PostMapping suspend fun createUser(@Valid @RequestBody request: CreateUserRequest): ResponseEntity<UserDto> { val user = userService.create(request) return ResponseEntity.created(URI.create("/api/users/${user.id}")).body(user.toDto()) } }
Advanced Patterns
Compose Multiplatform
Shared UI Component:
@Composable fun UserListScreen(viewModel: UserListViewModel, onUserClick: (Long) -> Unit) { val uiState by viewModel.uiState.collectAsState() when (val state = uiState) { is UiState.Loading -> LoadingIndicator() is UiState.Success -> UserList(state.users, onUserClick) is UiState.Error -> ErrorMessage(state.message, onRetry = viewModel::retry) } } @Composable fun UserCard(user: User, onClick: () -> Unit) { Card( modifier = Modifier.fillMaxWidth().clickable(onClick = onClick), elevation = CardDefaults.cardElevation(4.dp) ) { Row(modifier = Modifier.padding(16.dp)) { AsyncImage(model = user.avatarUrl, contentDescription = user.name, modifier = Modifier.size(48.dp).clip(CircleShape)) Spacer(Modifier.width(16.dp)) Column { Text(user.name, style = MaterialTheme.typography.titleMedium) Text(user.email, style = MaterialTheme.typography.bodySmall) } } } }
Testing with MockK
class UserServiceTest { private val userRepository = mockk<UserRepository>() private val userService = UserService(userRepository) @Test fun `should fetch user concurrently`() = runTest { val testUser = User(1L, "John", "john@example.com") coEvery { userRepository.findById(1L) } coAnswers { delay(100); testUser } val result = userService.findById(1L) assertThat(result).isEqualTo(testUser) } @Test fun `should handle Flow emissions`() = runTest { val users = listOf(User(1L, "John", "john@example.com")) coEvery { userRepository.findAllAsFlow() } returns users.asFlow() userService.streamUsers().toList().also { result -> assertThat(result).hasSize(1) } } }
Gradle Build Configuration
plugins { kotlin("jvm") version "2.0.20" kotlin("plugin.serialization") version "2.0.20" id("io.ktor.plugin") version "3.0.0" } kotlin { jvmToolchain(21) } dependencies { implementation("io.ktor:ktor-server-core-jvm") implementation("io.ktor:ktor-server-netty-jvm") implementation("io.ktor:ktor-server-content-negotiation-jvm") implementation("io.ktor:ktor-server-auth-jwt-jvm") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0") implementation("org.jetbrains.exposed:exposed-core:0.55.0") implementation("org.jetbrains.exposed:exposed-dao:0.55.0") implementation("org.postgresql:postgresql:42.7.3") testImplementation("io.mockk:mockk:1.13.12") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0") testImplementation("app.cash.turbine:turbine:1.1.0") }
Context7 Integration
Library mappings for latest documentation:
- Ktor 3.0 server/client documentation/ktorio/ktor
- Exposed SQL framework/jetbrains/exposed
- Kotlin 2.0 language reference/JetBrains/kotlin
- Coroutines library/Kotlin/kotlinx.coroutines
- Compose Multiplatform/jetbrains/compose-multiplatform
- Arrow functional programming/arrow-kt/arrow
Usage:
docs = await mcp__context7__get_library_docs( context7CompatibleLibraryID="/ktorio/ktor", topic="routing authentication jwt", tokens=8000 )
When to Use Kotlin
Use Kotlin When:
- Developing Android applications (official language)
- Building modern server applications with Ktor
- Preferring concise, expressive syntax
- Building reactive services with coroutines and Flow
- Creating multiplatform applications (iOS, Desktop, Web)
- Full Java interoperability required
Consider Alternatives When:
- Legacy Java codebase requiring minimal changes
- Big data pipelines (prefer Scala with Spark)
Works Well With
- Java interoperability and Spring Boot patternsmoai-lang-java
- REST API, GraphQL, microservices architecturemoai-domain-backend
- JPA, Exposed, R2DBC patternsmoai-domain-database
- JUnit 5, MockK, TestContainers integrationmoai-quality-testing
- JVM container optimizationmoai-infra-docker
Troubleshooting
K2 Compiler: Add
kotlin.experimental.tryK2=true to gradle.properties; clear .gradle for rebuild
Coroutines: Avoid
runBlocking in suspend contexts; use Dispatchers.IO for blocking operations
Ktor: Ensure
ContentNegotiation installed; check JWT verifier configuration; verify routing hierarchy
Exposed: Ensure all DB operations in transaction; be aware of entity loading outside transaction
Advanced Documentation
For comprehensive reference materials:
- reference.md - Complete ecosystem, Context7 mappings, testing patterns, performance
- examples.md - Production-ready code examples, Ktor, Compose, Android patterns
Last Updated: 2025-12-07 Status: Production Ready (v1.0.0)