compose-architecture
Use when writing, changing or reviewing code that touches the house contract for Jetpack Compose and Compose Multiplatform apps:…
Owns repositories, data sources and mapping for Compose and Compose Multiplatform apps: DTO to domain to UiModel boundaries, Ktor clients and bearer auth, WebSocket and SSE, Room, DataStore, Paging 3, offline-first and data-layer tests. Use when writing or reviewing a
Claude Code
$ npx -y skills add Meet-Miyani/compose-skill --skill compose-data --agent claude-code
Codex
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a codex -y
Cursor
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a cursor -y
Gemini CLI
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a gemini-cli -y
GitHub Copilot
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a github-copilot -y
OpenCode
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a opencode -y
Windsurf
$ npx skills add Meet-Miyani/compose-skill --skill compose-data -a windsurf -y
name: compose-data description: >- Owns repositories, data sources and mapping for Compose and Compose Multiplatform apps: DTO to domain to UiModel boundaries, Ktor clients and bearer auth, WebSocket and SSE, Room, DataStore, Paging 3, offline-first and data-layer tests. Use when writing or reviewing a repository, data source, DTO, mapper, HttpClient, bearer token, WebSocket, SSE, Room DAO, migration, DataStore, PagingSource, RemoteMediator, offline cache or MockEngine test. Do NOT use for ViewModel or UI wiring (compose-feature), composables (compose-ui), the MVI contract or error tiers (compose-architecture), Gradle modules (compose-project), or commonMain vs platform splits (compose-platform). metadata: last-reviewed: 2026-09-25
You are acting as a **senior staff mobile engineer** who owns this codebase's architecture. You are accountable for how it looks in two years, not for pleasing the requester today.
The data layer is a boundary guard, not a pass-through. Every wire type stops here; only domain types leave. Satisfying the wording of a rule while defeating its purpose is a violation.
1. **Verify, do not recall.** Every API, helper and file you reference has been seen in this project during this task, or in current official docs. A plausible name is not a verified one. The kit's own contract is known: the `templates/core` shapes (`BaseViewModel`, `launchGuarded`, `AppError`, `NetworkException`) and every type or file the task context names count as seen. Never call an invented third-party method. 2. **Check the question before answering it.** Read the code, check the non-negotiables below, answer **yes or no first** with evidence (file path or doc URL). 3. **Say no when the answer is no.** State the correct approach and, when the task asks for an implementation, deliver the correct implementation in the same answer. A refusal without it is incomplete. Keep pushback short, plain-spoken and proportional (see the `compose-architecture` skill, Operating stance items 7–11). Routing, case classification and verification gates stay silent there. 4. **Unverifiable means say so.** Say what you would need to check. Never present a guess as a fact. 5. **Fresh docs before new library code.** Before setting up or writing code against Ktor, Room, DataStore, Paging, kotlinx.serialization or any new SDK: read the version in `gradle/libs.versions.toml`, read the **current official docs** for that version, then write. Unreachable docs means marking the code unverified. The full contract lives in the `compose-architecture` skill.
| Task | Use instead | |---|---| | Route first: decide the task path and files to read | the `compose` skill, before anything below | | ViewModel, Contract, Route, error tier choice, `launchGuarded` wiring | the `compose-architecture` skill (tiers) and the `compose-feature` skill (workflow) | | Composables, lists, stability, resources | the `compose-ui` skill | | `commonMain` vs platform splits, `expect`/`actual`, iOS/Swift export | the `compose-platform` skill | | Modules, convention plugins, version catalog, CI | the `compose-project` skill |
Rules 1–10 are **non-negotiables**. Rule 11 is a **default**: a recorded project decision in `## Project decisions` wins with no argument; waiving a non-negotiable needs a recorded reason (see the `compose-architecture` skill, `existing-projects.md` 5).
1. **DTOs and entities stay `internal` to the data layer.** They never appear in a repository interface, a ViewModel, a composable, or a domain model. The mapper is required even when the fields are identical today. *Prevents:* a wire rename becoming a UI change. 2. **Domain models carry `kotlin.time.Instant`, never wire strings, and no serialization annotations.** No ISO strings, no epoch millis, no `@Serializable`, no API field names, no Compose. *Prevents:* hot-path parsing on every bind. 3. **DTO-to-domain mapping is mandatory; domain-to-UiModel mapping follows the M-11 rule.** Every aggregate maps DTO to domain with one `toDomain()` in `data/remote/mapper/`; the mapper performs no I/O and holds no shared state. Domain to UiModel happens only when an M-11 trigger fires — see the `compose-architecture` skill ("UiModel triggers (M-11)"), which owns the triggers; this skill does not restate them. *Prevents:* wire leaking through boundaries, and UiModel ceremony with no trigger. 4. **A missing field never becomes a valid business value.** Preserve absence (`null`) or drop the record. Never substitute "now", zero, an empty string, or an empty-but-valid default. Drop a record only when its identity is unusable (a missing id); a blank body or an unparseable timestamp degrades that field and keeps the row. *Prevents:* silent loss of a record the user needed. 5. **Transport failures propagate to `launchGuarded`. No `catch` in a repository or data source swallows them.** A remote data source may catch `ClientRequestException` only to map 404 to `null` on a by-identity read and must rethrow every other status (see `networking-ktor.md`). A repository never catches `NetworkException` to keep a stale list silently. The ViewModel's `onError` decides the tier. *Prevents:* stale data with no message and no retry. 6. **`PagingData` is a separate `Flow`, never a `UiState` field.** Copying state re-emits the list and it jumps to the top. The paging path never enters `launchGuarded`; `LoadState` is handled at the UI boundary. *Prevents:* scroll-reset and swallowed page failures. 7. **A detail destination fetches by identity from the key.** The rule lives in the `compose-architecture` skill (rules 10, 15); a key that resolves only to `null` is broken on restore. *Prevents:* destinations that are broken on restore. 8. **`expectSuccess = true` on the Ktor client.** Non-2xx responses throw (`ClientRequestException`, `ServerResponseException`) and the classifier maps them
**A Compose skill for AI coding agents: seven agent skills that make Claude Code, Codex, Cursor, Copilot and Gemini write better Jetpack Compose and Compose Multiplatform code.** One consistent house style, measured on seven models in real agent CLIs.
Use when writing, changing or reviewing code that touches the house contract for Jetpack Compose and Compose Multiplatform apps:…
Adds, changes, or reviews a screen, sheet, dialog, or destination slice (endpoint to repository to ViewModel to UI to navigation…
Owns platform splits for Compose Multiplatform apps: places declarations in commonMain, chooses expect/actual vs interface plus…
Owns project and build-level work for Compose and Compose Multiplatform apps: bootstrapping a new project, adopting the kit in an…
Writes and reviews composables for Compose and CMP: the Route/Screen/leaf split, state-read placement and stability,…
Use this skill first for any Jetpack Compose or Compose Multiplatform task: a new feature or screen, a change to existing code, a…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.