{"id":"2271ca79-0fe2-4a51-b08d-6aa9fa4f4a8d","shortId":"Erv4Jc","kind":"skill","title":"kotlin-springboot","tagline":"Get best practices for developing applications with Spring Boot and Kotlin.","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","agent-skills","agents","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"capabilities":["skill","source-github","skill-kotlin-springboot","topic-agent-skills","topic-agents","topic-awesome","topic-custom-agents","topic-github-copilot","topic-hacktoberfest","topic-prompt-engineering"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/kotlin-springboot","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add github/awesome-copilot","source_repo":"https://github.com/github/awesome-copilot","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 33270 github stars · SKILL.md body (4,281 chars)","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-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:52:15.702Z","embedding":null,"createdAt":"2026-04-18T20:25:45.021Z","updatedAt":"2026-05-18T18:52:15.702Z","lastSeenAt":"2026-05-18T18:52:15.702Z","tsv":"'380':265 '5':445,447 'alway':113 'annot':157,267,490 'api':229 'appli':318 'applic':9,34,392,501 'application-dev.yml':196 'application-prod.yml':197 'application.yml':168 'approach':129 'assert':469 'asynchron':516,524 'automat':69,353 'aw':222 'bean':262 'best':5,19 'block':523 'boilerpl':75 'boot':12,16,33,79,84,89,395,535 'broker':513 'build':40 'build.gradle':47 'busi':293,296 'clariti':442 'class':72,183,237,243,275,300,320,332 'class.java':429 'clear':231,363 'code':98,525 'com.example.app.order':102 'com.example.app.user':103 'companion':406,419,422 'compil':348 'compon':110,150 'concis':128 'concurr':542 'configur':164,166,190,203 'configurationproperti':180 'consid':465 'consist':233,288 'constructor':112,117,141 'control':227,531 'controlleradvic':284 'copi':253 'coroutin':389,400,515,540,552 'coroutinescop':544 'creat':185 'crudrepositori':388 'data':91,182,236,242,274,324,377,381,403 'databas':511 'datajpatest':494 'declar':133,413 'dedic':214 'default':450 'defin':329,364 'depend':108,120,134 'design':230,476 'develop':8 'dto':273 'dtos':239,246 'e.g':81,101 'enabl':62 'encapsul':295 'endpoint':235 'entiti':71,328,330,366 'environ':201,210 'environment-specif':200 'equal':249 'error':276,289 'etc':514 'everywher':146 'excel':537 'except':281 'exceptionhandl':286 'express':483 'extend':385 'extern':165 'feature/domain':100 'field':367 'fluent':461 'free':255 'function':322,519,528 'get':4 'global':280 'goal':22 'gradl':46 'handl':277,351 'handler':282 'hardcod':207 'hashcod':250 'hashicorp':219 'help':25 'hierarch':173 'high':29,340 'high-qual':28 'idiomat':31,126,410,456,463 'immut':132,149,186,258 'implement':278 'inject':109,121 'integr':507 'java':163,261 'jpa':61,66,92,327,347,378,382 'jparepositori':386 'jsr':264 'junit':444,446 'kotest':467 'kotlin':2,14,18,36,50,53,58,65,131,241,314,346,357,399,421,455,478 'kotlin-jpa':64,345 'kotlin-maven-plugin':52 'kotlin-springboot':1 'layer':107,226,292,325,404 'level':323,375 'leverag':356,393 'librari':458 'lifecycl':550 'like':218,491 'log':405,431 'logger':408,415,426 'logger.info':435 'loggerfactory.getlogger':427 'logic':294,297 'make':70 'manag':199,205,216,224,307,548 'maven':43,54 'messag':434,512 'method':312 'mock':473 'mockk':471 'must':335 'myclass':428 'never':206 'non':522 'non-block':521 'notnul':269 'null':354,360 'null-safeti':359 'object':191,407,420,423 'offer':480 'open':73,337 'option':369 'org.jetbrains.kotlin.jvm':57 'organ':97 'packag':95 'parameter':430,433 'part':498 'perform':440 'plugin':51,55,59,67,349 'pom.xml':44 'practic':6,20 'prefer':142 'primari':111,116,140 'privat':136,424 'process':436 'profil':192,195 'program':517 'project':37 'promot':148,257 'properti':178 'provid':248 'qualiti':30 'rather':104 'reactiv':391 'readabl':171 'real':510 'recommend':341 'reliabl':506 'rememb':333 'repositori':154,326,383 'requir':119,371 'respons':290 'rest':228,234 'restcontrol':156 'safe':177,189 'safeti':355,361 'seamless':453 'secret':204,208,215,223 'servic':153,291,299,302,311,533 'setup':38 'size':270 'skill' 'skill-kotlin-springboot' 'slice':486,489 'source-github' 'specif':202,497 'spring':11,15,32,78,83,88,194,376,380,394,534 'spring-boot-starter-data-jpa':87 'spring-boot-starter-web':82 'springboot':3 'starter':76,80,85,90 'stateless':301,305 'stereotyp':151 'structur':39,96,174,541 'supervisorscop':546 'support':397,538 'suspend':518,527 'syntax':484 'test':443,457,464,485,488,496,508 'testcontain':502,504 'tool':41,217 'topic-agent-skills' 'topic-agents' 'topic-awesome' 'topic-custom-agents' 'topic-github-copilot' 'topic-hacktoberfest' 'topic-prompt-engineering' 'tostr':251 'transact':306,309 'type':176,188,374 'type-saf':175,187 'use':35,42,77,114,152,167,179,193,209,240,260,283,308,343,379,432,466,487,503,526,543 'user':437 'userid':438 'usual':94 'val':137,143,425 'valid':259,263,268 'var':145 'variabl':211 'vault':220 'way':411 'web':86,225 'webmvctest':492 'within':298 'without':74 'work':452 'would':161 'write':27","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-05-18T18:52:15.702Z"},{"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-05-07T22:40:17.904Z"}],"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","github":{"repo":"github/awesome-copilot","stars":33270,"topics":["agent-skills","agents","ai","awesome","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"license":"mit","html_url":"https://github.com/github/awesome-copilot","pushed_at":"2026-05-18T01:26:59Z","description":"Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.","skill_md_sha":"7737e98b2b965fd12f3b1fa9ddd69ca474ba409a","skill_md_path":"skills/kotlin-springboot/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/github/awesome-copilot/tree/main/skills/kotlin-springboot"},"layout":"multi","source":"github","category":"awesome-copilot","frontmatter":{"name":"kotlin-springboot","description":"Get best practices for developing applications with Spring Boot and Kotlin."},"skills_sh_url":"https://skills.sh/github/awesome-copilot/kotlin-springboot"},"updatedAt":"2026-05-18T18:52:15.702Z"}}