{"id":50709199,"url":"https://github.com/sorunokoe/swiftui-compose-skill","last_synced_at":"2026-06-09T14:01:39.760Z","repository":{"id":354426987,"uuid":"1223571000","full_name":"sorunokoe/swiftui-compose-skill","owner":"sorunokoe","description":"AI coding skill for Compose Multiplatform ↔ SwiftUI bidirectional interop. UIViewControllerRepresentable, coordinator pattern, state sharing.","archived":false,"fork":false,"pushed_at":"2026-04-28T15:20:23.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T15:23:52.394Z","etag":null,"topics":["ai-skill","compose-multiplatform","ios","kotlin-multiplatform","swiftui","uiviewcontrollerrepresentable"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sorunokoe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-28T12:57:15.000Z","updated_at":"2026-04-28T15:17:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sorunokoe/swiftui-compose-skill","commit_stats":null,"previous_names":["sorunokoe/swiftui-compose-skill"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/sorunokoe/swiftui-compose-skill","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorunokoe%2Fswiftui-compose-skill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorunokoe%2Fswiftui-compose-skill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorunokoe%2Fswiftui-compose-skill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorunokoe%2Fswiftui-compose-skill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sorunokoe","download_url":"https://codeload.github.com/sorunokoe/swiftui-compose-skill/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorunokoe%2Fswiftui-compose-skill/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34110012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-skill","compose-multiplatform","ios","kotlin-multiplatform","swiftui","uiviewcontrollerrepresentable"],"created_at":"2026-06-09T14:01:38.612Z","updated_at":"2026-06-09T14:01:39.746Z","avatar_url":"https://github.com/sorunokoe.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cpre align=\"center\"\u003e\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n┃                                                     ┃\n┃   ◆  swiftui · compose             AI Coding Skill  ┃\n┃   ─────────────────────────────────────────────     ┃\n┃                                                     ┃\n┃   Compose  ◄────────────────────────────► SwiftUI   ┃\n┃                                                     ┃\n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\u003c/pre\u003e\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Compose Multiplatform](https://img.shields.io/badge/CMP-1.8+-4CAF50)](https://www.jetbrains.com/compose-multiplatform/)\n[![Swift](https://img.shields.io/badge/Swift-5.9+-FA7343?logo=swift\u0026logoColor=white)](https://swift.org)\n[![iOS stable](https://img.shields.io/badge/iOS-stable%20since%201.8-blue)](https://www.jetbrains.com/compose-multiplatform/)\n[![Maintained by skills-evolution](https://img.shields.io/badge/maintained%20by-skills--evolution-0ea5e9)](https://github.com/sorunokoe/skills-evolution)\n\u003cbr\u003e\n[![Works with Claude](https://img.shields.io/badge/Works%20with-Claude-9370DB)](https://claude.ai)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991?logo=openai\u0026logoColor=white)](https://openai.com/codex)\n[![Works with GitHub Copilot](https://img.shields.io/badge/Works%20with-GitHub%20Copilot-2ea44f?logo=github)](https://github.com/features/copilot)\n[![Works with Cursor](https://img.shields.io/badge/Works%20with-Cursor-000000)](https://cursor.com)\n[![Works with Gemini](https://img.shields.io/badge/Works%20with-Gemini-4285F4?logo=google\u0026logoColor=white)](https://gemini.google.com)\n\u003c!-- skill-evolution:badge:begin --\u003e\n[![Skill evolved 2×](https://img.shields.io/badge/evolved-2%C3%97_evolving-green?style=flat-square\u0026logo=dna\u0026logoColor=white)](https://github.com/sorunokoe/swiftui-compose-skill/pulls?q=is%3Apr+is%3Amerged)\n\u003c!-- skill-evolution:badge:end --\u003e\n\n**An AI coding skill for bidirectional interop between  \nCompose Multiplatform and SwiftUI.**\n\n[What it covers](#what-this-skill-covers) · [Files](#files) · [Core principle](#core-principle) · [Quick start](#quick-start) · [Key rules](#key-rules-summary) · [Docs](#official-documentation) · [Automated maintenance](#automated-maintenance)\n\n\u003c/div\u003e\n\n---\n\n## What This Skill Covers\n\n| | |\n|---|---|\n| **Compose in SwiftUI** | `ComposeUIViewController` + `UIViewControllerRepresentable` wiring |\n| **State bridging** | `makeCoordinator()`, push and bidirectional patterns, Kotlin `mutableStateOf` |\n| **SwiftUI in Compose** | `UIKitView`, `UIKitViewController`, `UIHostingController` |\n| **UIKit embedding** | Maps, text fields, camera, pickers via `UIKitView` |\n| **Teardown** | `dismantleUIViewController`, `AsyncStream.onTermination` |\n| **Touch routing** | `UIKitInteropProperties` cooperative vs non-cooperative gestures |\n\n\u003e 🔗 Bridging KMP data and logic into Swift? See the companion [**swift-kmp**](https://github.com/sorunokoe/swift-kmp-skill) skill.\n\n---\n\n## Core Principle\n\n\u003e **Create the Compose `UIViewController` once, then update state through methods —  \n\u003e never recreate it.**\n\n```\n❌ Anti-pattern: .id(someState) on a Compose view\n   → tears down and recreates UIViewController on every state change\n   → visual glitches, wasted memory, Compose lifecycle restart\n\n✅ Correct: makeCoordinator() holds the UIViewController reference (created once)\n           updateUIViewController() calls context.coordinator.update*(newState)\n```\n\nApple's documentation confirms the intended lifecycle:\n\u003e *\"SwiftUI calls `makeCoordinator()` before calling `makeUIViewController(context:)`.\n\u003e The system provides your coordinator either directly or as part of a context structure\n\u003e when calling the other methods of your representable instance.\"*\n\n---\n\n## Files\n\n| File | Load when | Tokens |\n|------|-----------|--------|\n| [`SKILL.md`](SKILL.md) | **Always first** — anti-patterns, quick reference, review checklist | ~1.5k |\n| [`references/compose-in-swiftui.md`](references/compose-in-swiftui.md) | Embedding Compose in SwiftUI; coordinator wiring; `ComposeUIViewController` Kotlin setup | ~2k |\n| [`references/swiftui-in-compose.md`](references/swiftui-in-compose.md) | Embedding SwiftUI/UIKit inside Compose; `UIKitViewController`; `UIKitView` | ~2k |\n| [`references/state-sharing.md`](references/state-sharing.md) | Bidirectional state; all 3 patterns; `StateFlow` → `AsyncStream`; `dismantleUIViewController` | ~2.5k |\n\n\u003e **Token budget:** `SKILL.md` (~1.5k tokens) covers anti-patterns and routing. Load one reference only when you need the detailed API for that topic.\n\n---\n\n## Quick Start\n\n### 1. Install\n\n```bash\n# Clone into the canonical skill location:\ngit clone https://github.com/sorunokoe/swiftui-compose-skill.git \\\n  /path/to/your-project/.github/skills/swiftui-compose\n\n# Optional: detach from upstream git history\nrm -rf /path/to/your-project/.github/skills/swiftui-compose/.git\n```\n\n\u003e **Why `.github/skills/swiftui-compose/`?** This is the path GitHub Copilot, Cursor, and\n\u003e [skills-evolution](https://github.com/sorunokoe/skills-evolution) discover skills from.\n\n### 2. Use with GitHub Copilot\n\n```\n@swiftui-compose Help me embed a Compose map screen in my SwiftUI app with filter state\n```\n\n### 3. Use with Claude / any AI agent\n\n```\nLoad swiftui-compose/SKILL.md, then swiftui-compose/references/state-sharing.md.\n\nI need to embed a Kotlin Compose map screen in SwiftUI. The SwiftUI side has\n@State var filters: [MapFilter] that need to flow into Compose when they change.\nCompose calls back via onMarkerClick. Implement the full coordinator pattern.\n```\n\n---\n\n---\n\n## Key Rules (summary)\n\n- ❌ **`.id(someState)` on a Compose view** — recreates the entire lifecycle\n- ❌ **Calling the `build:` closure inside `updateUIViewController`** — creates a new Compose lifecycle on every update\n- ❌ **Storing a `@State` copy of the Kotlin holder** — use `makeCoordinator()` for a stable reference\n- ✅ **`CADisableMinimumFrameDurationOnPhone = YES` in `Info.plist`** — required for Compose on iOS\n- ✅ **`context.coordinator.update*(…)` in `updateUIViewController`** — correct way to push SwiftUI state to Compose\n- ✅ **`dismantleUIViewController` implemented** when coordinator owns subscriptions or tasks\n\nFull rules and review checklist in [`SKILL.md`](SKILL.md).\n\n---\n\n## The Three State Patterns\n\n| When | Pattern |\n|------|---------|\n| Compose owns all state; SwiftUI just positions | **Unidirectional** — simple `UIViewControllerRepresentable`, empty `updateUIViewController` |\n| SwiftUI state needs to flow into Compose | **Push** — `makeCoordinator()` + `context.coordinator.update*()` in `updateUIViewController` |\n| State flows both ways + Compose fires Swift callbacks | **Bidirectional** — coordinator holds holder, callbacks provided at build time |\n\nFull patterns with code in [`references/state-sharing.md`](references/state-sharing.md).\n\n---\n\n## Official Documentation\n\n| Topic | Link |\n|-------|------|\n| Compose Multiplatform ↔ SwiftUI | [kotlinlang.org →](https://kotlinlang.org/docs/multiplatform/compose-swiftui-integration.html) |\n| Compose Multiplatform ↔ UIKit | [kotlinlang.org →](https://kotlinlang.org/docs/multiplatform/compose-uikit-integration.html) |\n| Apple `UIViewControllerRepresentable` | [developer.apple.com →](https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable) |\n| Apple `makeCoordinator()` | [developer.apple.com →](https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable/makecoordinator()-9vwm8) |\n| Apple `dismantleUIViewController` | [developer.apple.com →](https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable/dismantleuiviewcontroller(_:coordinator:)) |\n| Apple `UIHostingController` | [developer.apple.com →](https://developer.apple.com/documentation/swiftui/uihostingcontroller) |\n| Compose Multiplatform interop examples | [github.com/JetBrains →](https://github.com/JetBrains/compose-multiplatform/tree/master/examples/interop) |\n\n---\n\n## Requirements\n\n| | Version |\n|---|---|\n| Compose Multiplatform | 1.8+ (iOS **stable** since 1.8.0, May 2025) |\n| Kotlin | 2.1+ |\n| Swift | 5.9+ |\n| iOS | 15.0+ |\n\n\u003e Compose Multiplatform iOS is **stable** as of version 1.8.0 (May 2025). CMP 1.8+ requires Kotlin 2.1+.\n\n---\n\n## Related Skills\n\n\u003e 🔗 **Bridging Kotlin data and logic into your Swift feature modules?**  \n\u003e Check out [**swift-kmp**](https://github.com/sorunokoe/swift-kmp-skill) — the companion skill covering the bridge layer architecture, interactors, `SkieSwiftFlow` → `AsyncStream` wrapping, type mapping, and `KotlinThrowable` containment.\n\n---\n\n## Automated Maintenance\n\nThis skill is governed by [**skills-evolution**](https://github.com/sorunokoe/skills-evolution) — AI skill governance that keeps guidance files accurate and up to date automatically.\n\n### gh-aw (recommended)\n\n```bash\n# PR review — AI feedback on every PR touching SKILL.md or references/**\ngh aw add sorunokoe/skills-evolution/workflows/oss-skill-pr-check.md@latest\n\n# Monthly update — version checks, AI content patches, opens PR\ngh aw add sorunokoe/skills-evolution/workflows/oss-skill-update.md@latest\n\ngh aw compile\n```\n\n### GitHub Actions\n\n\u003cdetails\u003e\n\u003csummary\u003eMonthly skill health workflow\u003c/summary\u003e\n\n[`.github/workflows/skill-health.yml`](.github/workflows/skill-health.yml) — runs monthly and on demand:\n\n- **Structural audit** — broken local links, missing frontmatter fields\n- **AI content update** — checks `SKILL.md` + `references/*.md` against the latest `compose-multiplatform` release; proposes conservative patches via GitHub Models\n\n```yaml\n# .github/workflows/skill-health.yml\nname: Skill Health\non:\n  schedule:\n    - cron: \"0 3 1 * *\"\n  workflow_dispatch:\npermissions:\n  contents: write\n  pull-requests: write\n  models: read\njobs:\n  health:\n    uses: sorunokoe/skills-evolution/.github/workflows/oss-skill-health.yml@latest\n    with:\n      enable_ai_skill_update: true\n    secrets:\n      token: ${{ secrets.GITHUB_TOKEN }}\n```\n\u003c/details\u003e\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for how to improve patterns or add new reference files.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsorunokoe%2Fswiftui-compose-skill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsorunokoe%2Fswiftui-compose-skill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsorunokoe%2Fswiftui-compose-skill/lists"}