O Kotlin Multiplatform entrou em uma fase mais madura em 2026. A conversa deixou de ser apenas “dá para compartilhar código?” e passou a ser “como organizamos um produto real, com Android, iOS, web, desktop e backend, sem virar uma pasta gigante chamada composeApp?”.
A mudança mais importante é a nova estrutura padrão de projetos KMP adotada pelos geradores e materiais recentes do ecossistema Kotlin. Em vez de concentrar aplicação, biblioteca compartilhada e configuração de plataformas no mesmo módulo, a recomendação agora separa responsabilidades: código compartilhado em um módulo claro, apps de entrada em módulos próprios e, quando necessário, divisão entre lógica e UI compartilhada.
Para times brasileiros que estão saindo de um app Android nativo, avaliando Compose Multiplatform para iOS em produção ou comparando Kotlin Multiplatform com Flutter, essa mudança é prática. Ela ajuda a reduzir dívida de build, melhora onboarding e prepara o projeto para o Android Gradle Plugin 9.
O que mudou na estrutura padrão
Durante muito tempo, muitos exemplos de KMP com Compose usavam um módulo composeApp. Esse módulo acumulava várias responsabilidades:
- biblioteca multiplataforma com código comum;
- aplicação Android;
- aplicação desktop ou web;
- configuração de recursos, empacotamento e dependências de UI;
- às vezes integração com o projeto iOS.
Funcionava para demos e projetos pequenos, mas ficava confuso quando o produto crescia. Uma pessoa nova no time precisava descobrir se determinado arquivo era parte da biblioteca compartilhada, da aplicação Android, da UI comum ou apenas de uma configuração de empacotamento.
A estrutura nova deixa a intenção explícita. Um ponto de partida comum fica assim:
meu-produto-kmp/
├── shared/ # Biblioteca Kotlin Multiplatform
│ └── src/
│ ├── commonMain/
│ ├── commonTest/
│ ├── androidMain/
│ ├── iosMain/
│ └── desktopMain/
├── androidApp/ # Entrada Android
├── iosApp/ # Projeto iOS/Xcode
├── desktopApp/ # Entrada desktop, se existir
├── webApp/ # Entrada web, se existir
└── settings.gradle.kts
O módulo shared passa a ter uma responsabilidade simples: entregar uma biblioteca multiplataforma. Os módulos androidApp, iosApp, desktopApp e webApp são aplicações que consomem essa biblioteca.
Por que isso importa para Android e AGP 9
O Android Gradle Plugin 9 reforça uma separação que já era saudável: a aplicação Android deve viver em um módulo próprio. Em projetos KMP antigos, era comum aplicar plugin de aplicação Android dentro do mesmo módulo multiplataforma que também carregava a lógica compartilhada. Essa abordagem cria acoplamento entre distribuição Android e biblioteca comum.
Com a nova estrutura, o shared pode aplicar com.android.library, enquanto androidApp aplica com.android.application:
// shared/build.gradle.kts
plugins {
kotlin("multiplatform")
id("com.android.library")
}
kotlin {
androidTarget()
iosArm64()
iosSimulatorArm64()
sourceSets {
commonMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
}
}
}
// androidApp/build.gradle.kts
plugins {
id("com.android.application")
kotlin("android")
}
dependencies {
implementation(project(":shared"))
}
Essa separação facilita CI, assinatura, flavors, Play Store, testes instrumentados e migração incremental. O time Android continua tendo um módulo de app reconhecível, enquanto o time multiplataforma trabalha na biblioteca compartilhada sem carregar toda a configuração de distribuição.
Quando usar sharedLogic e sharedUI
Nem todo projeto KMP compartilha interface. Muitos times brasileiros começam compartilhando apenas domínio, validações, modelos, clientes HTTP e casos de uso. Outros querem compartilhar telas com Compose Multiplatform. A estrutura nova acomoda os dois cenários.
Se parte das plataformas usa UI nativa e parte usa Compose, separar sharedLogic e sharedUI costuma ser melhor:
meu-app/
├── sharedLogic/ # Regras, modelos, networking, storage abstrato
├── sharedUI/ # Componentes Compose compartilhados
├── androidApp/ # Consome sharedLogic + sharedUI
├── iosApp/ # Pode consumir sharedLogic e usar SwiftUI
└── desktopApp/ # Pode consumir sharedLogic + sharedUI
Use sharedLogic para código que todas as plataformas precisam:
- modelos de domínio;
- validações de formulário;
- regras de preço, elegibilidade ou permissões;
- clientes HTTP com Ktor Client;
- serialização;
- interfaces de repositório;
- casos de uso testáveis.
Use sharedUI quando a plataforma realmente vai renderizar com Compose:
- componentes visuais compartilhados;
- design system multiplataforma;
- telas comuns entre Android, desktop e web;
- previews e testes de UI Compose quando fizer sentido.
Em um banco, marketplace ou app de delivery no Brasil, essa divisão permite um caminho gradual: Android pode adotar Compose compartilhado primeiro, iOS pode manter SwiftUI, e a lógica de Pix, carrinho, autenticação ou catálogo continua unificada.
Estrutura com backend Kotlin no mesmo produto
Alguns projetos KMP também têm backend Kotlin. Isso é comum quando a equipe quer compartilhar modelos, validações e contratos entre app e servidor. Nesse caso, uma estrutura com core e server evita misturar código de cliente com API:
produto/
├── core/ # Modelos e validações comuns a client/server
├── shared/ # Código compartilhado entre apps cliente
├── server/ # Ktor ou Spring Boot
└── app/
├── androidApp/
├── iosApp/
└── webApp/
O core deve ser pequeno e conservador. Coloque ali apenas o que realmente precisa existir dos dois lados. Se o módulo vira um depósito de tudo, você troca duplicação por acoplamento.
Para backend, o site já tem guias sobre Ktor, OpenAPI com Ktor e Kotlin server-side. A nova estrutura KMP combina bem com essa linha porque separa contrato, app e servidor desde cedo.
Como migrar de composeApp sem quebrar tudo
Não precisa reescrever o projeto em um fim de semana. A migração segura é incremental:
- Mapeie responsabilidades atuais. Liste o que em
composeAppé lógica compartilhada, UI compartilhada, app Android, desktop ou web. - Crie o módulo
shared. Mova primeiro modelos, casos de uso, clientes HTTP e testes comuns. - Crie
androidApp. Faça o app Android depender desharede mova configurações específicas de aplicação. - Mantenha iOS simples. Garanta que o framework gerado continue sendo consumido pelo projeto Xcode antes de mexer em UI.
- Extraia
sharedUIsó se houver necessidade real. Não crie módulo visual compartilhado se iOS continuará 100% nativo. - Atualize CI por módulo. Rode build e testes por partes para saber onde a quebra aconteceu.
Uma migração mínima pode começar apenas movendo domínio para shared e deixando o restante como está. O ganho imediato é deixar claro o que é biblioteca multiplataforma e o que é aplicação.
Checklist para projetos novos em 2026
Se você está criando um projeto KMP agora, use este checklist:
sharedé biblioteca, não aplicação;androidAppaplicacom.android.application;iosAppfica explícito e documentado para quem usa Xcode;commonMainnão importa API Android, UIKit ou JVM sem abstração;commonTestcobre regras de negócio antes de UI;- dependências ficam próximas do módulo que as usa;
settings.gradle.ktsmostra a arquitetura com nomes claros;- CI roda pelo menos
:shared:allTestse build do app Android; - versões de Kotlin, Compose, AGP e Ktor ficam centralizadas em version catalog quando o projeto crescer.
Para quem ainda está aprendendo, comece pelo guia de Kotlin Multiplatform e pelo tutorial de Kotlin Multiplatform. Para decisão de produto, compare também KMP vs React Native e KMP vs Flutter.
Erros comuns na adoção
O erro mais comum é transformar shared em uma camada “global” onde tudo entra. KMP funciona melhor quando o módulo compartilhado tem limites. Se uma regra só existe no Android, ela deve ficar no Android. Se uma tela só existe no iOS, não force Compose compartilhado.
Outro erro é migrar UI e lógica ao mesmo tempo. Para times que já têm app em produção, normalmente vale compartilhar lógica primeiro. Depois, componentes Compose podem entrar em telas novas, fluxos internos ou áreas onde a paridade visual entre plataformas compensa.
Também evite copiar estruturas de exemplo sem olhar o contexto. Um app com Android e iOS nativo não precisa da mesma organização de um produto com Android, iOS, desktop, web e backend. A nova estrutura não é uma árvore obrigatória; é um conjunto de princípios: responsabilidade clara, entradas separadas e compartilhamento explícito.
Conclusão
A nova estrutura padrão do Kotlin Multiplatform em 2026 é menos sobre nomes de pastas e mais sobre maturidade. Separar shared, androidApp, iosApp e módulos opcionais de UI deixa o projeto mais previsível, especialmente para equipes que precisam evoluir produto, CI, publicação e onboarding ao mesmo tempo.
Para projetos brasileiros, o ganho é direto: dá para adotar KMP sem pedir que todo mundo mude de ferramenta no mesmo dia. Android continua com seu módulo, iOS continua com Xcode quando necessário, backend Kotlin pode compartilhar contratos com cuidado, e a lógica comum fica testável em um lugar claro.
Se você está começando um app novo, já comece com módulos separados. Se está migrando um projeto antigo com composeApp, faça a extração em etapas: lógica primeiro, aplicação Android em módulo próprio, UI compartilhada apenas quando ela realmente pagar a conta.