{"id":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","shortId":"Erv4Jc","kind":"skill","title":"Kotlin Springboot","tagline":"Awesome Copilot skill by Github","description":"# Spring Boot with Kotlin Best Practices\n\nYour goal is to help me write high-quality, idiomatic Spring Boot applications using Kotlin.\n\n## Project Setup & Structure\n\n- **Build Tool:** Use Maven (`pom.xml`) or Gradle (`build.gradle`) with the Kotlin plugins (`kotlin-maven-plugin` or `org.jetbrains.kotlin.jvm`).\n- **Kotlin Plugins:** For JPA, enable the `kotlin-jpa` plugin to automatically make entity classes `open` without boilerplate.\n- **Starters:** Use Spring Boot starters (e.g., `spring-boot-starter-web`, `spring-boot-starter-data-jpa`) as usual.\n- **Package Structure:** Organize code by feature/domain (e.g., `com.example.app.order`, `com.example.app.user`) rather than by layer.\n\n## Dependency Injection & Components\n\n- **Primary Constructors:** Always use the primary constructor for required dependency injection. It's the most idiomatic and concise approach in Kotlin.\n- **Immutability:** Declare dependencies as `private val` in the primary constructor. Prefer `val` over `var` everywhere to promote immutability.\n- **Component Stereotypes:** Use `@Service`, `@Repository`, and `@RestController` annotations just as you would in Java.\n\n## Configuration\n\n- **Externalized Configuration:** Use `application.yml` for its readability and hierarchical structure.\n- **Type-Safe Properties:** Use `@ConfigurationProperties` with `data class` to create immutable, type-safe configuration objects.\n- **Profiles:** Use Spring Profiles (`application-dev.yml`, `application-prod.yml`) to manage environment-specific configurations.\n- **Secrets Management:** Never hardcode secrets. Use environment variables or a dedicated secret management tool like HashiCorp Vault or AWS Secrets Manager.\n\n## Web Layer (Controllers)\n\n- **RESTful APIs:** Design clear and consistent RESTful endpoints.\n- **Data Classes for DTOs:** Use Kotlin `data class` for all DTOs. This provides `equals()`, `hashCode()`, `toString()`, and `copy()` for free and promotes immutability.\n- **Validation:** Use Java Bean Validation (JSR 380) with annotations (`@Valid`, `@NotNull`, `@Size`) on your DTO data classes.\n- **Error Handling:** Implement a global exception handler using `@ControllerAdvice` and `@ExceptionHandler` for consistent error responses.\n\n## Service Layer\n\n- **Business Logic:** Encapsulate business logic within `@Service` classes.\n- **Statelessness:** Services should be stateless.\n- **Transaction Management:** Use `@Transactional` on service methods. In Kotlin, this can be applied to class or function level.\n\n## Data Layer (Repositories)\n\n- **JPA Entities:** Define entities as classes. Remember they must be `open`. It's highly recommended to use the `kotlin-jpa` compiler plugin to handle this automatically.\n- **Null Safety:** Leverage Kotlin's null-safety (`?`) to clearly define which entity fields are optional or required at the type level.\n- **Spring Data JPA:** Use Spring Data JPA repositories by extending `JpaRepository` or `CrudRepository`.\n- **Coroutines:** For reactive applications, leverage Spring Boot's support for Kotlin Coroutines in the data layer.\n\n## Logging\n\n- **Companion Object Logger:** The idiomatic way to declare a logger is in a companion object.\n  ```kotlin\n  companion object {\n      private val logger = LoggerFactory.getLogger(MyClass::class.java)\n  }\n  ```\n- **Parameterized Logging:** Use parameterized messages (`logger.info(\"Processing user {}...\", userId)`) for performance and clarity.\n\n## Testing\n\n- **JUnit 5:** JUnit 5 is the default and works seamlessly with Kotlin.\n- **Idiomatic Testing Libraries:** For more fluent and idiomatic tests, consider using **Kotest** for assertions and **MockK** for mocking. They are designed for Kotlin and offer a more expressive syntax.\n- **Test Slices:** Use test slice annotations like `@WebMvcTest` or `@DataJpaTest` to test specific parts of the application.\n- **Testcontainers:** Use Testcontainers for reliable integration tests with real databases, message brokers, etc.\n\n## Coroutines & Asynchronous Programming\n\n- **`suspend` functions:** For non-blocking asynchronous code, use `suspend` functions in your controllers and services. Spring Boot has excellent support for coroutines.\n- **Structured Concurrency:** Use `coroutineScope` or `supervisorScope` to manage the lifecycle of coroutines.","tags":["kotlin","springboot","awesome","copilot","github"],"capabilities":["skill","source-github","category-awesome-copilot"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/kotlin-springboot","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"install_from":"skills.sh"}},"qualityScore":"0.300","qualityRationale":"deterministic score 0.30 from registry signals: · indexed on skills.sh · published under github/awesome-copilot","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T14:40:17.303Z","embedding":null,"createdAt":"2026-04-18T20:25:45.021Z","updatedAt":"2026-04-22T14:40:17.303Z","lastSeenAt":"2026-04-22T14:40:17.303Z","tsv":"'380':258 '5':438,440 'alway':106 'annot':150,260,483 'api':222 'appli':311 'applic':27,385,494 'application-dev.yml':189 'application-prod.yml':190 'application.yml':161 'approach':122 'assert':462 'asynchron':509,517 'automat':62,346 'aw':215 'awesom':3 'bean':255 'best':12 'block':516 'boilerpl':68 'boot':9,26,72,77,82,388,528 'broker':506 'build':33 'build.gradle':40 'busi':286,289 'category-awesome-copilot' 'clariti':435 'class':65,176,230,236,268,293,313,325 'class.java':422 'clear':224,356 'code':91,518 'com.example.app.order':95 'com.example.app.user':96 'companion':399,412,415 'compil':341 'compon':103,143 'concis':121 'concurr':535 'configur':157,159,183,196 'configurationproperti':173 'consid':458 'consist':226,281 'constructor':105,110,134 'control':220,524 'controlleradvic':277 'copi':246 'copilot':4 'coroutin':382,393,508,533,545 'coroutinescop':537 'creat':178 'crudrepositori':381 'data':84,175,229,235,267,317,370,374,396 'databas':504 'datajpatest':487 'declar':126,406 'dedic':207 'default':443 'defin':322,357 'depend':101,113,127 'design':223,469 'dto':266 'dtos':232,239 'e.g':74,94 'enabl':55 'encapsul':288 'endpoint':228 'entiti':64,321,323,359 'environ':194,203 'environment-specif':193 'equal':242 'error':269,282 'etc':507 'everywher':139 'excel':530 'except':274 'exceptionhandl':279 'express':476 'extend':378 'extern':158 'feature/domain':93 'field':360 'fluent':454 'free':248 'function':315,512,521 'github':7 'global':273 'goal':15 'gradl':39 'handl':270,344 'handler':275 'hardcod':200 'hashcod':243 'hashicorp':212 'help':18 'hierarch':166 'high':22,333 'high-qual':21 'idiomat':24,119,403,449,456 'immut':125,142,179,251 'implement':271 'inject':102,114 'integr':500 'java':156,254 'jpa':54,59,85,320,340,371,375 'jparepositori':379 'jsr':257 'junit':437,439 'kotest':460 'kotlin':1,11,29,43,46,51,58,124,234,307,339,350,392,414,448,471 'kotlin-jpa':57,338 'kotlin-maven-plugin':45 'layer':100,219,285,318,397 'level':316,368 'leverag':349,386 'librari':451 'lifecycl':543 'like':211,484 'log':398,424 'logger':401,408,419 'logger.info':428 'loggerfactory.getlogger':420 'logic':287,290 'make':63 'manag':192,198,209,217,300,541 'maven':36,47 'messag':427,505 'method':305 'mock':466 'mockk':464 'must':328 'myclass':421 'never':199 'non':515 'non-block':514 'notnul':262 'null':347,353 'null-safeti':352 'object':184,400,413,416 'offer':473 'open':66,330 'option':362 'org.jetbrains.kotlin.jvm':50 'organ':90 'packag':88 'parameter':423,426 'part':491 'perform':433 'plugin':44,48,52,60,342 'pom.xml':37 'practic':13 'prefer':135 'primari':104,109,133 'privat':129,417 'process':429 'profil':185,188 'program':510 'project':30 'promot':141,250 'properti':171 'provid':241 'qualiti':23 'rather':97 'reactiv':384 'readabl':164 'real':503 'recommend':334 'reliabl':499 'rememb':326 'repositori':147,319,376 'requir':112,364 'respons':283 'rest':221,227 'restcontrol':149 'safe':170,182 'safeti':348,354 'seamless':446 'secret':197,201,208,216 'servic':146,284,292,295,304,526 'setup':31 'size':263 'skill':5 'slice':479,482 'source-github' 'specif':195,490 'spring':8,25,71,76,81,187,369,373,387,527 'spring-boot-starter-data-jpa':80 'spring-boot-starter-web':75 'springboot':2 'starter':69,73,78,83 'stateless':294,298 'stereotyp':144 'structur':32,89,167,534 'supervisorscop':539 'support':390,531 'suspend':511,520 'syntax':477 'test':436,450,457,478,481,489,501 'testcontain':495,497 'tool':34,210 'tostr':244 'transact':299,302 'type':169,181,367 'type-saf':168,180 'use':28,35,70,107,145,160,172,186,202,233,253,276,301,336,372,425,459,480,496,519,536 'user':430 'userid':431 'usual':87 'val':130,136,418 'valid':252,256,261 'var':138 'variabl':204 'vault':213 'way':404 'web':79,218 'webmvctest':485 'within':291 'without':67 'work':445 'would':154 'write':20","prices":[{"id":"809e831d-f4e6-4dff-8fd8-91d1b0f93e4b","listingId":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"github","category":"awesome-copilot","install_from":"skills.sh"},"createdAt":"2026-04-18T20:25:45.021Z"}],"sources":[{"listingId":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","source":"github","sourceId":"github/awesome-copilot/kotlin-springboot","sourceUrl":"https://github.com/github/awesome-copilot/tree/main/skills/kotlin-springboot","isPrimary":false,"firstSeenAt":"2026-04-18T21:50:00.650Z","lastSeenAt":"2026-04-22T12:52:16.000Z"},{"listingId":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","source":"skills_sh","sourceId":"github/awesome-copilot/kotlin-springboot","sourceUrl":"https://skills.sh/github/awesome-copilot/kotlin-springboot","isPrimary":true,"firstSeenAt":"2026-04-18T20:25:45.021Z","lastSeenAt":"2026-04-22T14:40:17.303Z"}],"details":{"listingId":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"github","slug":"kotlin-springboot","source":"skills_sh","category":"awesome-copilot","skills_sh_url":"https://skills.sh/github/awesome-copilot/kotlin-springboot"},"updatedAt":"2026-04-22T14:40:17.303Z"}}