agentsclimarketplace

Coil compose

Skill ShinKev/kmp-skill-library/ui/coil-compose

19 Claude AI skills for Kotlin Multiplatform (KMP) & Compose Multiplatform (CMP): architecture, networking, UI, testing, migration & build tooling for Android and iOS.

Install
npx -y skills add ShinKev/kmp-skill-library --skill coil-compose

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expert guidance on using Coil 3 for image loading in Compose Multiplatform. Use when asked about loading images from URLs, handling image states, or optimizing image performance in CMP (Android + iOS).

SKILL.md

3.9 KB, as published. Nobody here has run it

Coil 3 for Compose Multiplatform

Instructions

Use Coil 3 (coil3) for image loading in CMP. Coil 3 is fully KMP-compatible — it works in commonMain composables without LocalContext.current.

Migration note: Coil 2.x (coil package) required LocalContext.current in ImageRequest.Builder. Coil 3 (coil3 package) removes this requirement. If you see LocalContext.current in image loading code, update to Coil 3.

Setup (libs.versions.toml)

[versions]
coil = "3.1.0"

[libraries]
coil-compose  = { group = "io.coil-kt.coil3", name = "coil-compose",        version.ref = "coil" }
coil-network  = { group = "io.coil-kt.coil3", name = "coil-network-ktor",   version.ref = "coil" }
// shared/build.gradle.kts
commonMain.dependencies {
    implementation(libs.coil.compose)
    implementation(libs.coil.network) // Uses Ktor under the hood
}

1. Primary Composable: AsyncImage

Use AsyncImage for most cases. No LocalContext needed in commonMain:

// coil3 — works in commonMain
AsyncImage(
    model = ImageRequest.Builder()
        .data("https://example.com/image.jpg")
        .crossfade(true)
        .build(),
    contentDescription = "Profile picture",
    contentScale = ContentScale.Crop,
    placeholder = painterResource(Res.drawable.placeholder),
    error = painterResource(Res.drawable.error_image),
    modifier = Modifier
        .size(64.dp)
        .clip(CircleShape)
)

2. Low-Level Control: rememberAsyncImagePainter

Use only when you need a Painter (e.g., for Canvas or Icon).

Warning: rememberAsyncImagePainter does not auto-detect the display size and loads the image at its original dimensions by default. Always set an explicit size or prefer AsyncImage.

val painter = rememberAsyncImagePainter(
    model = ImageRequest.Builder()
        .data("https://example.com/image.jpg")
        .size(Size.ORIGINAL)
        .build()
)

3. Custom State Slots: SubcomposeAsyncImage

Use when you need custom loading/error UI with access to the AsyncImagePainter.State.

Caution: Subcomposition is slower than regular composition. Avoid in LazyColumn or LazyRow.

SubcomposeAsyncImage(
    model = "https://example.com/image.jpg",
    contentDescription = null,
    loading = { CircularProgressIndicator(modifier = Modifier.size(24.dp)) },
    error = { Icon(Icons.Default.BrokenImage, contentDescription = null) }
)

4. Singleton ImageLoader via Koin

Provide a single ImageLoader instance for the whole app to share cache:

// commonMain Koin module
val imageModule = module {
    single {
        ImageLoader.Builder()
            .components { add(KtorNetworkFetcherFactory(get())) } // reuse app HttpClient
            .crossfade(true)
            .build()
    }
}

5. Performance & Best Practices

  • Singleton: Always share one ImageLoader — it owns the disk/memory cache.
  • Crossfade: Enable crossfade(true) for smooth placeholder → image transitions.
  • Sizing: Set contentScale appropriately — Coil 3 uses it to avoid loading images larger than needed.
  • Lists: Prefer AsyncImage over SubcomposeAsyncImage inside LazyColumn/LazyRow.
  • Transformations: Apply via ImageRequest.Builder().transformations(CircleCropTransformation()).

6. Checklist

  • Using coil3 package (not coil — that's Coil 2)
  • No LocalContext.current in commonMain image loading code
  • ImageLoader provided as a Koin singleton
  • AsyncImage preferred over other variants
  • Meaningful contentDescription on all images (or null for decorative)
  • crossfade(true) enabled for better UX
  • SubcomposeAsyncImage avoided in lazy lists

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.