# Jetpack Best Practices

> USE THIS when writing or reviewing Jetpack Compose / Kotlin code in packages/cds-android or apps/android-app - @Composable APIs, Modifier parameters, CompositionLocal, state hoisting, or naming. Not for React or React Native work.

- Skill: `coinbase/jetpack-best-practices` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add coinbase/jetpack-best-practices`
- Raw SKILL.md: https://api.skillmd.com/api/skills/coinbase/jetpack-best-practices/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: coinbase (https://skillmd.com/u/coinbase)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/coinbase/jetpack-best-practices

---


# Jetpack Compose API guidelines

`references/compose-api-guidelines.md` is the official AOSP Compose API guidelines document,
vendored verbatim. **Read it before writing or reviewing a Compose API.** It is the authority here;
do not invent house style that contradicts it, and do not paraphrase it from memory.

## How the requirement levels apply to us

The document assigns different requirement levels to different audiences. CDS Android is
**"Library development based on Jetpack Compose"** — we publish `@Composable` functions and
supporting types for other teams to consume. Read the MUST/SHOULD/MAY markers for that audience,
not the app-development ones. In practice we hold close to the framework-development bar, because
anything we ship publicly is expensive to change later.

## The rules that come up most in this codebase

These are the ones worth checking on every change. The document explains each in full.

- **Every element accepts and respects a `Modifier` parameter.** It is the first optional
  parameter, defaults to `Modifier`, is applied to the outermost layout node the element emits, and
  is used exactly once. Never accept a `Modifier` and drop it.
- **Composables that emit UI return `Unit`** and are named as PascalCase nouns (`Button`,
  `SlideButton`) — they declare a piece of UI rather than performing an action.
- **Hoist state.** Prefer stateless composables taking a value plus an `onValueChange` callback
  over ones that own their state internally.
- **`CompositionLocal` is for cross-cutting context, not for passing parameters.** In this
  codebase that means theme. A local should have a sensible default and should not be how a caller
  configures a specific component.
- **Parameter order:** required parameters, then `modifier`, then other optional parameters, then a
  trailing `@Composable` content lambda if there is one.
- **Default values belong in the signature**, so callers can see them and override any one of them
  independently.

## Boundary rules specific to CDS Android

Complementary to the guidelines, not covered by them. `packages/cds-android/AGENTS.md` is the full
version:

- `:cds` compiles with Kotlin explicit API mode. Every `public` declaration is a customer promise —
  make it a decision, not a compiler-satisfying reflex, and default to `internal`.
- Read tokens through `CdsTheme.colors` / `CdsTheme.space`; author themes with `cdsTheme { }`.
  `LocalCdsTheme` is public only so custom `Modifier` nodes can read theme outside composition.
- Never widen a declaration's visibility just to make `apps/android-app` compile.

## Related reading

The separate [component API guidelines](https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md)
go deeper on designing individual components (slots, state holders, styling). Not vendored here;
consult it when designing a new component from scratch.

