[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71FQFKRVZP54AFAKN428YB9":3,"skill-same:01M71FQFKRVZP54AFAKN428YB9":70},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":6,"ownerHtmlUrl":52,"ownerBlogUrl":53,"ownerDescription":54,"updatedAt":55,"install":56,"resources":69},"01M71FQFKRVZP54AFAKN428YB9","kotlin-tooling-cocoapods-spm-migration",null,"Migrate KMP projects from CocoaPods (kotlin(\"native.cocoapods\")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.","iDorgham\u002FWorkspace-Factory","iDorgham","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F136521493?v=4","01M6CNGBDAHE4ARW3YJEF4X2FD","Dorgham","01M71E8H3CXZ7DJX59MTM9JEB2",1,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002F.ai\u002Fskills\u002Fofficial_kotlin_kotlin_tooling_cocoapods_spm_migration\u002Fskill.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"spm","kotlin tooling cocoapods spm migration","kotlin","cocoapods","tooling","migration","kotlin tooling","package","swift","manager","transforms","native","jetbrains","imports","xcode","migrate","project","dsl","package manager","projects","2026-11-10 10:12:30",false,"---\nname: kotlin-tooling-cocoapods-spm-migration\ndescription: Migrate KMP projects from CocoaPods (kotlin(\"native.cocoapods\")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.\nlicense: Apache-2.0\nmetadata:\n  author: JetBrains\n  version: \"1.0.0\"\n---\n\n# CocoaPods to SwiftPM Migration for KMP\n\nMigrate Kotlin Multiplatform projects from `kotlin(\"native.cocoapods\")` to `swiftPMDependencies {}` DSL.\n\n## Requirements\n\n- **Kotlin**: Version with Swift Import support (e.g., 2.4.0-Beta1 or later)\n- **Xcode**: 16.4 or 26.0+\n- **iOS Deployment Target**: 16.0+ recommended\n\n## Migration Overview\n\n**IMPORTANT**: Keep the `cocoapods {}` block and plugin active until Phase 6. The migration adds `swiftPMDependencies {}` alongside the existing CocoaPods setup first, reconfigures Xcode, and only then removes CocoaPods.\n\n| Phase | Action |\n|-------|--------|\n| 1 | Analyze existing CocoaPods configuration |\n| 2 | Update Gradle configuration (repos, Kotlin version) |\n| 3 | Add `swiftPMDependencies {}` alongside existing `cocoapods {}` |\n| 4 | Transform Kotlin imports |\n| 5 | Reconfigure iOS project and deintegrate CocoaPods |\n| 6 | Remove CocoaPods plugin from Gradle |\n| 7 | Verify Gradle build and Xcode project build |\n| 8 | Write MIGRATION_REPORT.md |\n\n---\n\n## Phase 1: Pre-Migration Analysis\n\n### 1.0 Verify the project builds\n\nBefore starting migration, identify the module to migrate and confirm it compiles successfully.\n\n1. **Find the module that uses CocoaPods** — look for `build.gradle.kts` files containing `cocoapods`:\n   ```bash\n   grep -rl \"cocoapods\" --include=\"build.gradle.kts\" .\n   ```\n   Extract the module name from the path (e.g., `.\u002Fshared\u002Fbuild.gradle.kts` → module name is `shared`). Note: multiple modules may use CocoaPods — record all of them. Typically only the module that produces the framework linked into the iOS app needs `swiftPMDependencies`; the others only need CocoaPods removed (Phase 6).\n\n2. **Compile Kotlin code** — run the Kotlin compilation task for that module to verify the Kotlin source compiles:\n   ```bash\n   .\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64\n   ```\n   Replace `moduleName` with the directory name of the module (e.g., `:shared:compileKotlinIosSimulatorArm64`). This is faster than a full `build` (which also runs release linkage) and sufficient to verify Kotlin code correctness.\n\n3. **Build the iOS app (optional)** — try to locate the Xcode project and build it to confirm the full app compiles:\n   ```bash\n   # Find the Xcode project\n   find . -name \"*.xcworkspace\" -not -path \"*\u002FPods\u002F*\" -maxdepth 2\n   # Build (replace scheme name with the actual app scheme)\n   cd \u002Fpath\u002Fto\u002FiosApp\n   xcodebuild -workspace *.xcworkspace -scheme \"\u003CAppScheme>\" -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64\n   ```\n   If the user wants to skip the Xcode build or no Xcode project is found, proceed without it — the Kotlin compilation from step 2 is sufficient to continue.\n\n4. **If the Kotlin compilation fails**, ask the user to either:\n   - Provide the correct Gradle command to verify the module builds, or\n   - Confirm the module is in a working state and it's safe to proceed\n\n   If the user confirms without providing a build command, **record that the pre-migration build could not be verified** and warn about this at the end of migration (Phase 7).\n\n### 1.0a Confirm Kotlin version with Swift Import support\n\nAsk the user:\n\n> Does your project already use a Kotlin version with Swift Import support (swiftPMDependencies DSL)?\n\n**If yes** → read their current Kotlin version from `gradle\u002Flibs.versions.toml` (or `build.gradle.kts`), record it, and skip Phase 2.2 (no version change needed).\n\n**If no** → ask:\n\n> Please provide the Kotlin version to use (e.g., \"2.4.0\", \"2.4.0-Beta1\", \"2.4.0-dev-123\").\n\nRecord the user-provided version. Then ask:\n\n> Does this Kotlin version require a custom Maven repository (e.g., JetBrains dev repo)?\n\n- **Yes** → ask for the repo URL (suggest `https:\u002F\u002Fpackages.jetbrains.team\u002Fmaven\u002Fp\u002Fkt\u002Fdev` as default). Phase 2.1 will add it.\n- **No** → Phase 2.1 is skipped (no custom repo needed).\n\nFinally, check the project's current Kotlin version. Compare **major.minor** against the target. If it differs significantly (e.g., `2.1.0` → `2.4.0`), warn: \"⚠️ Kotlin version jump — upgrading across minor versions can introduce breaking changes unrelated to this migration. Recommended: update first, verify it builds, then re-run.\" If the user confirms despite the mismatch, proceed.\n\n### 1.1 Check for deprecated CocoaPods workaround property\n\nSearch `gradle.properties` for the deprecated property:\n\n```properties\nkotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true\n```\n\nThis property was a workaround (see [KT-64096](https:\u002F\u002Fyoutrack.jetbrains.com\u002Fissue\u002FKT-64096)) for projects using `embedAndSign` alongside CocoaPods dependencies. It suppresses an error about unsupported configurations that can cause runtime crashes or symbol duplication. After migrating to SwiftPM import, this property is no longer needed and **must be removed** in Phase 6. Record its presence if found.\n\n### 1.2 Check for EmbedAndSign disablers\n\nSearch all `build.gradle.kts` files for code that disables `EmbedAndSign` tasks (e.g., `TaskGraph.whenReady` filters, `tasks.matching` blocks). This is a CocoaPods-era workaround that **breaks the migration** because `integrateEmbedAndSign` (needed in Phase 5) gets disabled too. Record any such code — it **must be removed** in Phase 6, and may need to be removed earlier. See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"`integrateEmbedAndSign` Skipped\" for patterns.\n\n### 1.3 Check for third-party KMP libraries with bundled cinterop klibs\n\nSome KMP libraries ship pre-built cinterop klibs with `cocoapods.*` package namespaces. After migration, the swiftPMDependencies cinterop generator detects these existing bindings and **skips generating new bindings** for those Clang modules to avoid duplicates. This means `cocoapods.*` imports for those modules must be **kept as-is** — they resolve to the third-party library's bundled klib, not to actual CocoaPods.\n\n**Known libraries with bundled `cocoapods.*` klibs:**\n\n| Library | Maven artifact | Bundled klib namespace | Classes provided |\n|---------|---------------|----------------------|-----------------|\n| [KMPNotifier](https:\u002F\u002Fgithub.com\u002Fmirzemehdi\u002FKMPNotifier) | `io.github.mirzemehdi:kmpnotifier` | `cocoapods.FirebaseMessaging` | `FIRMessaging`, `FIRMessagingAPNSTokenType`, etc. |\n\n**How to detect:** Search Gradle dependency declarations for known libraries, then cross-reference their bundled namespaces against the `import cocoapods.*` statements found in step 4. Mark any matches — these imports will NOT be transformed in Phase 4.\n\nIf unsure whether a third-party KMP library bundles cinterop klibs, check if it has a `linkOnly = true` pod dependency in the project — this is a strong indicator that the library provides its own klib for those classes.\n\nTo inspect klib contents and verify bundled bindings, see troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Third-Party KMP Libraries with Bundled Klibs\".\n\n**Find and record:**\n\n1. **CocoaPods configuration** - Search for `cocoapods` in `build.gradle.kts` files\n2. **Pod dependencies** - Extract pod names, versions from `cocoapods {}` blocks\n3. **Framework configuration** - Record `baseName`, `isStatic`, deployment target from `cocoapods.framework {}`\n4. **linkOnly pods** - Record pods declared with `linkOnly = true`. These pods provide native linking only — cinterop bindings come from a KMP wrapper library (e.g., `dev.gitlive:firebase-*`). See common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for implications.\n5. **Kotlin imports** - Find all `import cocoapods.*` statements. Cross-reference with step 1.3 to identify which imports come from bundled klibs (and must be preserved) vs. which come from direct pod cinterop (and must be transformed).\n6. **Map pods to SPM** - See common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`)\n7. **Locate iOS project directory** - Find the directory containing `Podfile` and `.xcworkspace`:\n   ```bash\n   find . -name \"Podfile\" -type f\n   ```\n   Record this path (e.g., `iosApp\u002F`, `ios\u002F`, or project root) - needed for Phase 5\n8. **Check for non-KMP CocoaPods** - Determine if the project uses CocoaPods for dependencies other than KMP. This affects cleanup strategy in Phase 5.\n9. **Cross-reference Podfile against `cocoapods {}` block** - Parse the `Podfile` and compare its pod entries with the pods declared in the Gradle `cocoapods {}` block. Record any dependencies that exist in the `Podfile` but are **not** listed in `cocoapods {}`. These Podfile-only dependencies still linked into the app via CocoaPods and must be migrated to `swiftPMDependencies` — dropping them silently causes obscure linkage errors at runtime.\n10. **Check Xcode build phases** - Open the `.xcodeproj`'s `project.pbxproj` and search for the Gradle build phase script. Check if `embedAndSignAppleFrameworkForXcode` is present but **commented out** (prefixed with `#`). If commented out, it must be uncommented during Phase 5 — the `integrateEmbedAndSign` task may or may not handle this automatically.\n11. **Check for existing Crashlytics dSYM upload script** - If using FirebaseCrashlytics, search `project.pbxproj` for a dSYM upload shell script phase. Record its current path (CocoaPods-era scripts reference `${PODS_ROOT}\u002FFirebaseCrashlytics\u002Fupload-symbols`). This must be updated to the SPM path in Phase 5.\n12. **Identify CocoaPods-related extras in build scripts** - Search all `build.gradle.kts` files for CocoaPods workarounds beyond the standard `cocoapods {}` block (custom tasks hooking into `podInstall`, `Pods.xcodeproj` patching, podspec metadata, `extraSpecAttributes`, `noPodspec()`, etc.). See cocoapods_extras_patterns.md (`references\u002Fcocoapods_extras_patterns.md`) for the full pattern list. Record all findings — these will be handled in Phase 6.\n\n---\n\n## Phase 2: Gradle Configuration\n\n**Important scope note:** Do NOT upgrade the Gradle wrapper version, update KSP, or update any other dependencies during this migration. Those are separate concerns and out of scope. Only change what is listed below.\n\n### 2.1 Add custom Maven repository (if needed)\n\n**Skip this step** if the user indicated in Phase 1.0a that their Kotlin version does not require a custom Maven repository (i.e., it is an official release, Beta, or RC available from Maven Central).\n\nFor dev\u002Fcustom builds, add the custom Maven repository (URL from Phase 1.0a) to `settings.gradle.kts`:\n\n```kotlin\npluginManagement {\n    repositories {\n        gradlePluginPortal()\n        mavenCentral()\n        maven(\"\u003Ccustom-repo-url>\")  \u002F\u002F ADD\n    }\n}\n\ndependencyResolutionManagement {\n    repositories {\n        mavenCentral()\n        maven(\"\u003Ccustom-repo-url>\")  \u002F\u002F ADD\n    }\n}\n```\n\n### 2.2 Update Kotlin version\n\n**Skip this step** if the user's project already uses a Kotlin version with Swift Import support (recorded in Phase 1.0a).\n\nUpdate to the version recorded in Phase 1.0a:\n\n```toml\n# gradle\u002Flibs.versions.toml\n[versions]\nkotlin = \"\u003Ckotlin-version>\"\n```\n\n### 2.3 Add buildscript constraint (if swiftPMDependencies not recognized)\n\n```kotlin\n\u002F\u002F root build.gradle.kts\nbuildscript {\n    dependencies.constraints {\n        \"classpath\"(\"org.jetbrains.kotlin:kotlin-gradle-plugin:\u003Ckotlin-version>!!\")\n    }\n}\n```\n\nReplace `\u003Ckotlin-version>` with the version recorded in Phase 1.0a. The `!!` suffix forces strict version resolution, ensuring no other dependency pulls in a different Kotlin Gradle plugin version.\n\n---\n\n## Phase 3: Add swiftPMDependencies (Keep CocoaPods)\n\n**Do NOT remove the `cocoapods {}` block or `kotlin(\"native.cocoapods\")` plugin yet.** Add `swiftPMDependencies {}` alongside the existing CocoaPods configuration.\n\n### 3.1 Add group property\n\n```kotlin\ngroup = \"org.example.myproject\"  \u002F\u002F Required for import namespace\n```\n\n**Compose Resources warning:** If the project uses Compose Multiplatform resources (`org.jetbrains.compose` plugin or `compose.resources`), the `group` property is also used as the namespace for generated resource accessors (e.g., `Res.string.*`, `Res.drawable.*`). If `group` already exists in `build.gradle.kts`, do **not** change it. If you are adding `group` for the first time, warn the user that existing Compose resource accessor call sites throughout the project will change namespace and may need updating.\n\n### 3.2 Add swiftPMDependencies block alongside cocoapods\n\nFor each pod dependency, add the equivalent SwiftPM package declaration. Use common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) to map each pod to its SPM package URL, product name, and `importedClangModules`.\n\n**Version preservation:** Match the version constraint semantics from the `cocoapods {}` block. Using `from()` for an exact CocoaPods version can resolve to a newer version that breaks cinterop APIs (removed symbols, changed signatures).\n\n| CocoaPods version spec | SPM equivalent | Example |\n|------------------------|---------------|---------|\n| `version = \"1.2.3\"` (exact) | `exact(\"1.2.3\")` | `pod(\"GoogleMaps\") { version = \"10.3.0\" }` → `exact(\"10.3.0\")` |\n| `version = \"~> 1.2\"` (optimistic) | `from(\"1.2.0\")` | `pod(\"FirebaseAuth\") { version = \"~> 12.5\" }` → `from(\"12.5.0\")` |\n| No version specified | `exact()` with latest, or ask user | Ask the user which version to pin |\n\n**Key concepts:** `products` = SPM product names (controls linking). `importedClangModules` = Clang module names for cinterop bindings (only when `discoverModulesImplicitly = false`). `discoverModulesImplicitly` defaults to `true` (bindings for all Clang modules); set `false` when transitive C\u002FC++ modules fail cinterop (Firebase, gRPC), then list needed modules explicitly.\n\n**Important:** SPM product names and Clang module names don't always match. Always consult common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for correct values.\n\n**Podfile-only dependencies:** If Phase 1 step 9 identified dependencies that exist in the `Podfile` but not in the Gradle `cocoapods {}` block, these must also be added to `swiftPMDependencies` as `products` entries. Even though the KMP module didn't declare them, they were linked into the app by CocoaPods and may be required for the app to build. Look up each Podfile-only pod's SPM package URL and add it as a `swiftPackage()` with at least its `products`. If any of these pods were used via cinterop (check for `import cocoapods.*` statements referencing them), also add `importedClangModules`.\n\n**Do not mix the same library suite across CocoaPods and SPM.** Libraries that share a common repository (e.g., all Firebase products) share transitive dependencies. Having some products linked via CocoaPods and others via SPM causes duplicate\u002Fconflicting symbols and dyld crashes at runtime. When migrating such a suite, move **all** pods from that suite to SPM at once — including Swift-only pods that Kotlin doesn't use directly. Add Swift-only pods as `products` entries (no `importedClangModules` needed). After adding new products, re-run `integrateLinkagePackage` to regenerate the linkage Swift package.\n\n```kotlin\nkotlin {\n    \u002F\u002F Keep existing targets\n    iosArm64()\n    iosSimulatorArm64()\n    iosX64()\n\n    swiftPMDependencies {\n        iosDeploymentVersion.set(\"16.0\")\n\n        \u002F\u002F If using KMP IntelliJ plugin, specify the .xcodeproj path:\n        \u002F\u002F xcodeProjectPathForKmpIJPlugin.set(\n        \u002F\u002F     layout.projectDirectory.file(\"..\u002FiosApp\u002FiosApp.xcodeproj\")\n        \u002F\u002F )\n\n        swiftPackage(\n            url = url(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo.git\"),\n            version = from(\"1.0.0\"),\n            products = listOf(product(\"ProductName\")),\n        )\n    }\n\n    cocoapods {\n        \u002F\u002F ... keep existing cocoapods block for now\n    }\n}\n```\n\n### 3.3 Move framework configuration out of cocoapods block\n\nIf the `cocoapods` block contains a `framework {}` configuration, move it to the `binaries` API on each target. **`isStatic = true` is recommended** — dynamic frameworks have known edge cases with SwiftPM import that can cause linker errors, dyld crashes, or duplicate class warnings:\n\n```kotlin\nlistOf(iosArm64(), iosSimulatorArm64(), iosX64()).forEach { iosTarget ->\n    iosTarget.binaries.framework { baseName = \"Shared\"; isStatic = true }\n}\n```\n\nIf the `cocoapods.framework {}` block contained `export(project(...))` or `transitiveExport = true`, preserve these in the new `binaries.framework {}` block — they are essential for multi-module projects where the framework exports child modules.\n\n### 3.4 Handle dev.gitlive\u002Ffirebase-kotlin-sdk and similar CocoaPods-era KMP wrappers\n\nIf the project uses `dev.gitlive:firebase-*` or similar KMP wrapper libraries, two additional steps are required:\n\n**A. Switch to `isStatic = true`** — dynamic frameworks + Firebase SPM = runtime `dyld` crash. After switching: re-run `integrateLinkagePackage`, remove any \"Embed Frameworks\" copy phase, move linker flags to `OTHER_LDFLAGS`.\n\n**B. Add framework search paths** — add conditional `-F` linkerOpts in `build.gradle.kts` and matching `FRAMEWORK_SEARCH_PATHS` in the Xcode project.\n\nSee common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) § dev.gitlive and troubleshooting.md (`references\u002Ftroubleshooting.md`) for code snippets and the full product list.\n\n### 3.5 Add opt-in for cinterop API\n\n```kotlin\nkotlin.compilerOptions {\n    optIn.add(\"kotlinx.cinterop.ExperimentalForeignApi\")\n}\n```\n\nFor full DSL reference, see dsl_reference.md (`references\u002Fdsl_reference.md`).\n\n---\n\n## Phase 4: Kotlin Source Updates\n\n### Import Namespace Formula\n\n```\nswiftPMImport.\u003Cgroup>.\u003Cmodule>.\u003CClassName>\n\nWhere:\n- group: build.gradle.kts `group` property, dashes (-) → dots (.)\n- module: Gradle module name, dashes (-) → dots (.), underscores (_) preserved as-is\n- ClassName: Objective-C class name (FIR* for Firebase, GMS* for Google Maps)\n```\n\n### Example Transformation\n\n```kotlin\n\u002F\u002F group = \"org.jetbrains.kotlin.firebase.sample\", module = \"kotlin-library\"\n\n\u002F\u002F BEFORE:\nimport cocoapods.FirebaseAnalytics.FIRAnalytics\n\n\u002F\u002F AFTER:\nimport swiftPMImport.org.jetbrains.kotlin.firebase.sample.kotlin.library.FIRAnalytics\n```\n\n**Import flattening:** The Clang module name (e.g., `FirebaseFirestoreInternal`, `FirebaseAuth`) disappears from the import path — all classes are flattened under the same `swiftPMImport.\u003Cgroup>.\u003Cmodule>` prefix regardless of which library they come from. For example, both `cocoapods.FirebaseAuth.FIRAuth` and `cocoapods.FirebaseFirestoreInternal.FIRFirestore` become `swiftPMImport.\u003Cgroup>.\u003Cmodule>.FIRAuth` and `swiftPMImport.\u003Cgroup>.\u003Cmodule>.FIRFirestore`.\n\n### Preserving Bundled Klib Imports\n\n> **CRITICAL:** Do NOT replace `cocoapods.*` imports that resolve to third-party KMP libraries' bundled cinterop klibs (identified in Phase 1 step 1.3). These imports must remain as-is — the `cocoapods` prefix is the package namespace in the library's published klib, not an actual CocoaPods dependency. The swiftPMDependencies cinterop generator skips modules already provided by a dependency's klib, so `swiftPMImport.*` for those classes will fail with \"Unresolved reference\".\n\n**Example** (project using [KMPNotifier](https:\u002F\u002Fgithub.com\u002Fmirzemehdi\u002FKMPNotifier)):\n```kotlin\n\u002F\u002F KEEP — resolves to kmpnotifier's bundled cinterop klib\nimport cocoapods.FirebaseMessaging.FIRMessaging\n```\n\n### Bulk Replacement\n\nUse a regex find-and-replace across all Kotlin source files, **excluding imports identified in Phase 1 step 1.3**:\n\n```\nFind:    cocoapods\\.\\w+\\.\nReplace: swiftPMImport.\u003Cyour.group>.\u003Cyour.module>.\n```\n\nAfter bulk replacement, **manually restore** any `cocoapods.*` imports that should be preserved (from bundled klibs).\n\n**Finding correct import path:** Run `.\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64` - errors show available classes.\n\n---\n\n## Phase 5: iOS Project Reconfiguration\n\n### 5.1 Get migration command\n\nBuild the CocoaPods workspace to obtain the migration command:\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\n\nxcodebuild -scheme \"$(echo -n *.xcworkspace | python3 -c 'import sys, json; from subprocess import check_output; print(list(set(json.loads(check_output([\"xcodebuild\", \"-workspace\", sys.stdin.readline(), \"-list\", \"-json\"]))[\"workspace\"][\"schemes\"]) - set(json.loads(check_output([\"xcodebuild\", \"-project\", \"Pods\u002FPods.xcodeproj\", \"-list\", \"-json\"]))[\"project\"][\"schemes\"]))[0])')\" -workspace *.xcworkspace -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64 | grep -A5 'What went wrong'\n```\n\nThe build output will contain a command like:\n```bash\nXCODEPROJ_PATH='\u002Fpath\u002Fto\u002Fproject\u002FiosApp.xcodeproj' GRADLE_PROJECT_PATH=':shared' '\u002Fpath\u002Fto\u002Fproject\u002Fgradlew' -p '\u002Fpath\u002Fto\u002Fproject' ':shared:integrateEmbedAndSign' ':shared:integrateLinkagePackage'\n```\n\nRun this command. It modifies the `.xcodeproj` to trigger `embedAndSignAppleFrameworkForXcode` during the build. `integrateLinkagePackage` is a one-time setup — it does not need to be added as a build phase. If `integrateEmbedAndSign` is skipped, check for EmbedAndSign disablers (Phase 1 step 1.2) — remove them first, then re-run.\n\n**Verify `embedAndSignAppleFrameworkForXcode` is active:** After running integration, check the build phase script in `project.pbxproj`. If `embedAndSignAppleFrameworkForXcode` is commented out (prefixed with `#`), uncomment it.\n\nThe `integrateLinkagePackage` task generates `_internal_linkage_SwiftPMImport\u002F` at `\u003CiosDir>\u002F` — a local Swift package that mirrors your `products` list and ensures SPM libraries are linked into the final binary.\n\nAfter running the integration tasks, **disable User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING = NO`) in the `.xcodeproj`. Xcode 16+ enables it by default, which prevents the Gradle build phase from writing to the project directory:\n\n```bash\nsed -i '' 's\u002FENABLE_USER_SCRIPT_SANDBOXING = YES\u002FENABLE_USER_SCRIPT_SANDBOXING = NO\u002Fg' \"$XCODEPROJ_PATH\u002Fproject.pbxproj\"\n```\n\nIf the setting is absent (Xcode defaults to YES), add `ENABLE_USER_SCRIPT_SANDBOXING = NO;` to the app target's `buildSettings` sections. Then restart the Gradle daemon: `.\u002Fgradlew --stop`\n\n**Alternative (if xcodebuild approach fails):** See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual Integration Command Discovery\" for a fallback script to discover paths and run integration tasks directly.\n\n### 5.2 Update Crashlytics dSYM upload script (if applicable)\n\nIf the project uses FirebaseCrashlytics and has a dSYM upload run script phase (identified in Phase 1 step 11), update the script path from `${PODS_ROOT}\u002FFirebaseCrashlytics\u002Fupload-symbols` to `\"${BUILD_DIR%\u002FBuild\u002F*}\u002FSourcePackages\u002Fcheckouts\u002Ffirebase-ios-sdk\u002FCrashlytics\u002Frun\"`. See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Firebase Crashlytics: dSYM Upload Script\" and common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for the full script and input files list.\n\n### 5.3 Deintegrate CocoaPods\n\n**Option A: Full deintegration** (if CocoaPods was used ONLY for KMP dependencies):\n\nBefore deleting files, run `git status --short` and verify the paths. If unsure, move files to a backup location instead of deleting immediately.\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\npod deintegrate\nrm -rf Podfile Podfile.lock Pods\u002F\n# Remove the workspace that matches your app xcodeproj name\nXCODEPROJ_NAME=$(basename \"$(find . -maxdepth 1 -name \"*.xcodeproj\" -type d | grep -v Pods | head -1)\" .xcodeproj)\nrm -rf \"${XCODEPROJ_NAME}.xcworkspace\"\n# Return to project root\ncd ..\n# Remove the migrated module podspec only (for example, shared.podspec)\n# If unknown, list candidates and remove the matching one explicitly:\nls -1 *.podspec\n# rm -f shared.podspec\n```\n\nThis cleanup snippet is self-contained and does not assume `XCODEPROJ_PATH` or `GRADLE_PROJECT_PATH` from the earlier one-off migration command are still available in your shell.\n\nIf `pod deintegrate` is not available, see troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual CocoaPods Deintegration from pbxproj\" for the full list of references to remove. Also remove `Pods\u002F` from `.gitignore` and delete the `.xcworkspace` directory.\n\n**Option B: Partial removal** (if other non-KMP CocoaPods dependencies remain):\n\nRemove only the KMP pod line from the `Podfile` and re-run pod install:\n\n```ruby\ntarget 'iosApp' do\n  # Remove this line:\n  pod 'shared', :path => '..\u002Fshared'\n  # Keep other non-KMP pods\nend\n```\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp && pod install\n```\n\n> **Tip:** Consider migrating remaining pods to SPM too — most popular iOS libraries support it natively. Add them in Xcode via File → Add Package Dependencies, then fully deintegrate CocoaPods once all pods are replaced.\n\n### 5.4 Manual integration (if automatic fails)\n\nSee troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual Xcode Integration Steps\" for the 5-step manual setup (build phase, sandboxing, linkage package).\n\n---\n\n## Phase 6: Remove CocoaPods from Gradle\n\nNow that the iOS project is reconfigured, remove the CocoaPods plugin and block from **all** modules that used it (not just the primary one):\n\n### 6.1 Remove CocoaPods plugin\n\n```kotlin\nplugins {\n    \u002F\u002F REMOVE: kotlin(\"native.cocoapods\")\n    alias(libs.plugins.kotlinMultiplatform)  \u002F\u002F Keep\n}\n```\n\n### 6.2 Remove cocoapods block\n\nDelete the entire `cocoapods { ... }` block from `build.gradle.kts`. The `swiftPMDependencies {}` block and `binaries.framework {}` configuration added in Phase 3 replace it. Also delete any generated `.podspec` files from the module directory (e.g., `shared\u002Fshared.podspec`) — these were generated by the CocoaPods plugin and are no longer needed.\n\n### 6.3 Remove deprecated gradle.properties entries\n\nIf found in Phase 1.1, remove from `gradle.properties`:\n\n```properties\n# REMOVE — no longer needed after migrating away from CocoaPods (KT-64096)\nkotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true\n```\n\n### 6.4 Clean up CocoaPods-related extras\n\nReview the extras identified in Phase 1 step 12. Podspec metadata, `noPodspec()`, CocoaPods task hooks, and `Pods.xcodeproj` patching code are **safe to remove** without user consultation. Non-standard pod configurations (`extraOpts`, `moduleName`), custom cinterop `defFile` setups, and CocoaPods-specific compiler\u002Flinker flags **require analysis** — consult the user if unsure whether SPM handles them automatically.\n\nSee cocoapods_extras_patterns.md (`references\u002Fcocoapods_extras_patterns.md`) for the full categorized list with examples.\n\n---\n\n## Phase 7: Verification\n\n**Do NOT stop until the application builds successfully.** This phase is iterative — if any step fails, diagnose the error, fix it (consulting troubleshooting.md (`references\u002Ftroubleshooting.md`) and re-checking Phases 2–6), and re-run the failing step. Repeat until the build succeeds or the issue is clearly outside the migration scope (pre-existing bug, unrelated tooling problem). Do NOT write the migration report (Phase 8) until the build succeeds.\n\n### 7.1 Compile Kotlin code\n\nCompile the migrated module to verify Kotlin sources are correct:\n\n```bash\n.\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64\n```\n\nIf compilation fails with unresolved references, check import transformations (Phase 4) and SwiftPM dependency declarations (Phase 3.2). Common causes: missing `importedClangModules`, wrong Clang module names, preserved bundled klib imports that should have been transformed (or vice versa).\n\n### 7.2 Link framework\n\n```bash\n.\u002Fgradlew :moduleName:linkDebugFrameworkIosSimulatorArm64\n```\n\nIf linking fails, check that all required SPM products are declared and that version constraints resolve correctly. Linking errors about missing symbols often indicate a product was omitted from `swiftPMDependencies` or a version mismatch caused API removal.\n\n### 7.3 Build iOS\u002FmacOS Xcode project\n\nAfter the Gradle steps succeed, build the Xcode project to verify the full application compiles. Use `-project *.xcodeproj` if all CocoaPods were removed (Option A), or `-workspace *.xcworkspace` if non-KMP CocoaPods remain (Option B):\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\n# Discover schemes and build (replace -project\u002F-workspace as needed; for macOS use -destination 'platform=macOS'):\nxcodebuild -project *.xcodeproj -list -json 2>\u002Fdev\u002Fnull | python3 -c \"import sys,json; schemes=json.load(sys.stdin)['project']['schemes']; [print(s) for s in schemes]\"\nxcodebuild -project *.xcodeproj -scheme \"\u003CAppScheme>\" -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64 build\n```\n\n**If `checkSandboxAndWriteProtection` fails** — sandboxing was not disabled in Phase 5.1. Go back and apply the sandboxing fix from Phase 5.1, then retry.\n\n**If the pre-migration build was not verified** (Phase 1.0 fallback was used), warn the user:\n> Note: The pre-migration build could not be fully verified. If build errors appear now, some may be pre-existing issues unrelated to the migration. Compare errors against the pre-migration build output to distinguish migration issues from prior problems.\n\n### If the build fails\n\n**Do NOT revert the migration.** Read the error log, re-check Phases 2-6, and consult troubleshooting.md (`references\u002Ftroubleshooting.md`). If unsure, present options to the user — do not silently undo migration work. Fix the issue and re-run the failing verification step. Keep iterating until the build succeeds.\n\n---\n\n## Phase 8: Migration Report\n\nAfter the build succeeds, write a comprehensive `MIGRATION_REPORT.md` in the project root. Use the template in migration_report_template.md (`references\u002Fmigration_report_template.md`).\n\nThe report must include:\n1. **Pre-Migration State** — CocoaPods dependencies (name, version, `linkOnly`), framework config, `cocoapods.*` imports, non-KMP pods, atypical configuration\n2. **Migration Steps** — exact changes per phase with before\u002Fafter snippets for non-trivial changes\n3. **Import Transformations** — table of every import change, clearly marking preserved `cocoapods.*` imports and which bundled klib provides them\n4. **Errors Encountered** — structured `Error #N` entries: phase, exact symptom, root cause, fix, generalizable flag\n5. **Non-Trivial Decisions** — `isStatic` changes, preserved imports, framework search paths, trade-offs\n6. **Files Changed** — complete list grouped by type (Gradle, Kotlin, Xcode, created, deleted)\n\n---\n\n## Additional Resources\n\n- DSL Reference (`references\u002Fdsl_reference.md`) - Full swiftPMDependencies syntax\n- Common Pods Mapping (`references\u002Fcommon_pods_mapping.md`) - Pod to SPM mapping table\n- CocoaPods Extras Patterns (`references\u002Fcocoapods_extras_patterns.md`) - Detection and cleanup patterns for CocoaPods workarounds\n- Troubleshooting (`references\u002Ftroubleshooting.md`) - Issues, solutions, rollback\n- Migration Report Template (`references\u002Fmigration_report_template.md`) - Post-migration report template\n","# CocoaPods to SwiftPM Migration for KMP\n\nMigrate Kotlin Multiplatform projects from `kotlin(\"native.cocoapods\")` to `swiftPMDependencies {}` DSL.\n\n## Requirements\n\n- **Kotlin**: Version with Swift Import support (e.g., 2.4.0-Beta1 or later)\n- **Xcode**: 16.4 or 26.0+\n- **iOS Deployment Target**: 16.0+ recommended\n\n## Migration Overview\n\n**IMPORTANT**: Keep the `cocoapods {}` block and plugin active until Phase 6. The migration adds `swiftPMDependencies {}` alongside the existing CocoaPods setup first, reconfigures Xcode, and only then removes CocoaPods.\n\n| Phase | Action |\n|-------|--------|\n| 1 | Analyze existing CocoaPods configuration |\n| 2 | Update Gradle configuration (repos, Kotlin version) |\n| 3 | Add `swiftPMDependencies {}` alongside existing `cocoapods {}` |\n| 4 | Transform Kotlin imports |\n| 5 | Reconfigure iOS project and deintegrate CocoaPods |\n| 6 | Remove CocoaPods plugin from Gradle |\n| 7 | Verify Gradle build and Xcode project build |\n| 8 | Write MIGRATION_REPORT.md |\n\n---\n\n## Phase 1: Pre-Migration Analysis\n\n### 1.0 Verify the project builds\n\nBefore starting migration, identify the module to migrate and confirm it compiles successfully.\n\n1. **Find the module that uses CocoaPods** — look for `build.gradle.kts` files containing `cocoapods`:\n   ```bash\n   grep -rl \"cocoapods\" --include=\"build.gradle.kts\" .\n   ```\n   Extract the module name from the path (e.g., `.\u002Fshared\u002Fbuild.gradle.kts` → module name is `shared`). Note: multiple modules may use CocoaPods — record all of them. Typically only the module that produces the framework linked into the iOS app needs `swiftPMDependencies`; the others only need CocoaPods removed (Phase 6).\n\n2. **Compile Kotlin code** — run the Kotlin compilation task for that module to verify the Kotlin source compiles:\n   ```bash\n   .\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64\n   ```\n   Replace `moduleName` with the directory name of the module (e.g., `:shared:compileKotlinIosSimulatorArm64`). This is faster than a full `build` (which also runs release linkage) and sufficient to verify Kotlin code correctness.\n\n3. **Build the iOS app (optional)** — try to locate the Xcode project and build it to confirm the full app compiles:\n   ```bash\n   # Find the Xcode project\n   find . -name \"*.xcworkspace\" -not -path \"*\u002FPods\u002F*\" -maxdepth 2\n   # Build (replace scheme name with the actual app scheme)\n   cd \u002Fpath\u002Fto\u002FiosApp\n   xcodebuild -workspace *.xcworkspace -scheme \"\u003CAppScheme>\" -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64\n   ```\n   If the user wants to skip the Xcode build or no Xcode project is found, proceed without it — the Kotlin compilation from step 2 is sufficient to continue.\n\n4. **If the Kotlin compilation fails**, ask the user to either:\n   - Provide the correct Gradle command to verify the module builds, or\n   - Confirm the module is in a working state and it's safe to proceed\n\n   If the user confirms without providing a build command, **record that the pre-migration build could not be verified** and warn about this at the end of migration (Phase 7).\n\n### 1.0a Confirm Kotlin version with Swift Import support\n\nAsk the user:\n\n> Does your project already use a Kotlin version with Swift Import support (swiftPMDependencies DSL)?\n\n**If yes** → read their current Kotlin version from `gradle\u002Flibs.versions.toml` (or `build.gradle.kts`), record it, and skip Phase 2.2 (no version change needed).\n\n**If no** → ask:\n\n> Please provide the Kotlin version to use (e.g., \"2.4.0\", \"2.4.0-Beta1\", \"2.4.0-dev-123\").\n\nRecord the user-provided version. Then ask:\n\n> Does this Kotlin version require a custom Maven repository (e.g., JetBrains dev repo)?\n\n- **Yes** → ask for the repo URL (suggest `https:\u002F\u002Fpackages.jetbrains.team\u002Fmaven\u002Fp\u002Fkt\u002Fdev` as default). Phase 2.1 will add it.\n- **No** → Phase 2.1 is skipped (no custom repo needed).\n\nFinally, check the project's current Kotlin version. Compare **major.minor** against the target. If it differs significantly (e.g., `2.1.0` → `2.4.0`), warn: \"⚠️ Kotlin version jump — upgrading across minor versions can introduce breaking changes unrelated to this migration. Recommended: update first, verify it builds, then re-run.\" If the user confirms despite the mismatch, proceed.\n\n### 1.1 Check for deprecated CocoaPods workaround property\n\nSearch `gradle.properties` for the deprecated property:\n\n```properties\nkotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true\n```\n\nThis property was a workaround (see [KT-64096](https:\u002F\u002Fyoutrack.jetbrains.com\u002Fissue\u002FKT-64096)) for projects using `embedAndSign` alongside CocoaPods dependencies. It suppresses an error about unsupported configurations that can cause runtime crashes or symbol duplication. After migrating to SwiftPM import, this property is no longer needed and **must be removed** in Phase 6. Record its presence if found.\n\n### 1.2 Check for EmbedAndSign disablers\n\nSearch all `build.gradle.kts` files for code that disables `EmbedAndSign` tasks (e.g., `TaskGraph.whenReady` filters, `tasks.matching` blocks). This is a CocoaPods-era workaround that **breaks the migration** because `integrateEmbedAndSign` (needed in Phase 5) gets disabled too. Record any such code — it **must be removed** in Phase 6, and may need to be removed earlier. See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"`integrateEmbedAndSign` Skipped\" for patterns.\n\n### 1.3 Check for third-party KMP libraries with bundled cinterop klibs\n\nSome KMP libraries ship pre-built cinterop klibs with `cocoapods.*` package namespaces. After migration, the swiftPMDependencies cinterop generator detects these existing bindings and **skips generating new bindings** for those Clang modules to avoid duplicates. This means `cocoapods.*` imports for those modules must be **kept as-is** — they resolve to the third-party library's bundled klib, not to actual CocoaPods.\n\n**Known libraries with bundled `cocoapods.*` klibs:**\n\n| Library | Maven artifact | Bundled klib namespace | Classes provided |\n|---------|---------------|----------------------|-----------------|\n| [KMPNotifier](https:\u002F\u002Fgithub.com\u002Fmirzemehdi\u002FKMPNotifier) | `io.github.mirzemehdi:kmpnotifier` | `cocoapods.FirebaseMessaging` | `FIRMessaging`, `FIRMessagingAPNSTokenType`, etc. |\n\n**How to detect:** Search Gradle dependency declarations for known libraries, then cross-reference their bundled namespaces against the `import cocoapods.*` statements found in step 4. Mark any matches — these imports will NOT be transformed in Phase 4.\n\nIf unsure whether a third-party KMP library bundles cinterop klibs, check if it has a `linkOnly = true` pod dependency in the project — this is a strong indicator that the library provides its own klib for those classes.\n\nTo inspect klib contents and verify bundled bindings, see troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Third-Party KMP Libraries with Bundled Klibs\".\n\n**Find and record:**\n\n1. **CocoaPods configuration** - Search for `cocoapods` in `build.gradle.kts` files\n2. **Pod dependencies** - Extract pod names, versions from `cocoapods {}` blocks\n3. **Framework configuration** - Record `baseName`, `isStatic`, deployment target from `cocoapods.framework {}`\n4. **linkOnly pods** - Record pods declared with `linkOnly = true`. These pods provide native linking only — cinterop bindings come from a KMP wrapper library (e.g., `dev.gitlive:firebase-*`). See common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for implications.\n5. **Kotlin imports** - Find all `import cocoapods.*` statements. Cross-reference with step 1.3 to identify which imports come from bundled klibs (and must be preserved) vs. which come from direct pod cinterop (and must be transformed).\n6. **Map pods to SPM** - See common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`)\n7. **Locate iOS project directory** - Find the directory containing `Podfile` and `.xcworkspace`:\n   ```bash\n   find . -name \"Podfile\" -type f\n   ```\n   Record this path (e.g., `iosApp\u002F`, `ios\u002F`, or project root) - needed for Phase 5\n8. **Check for non-KMP CocoaPods** - Determine if the project uses CocoaPods for dependencies other than KMP. This affects cleanup strategy in Phase 5.\n9. **Cross-reference Podfile against `cocoapods {}` block** - Parse the `Podfile` and compare its pod entries with the pods declared in the Gradle `cocoapods {}` block. Record any dependencies that exist in the `Podfile` but are **not** listed in `cocoapods {}`. These Podfile-only dependencies still linked into the app via CocoaPods and must be migrated to `swiftPMDependencies` — dropping them silently causes obscure linkage errors at runtime.\n10. **Check Xcode build phases** - Open the `.xcodeproj`'s `project.pbxproj` and search for the Gradle build phase script. Check if `embedAndSignAppleFrameworkForXcode` is present but **commented out** (prefixed with `#`). If commented out, it must be uncommented during Phase 5 — the `integrateEmbedAndSign` task may or may not handle this automatically.\n11. **Check for existing Crashlytics dSYM upload script** - If using FirebaseCrashlytics, search `project.pbxproj` for a dSYM upload shell script phase. Record its current path (CocoaPods-era scripts reference `${PODS_ROOT}\u002FFirebaseCrashlytics\u002Fupload-symbols`). This must be updated to the SPM path in Phase 5.\n12. **Identify CocoaPods-related extras in build scripts** - Search all `build.gradle.kts` files for CocoaPods workarounds beyond the standard `cocoapods {}` block (custom tasks hooking into `podInstall`, `Pods.xcodeproj` patching, podspec metadata, `extraSpecAttributes`, `noPodspec()`, etc.). See cocoapods_extras_patterns.md (`references\u002Fcocoapods_extras_patterns.md`) for the full pattern list. Record all findings — these will be handled in Phase 6.\n\n---\n\n## Phase 2: Gradle Configuration\n\n**Important scope note:** Do NOT upgrade the Gradle wrapper version, update KSP, or update any other dependencies during this migration. Those are separate concerns and out of scope. Only change what is listed below.\n\n### 2.1 Add custom Maven repository (if needed)\n\n**Skip this step** if the user indicated in Phase 1.0a that their Kotlin version does not require a custom Maven repository (i.e., it is an official release, Beta, or RC available from Maven Central).\n\nFor dev\u002Fcustom builds, add the custom Maven repository (URL from Phase 1.0a) to `settings.gradle.kts`:\n\n```kotlin\npluginManagement {\n    repositories {\n        gradlePluginPortal()\n        mavenCentral()\n        maven(\"\u003Ccustom-repo-url>\")  \u002F\u002F ADD\n    }\n}\n\ndependencyResolutionManagement {\n    repositories {\n        mavenCentral()\n        maven(\"\u003Ccustom-repo-url>\")  \u002F\u002F ADD\n    }\n}\n```\n\n### 2.2 Update Kotlin version\n\n**Skip this step** if the user's project already uses a Kotlin version with Swift Import support (recorded in Phase 1.0a).\n\nUpdate to the version recorded in Phase 1.0a:\n\n```toml\n# gradle\u002Flibs.versions.toml\n[versions]\nkotlin = \"\u003Ckotlin-version>\"\n```\n\n### 2.3 Add buildscript constraint (if swiftPMDependencies not recognized)\n\n```kotlin\n\u002F\u002F root build.gradle.kts\nbuildscript {\n    dependencies.constraints {\n        \"classpath\"(\"org.jetbrains.kotlin:kotlin-gradle-plugin:\u003Ckotlin-version>!!\")\n    }\n}\n```\n\nReplace `\u003Ckotlin-version>` with the version recorded in Phase 1.0a. The `!!` suffix forces strict version resolution, ensuring no other dependency pulls in a different Kotlin Gradle plugin version.\n\n---\n\n## Phase 3: Add swiftPMDependencies (Keep CocoaPods)\n\n**Do NOT remove the `cocoapods {}` block or `kotlin(\"native.cocoapods\")` plugin yet.** Add `swiftPMDependencies {}` alongside the existing CocoaPods configuration.\n\n### 3.1 Add group property\n\n```kotlin\ngroup = \"org.example.myproject\"  \u002F\u002F Required for import namespace\n```\n\n**Compose Resources warning:** If the project uses Compose Multiplatform resources (`org.jetbrains.compose` plugin or `compose.resources`), the `group` property is also used as the namespace for generated resource accessors (e.g., `Res.string.*`, `Res.drawable.*`). If `group` already exists in `build.gradle.kts`, do **not** change it. If you are adding `group` for the first time, warn the user that existing Compose resource accessor call sites throughout the project will change namespace and may need updating.\n\n### 3.2 Add swiftPMDependencies block alongside cocoapods\n\nFor each pod dependency, add the equivalent SwiftPM package declaration. Use common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) to map each pod to its SPM package URL, product name, and `importedClangModules`.\n\n**Version preservation:** Match the version constraint semantics from the `cocoapods {}` block. Using `from()` for an exact CocoaPods version can resolve to a newer version that breaks cinterop APIs (removed symbols, changed signatures).\n\n| CocoaPods version spec | SPM equivalent | Example |\n|------------------------|---------------|---------|\n| `version = \"1.2.3\"` (exact) | `exact(\"1.2.3\")` | `pod(\"GoogleMaps\") { version = \"10.3.0\" }` → `exact(\"10.3.0\")` |\n| `version = \"~> 1.2\"` (optimistic) | `from(\"1.2.0\")` | `pod(\"FirebaseAuth\") { version = \"~> 12.5\" }` → `from(\"12.5.0\")` |\n| No version specified | `exact()` with latest, or ask user | Ask the user which version to pin |\n\n**Key concepts:** `products` = SPM product names (controls linking). `importedClangModules` = Clang module names for cinterop bindings (only when `discoverModulesImplicitly = false`). `discoverModulesImplicitly` defaults to `true` (bindings for all Clang modules); set `false` when transitive C\u002FC++ modules fail cinterop (Firebase, gRPC), then list needed modules explicitly.\n\n**Important:** SPM product names and Clang module names don't always match. Always consult common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for correct values.\n\n**Podfile-only dependencies:** If Phase 1 step 9 identified dependencies that exist in the `Podfile` but not in the Gradle `cocoapods {}` block, these must also be added to `swiftPMDependencies` as `products` entries. Even though the KMP module didn't declare them, they were linked into the app by CocoaPods and may be required for the app to build. Look up each Podfile-only pod's SPM package URL and add it as a `swiftPackage()` with at least its `products`. If any of these pods were used via cinterop (check for `import cocoapods.*` statements referencing them), also add `importedClangModules`.\n\n**Do not mix the same library suite across CocoaPods and SPM.** Libraries that share a common repository (e.g., all Firebase products) share transitive dependencies. Having some products linked via CocoaPods and others via SPM causes duplicate\u002Fconflicting symbols and dyld crashes at runtime. When migrating such a suite, move **all** pods from that suite to SPM at once — including Swift-only pods that Kotlin doesn't use directly. Add Swift-only pods as `products` entries (no `importedClangModules` needed). After adding new products, re-run `integrateLinkagePackage` to regenerate the linkage Swift package.\n\n```kotlin\nkotlin {\n    \u002F\u002F Keep existing targets\n    iosArm64()\n    iosSimulatorArm64()\n    iosX64()\n\n    swiftPMDependencies {\n        iosDeploymentVersion.set(\"16.0\")\n\n        \u002F\u002F If using KMP IntelliJ plugin, specify the .xcodeproj path:\n        \u002F\u002F xcodeProjectPathForKmpIJPlugin.set(\n        \u002F\u002F     layout.projectDirectory.file(\"..\u002FiosApp\u002FiosApp.xcodeproj\")\n        \u002F\u002F )\n\n        swiftPackage(\n            url = url(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo.git\"),\n            version = from(\"1.0.0\"),\n            products = listOf(product(\"ProductName\")),\n        )\n    }\n\n    cocoapods {\n        \u002F\u002F ... keep existing cocoapods block for now\n    }\n}\n```\n\n### 3.3 Move framework configuration out of cocoapods block\n\nIf the `cocoapods` block contains a `framework {}` configuration, move it to the `binaries` API on each target. **`isStatic = true` is recommended** — dynamic frameworks have known edge cases with SwiftPM import that can cause linker errors, dyld crashes, or duplicate class warnings:\n\n```kotlin\nlistOf(iosArm64(), iosSimulatorArm64(), iosX64()).forEach { iosTarget ->\n    iosTarget.binaries.framework { baseName = \"Shared\"; isStatic = true }\n}\n```\n\nIf the `cocoapods.framework {}` block contained `export(project(...))` or `transitiveExport = true`, preserve these in the new `binaries.framework {}` block — they are essential for multi-module projects where the framework exports child modules.\n\n### 3.4 Handle dev.gitlive\u002Ffirebase-kotlin-sdk and similar CocoaPods-era KMP wrappers\n\nIf the project uses `dev.gitlive:firebase-*` or similar KMP wrapper libraries, two additional steps are required:\n\n**A. Switch to `isStatic = true`** — dynamic frameworks + Firebase SPM = runtime `dyld` crash. After switching: re-run `integrateLinkagePackage`, remove any \"Embed Frameworks\" copy phase, move linker flags to `OTHER_LDFLAGS`.\n\n**B. Add framework search paths** — add conditional `-F` linkerOpts in `build.gradle.kts` and matching `FRAMEWORK_SEARCH_PATHS` in the Xcode project.\n\nSee common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) § dev.gitlive and troubleshooting.md (`references\u002Ftroubleshooting.md`) for code snippets and the full product list.\n\n### 3.5 Add opt-in for cinterop API\n\n```kotlin\nkotlin.compilerOptions {\n    optIn.add(\"kotlinx.cinterop.ExperimentalForeignApi\")\n}\n```\n\nFor full DSL reference, see dsl_reference.md (`references\u002Fdsl_reference.md`).\n\n---\n\n## Phase 4: Kotlin Source Updates\n\n### Import Namespace Formula\n\n```\nswiftPMImport.\u003Cgroup>.\u003Cmodule>.\u003CClassName>\n\nWhere:\n- group: build.gradle.kts `group` property, dashes (-) → dots (.)\n- module: Gradle module name, dashes (-) → dots (.), underscores (_) preserved as-is\n- ClassName: Objective-C class name (FIR* for Firebase, GMS* for Google Maps)\n```\n\n### Example Transformation\n\n```kotlin\n\u002F\u002F group = \"org.jetbrains.kotlin.firebase.sample\", module = \"kotlin-library\"\n\n\u002F\u002F BEFORE:\nimport cocoapods.FirebaseAnalytics.FIRAnalytics\n\n\u002F\u002F AFTER:\nimport swiftPMImport.org.jetbrains.kotlin.firebase.sample.kotlin.library.FIRAnalytics\n```\n\n**Import flattening:** The Clang module name (e.g., `FirebaseFirestoreInternal`, `FirebaseAuth`) disappears from the import path — all classes are flattened under the same `swiftPMImport.\u003Cgroup>.\u003Cmodule>` prefix regardless of which library they come from. For example, both `cocoapods.FirebaseAuth.FIRAuth` and `cocoapods.FirebaseFirestoreInternal.FIRFirestore` become `swiftPMImport.\u003Cgroup>.\u003Cmodule>.FIRAuth` and `swiftPMImport.\u003Cgroup>.\u003Cmodule>.FIRFirestore`.\n\n### Preserving Bundled Klib Imports\n\n> **CRITICAL:** Do NOT replace `cocoapods.*` imports that resolve to third-party KMP libraries' bundled cinterop klibs (identified in Phase 1 step 1.3). These imports must remain as-is — the `cocoapods` prefix is the package namespace in the library's published klib, not an actual CocoaPods dependency. The swiftPMDependencies cinterop generator skips modules already provided by a dependency's klib, so `swiftPMImport.*` for those classes will fail with \"Unresolved reference\".\n\n**Example** (project using [KMPNotifier](https:\u002F\u002Fgithub.com\u002Fmirzemehdi\u002FKMPNotifier)):\n```kotlin\n\u002F\u002F KEEP — resolves to kmpnotifier's bundled cinterop klib\nimport cocoapods.FirebaseMessaging.FIRMessaging\n```\n\n### Bulk Replacement\n\nUse a regex find-and-replace across all Kotlin source files, **excluding imports identified in Phase 1 step 1.3**:\n\n```\nFind:    cocoapods\\.\\w+\\.\nReplace: swiftPMImport.\u003Cyour.group>.\u003Cyour.module>.\n```\n\nAfter bulk replacement, **manually restore** any `cocoapods.*` imports that should be preserved (from bundled klibs).\n\n**Finding correct import path:** Run `.\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64` - errors show available classes.\n\n---\n\n## Phase 5: iOS Project Reconfiguration\n\n### 5.1 Get migration command\n\nBuild the CocoaPods workspace to obtain the migration command:\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\n\nxcodebuild -scheme \"$(echo -n *.xcworkspace | python3 -c 'import sys, json; from subprocess import check_output; print(list(set(json.loads(check_output([\"xcodebuild\", \"-workspace\", sys.stdin.readline(), \"-list\", \"-json\"]))[\"workspace\"][\"schemes\"]) - set(json.loads(check_output([\"xcodebuild\", \"-project\", \"Pods\u002FPods.xcodeproj\", \"-list\", \"-json\"]))[\"project\"][\"schemes\"]))[0])')\" -workspace *.xcworkspace -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64 | grep -A5 'What went wrong'\n```\n\nThe build output will contain a command like:\n```bash\nXCODEPROJ_PATH='\u002Fpath\u002Fto\u002Fproject\u002FiosApp.xcodeproj' GRADLE_PROJECT_PATH=':shared' '\u002Fpath\u002Fto\u002Fproject\u002Fgradlew' -p '\u002Fpath\u002Fto\u002Fproject' ':shared:integrateEmbedAndSign' ':shared:integrateLinkagePackage'\n```\n\nRun this command. It modifies the `.xcodeproj` to trigger `embedAndSignAppleFrameworkForXcode` during the build. `integrateLinkagePackage` is a one-time setup — it does not need to be added as a build phase. If `integrateEmbedAndSign` is skipped, check for EmbedAndSign disablers (Phase 1 step 1.2) — remove them first, then re-run.\n\n**Verify `embedAndSignAppleFrameworkForXcode` is active:** After running integration, check the build phase script in `project.pbxproj`. If `embedAndSignAppleFrameworkForXcode` is commented out (prefixed with `#`), uncomment it.\n\nThe `integrateLinkagePackage` task generates `_internal_linkage_SwiftPMImport\u002F` at `\u003CiosDir>\u002F` — a local Swift package that mirrors your `products` list and ensures SPM libraries are linked into the final binary.\n\nAfter running the integration tasks, **disable User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING = NO`) in the `.xcodeproj`. Xcode 16+ enables it by default, which prevents the Gradle build phase from writing to the project directory:\n\n```bash\nsed -i '' 's\u002FENABLE_USER_SCRIPT_SANDBOXING = YES\u002FENABLE_USER_SCRIPT_SANDBOXING = NO\u002Fg' \"$XCODEPROJ_PATH\u002Fproject.pbxproj\"\n```\n\nIf the setting is absent (Xcode defaults to YES), add `ENABLE_USER_SCRIPT_SANDBOXING = NO;` to the app target's `buildSettings` sections. Then restart the Gradle daemon: `.\u002Fgradlew --stop`\n\n**Alternative (if xcodebuild approach fails):** See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual Integration Command Discovery\" for a fallback script to discover paths and run integration tasks directly.\n\n### 5.2 Update Crashlytics dSYM upload script (if applicable)\n\nIf the project uses FirebaseCrashlytics and has a dSYM upload run script phase (identified in Phase 1 step 11), update the script path from `${PODS_ROOT}\u002FFirebaseCrashlytics\u002Fupload-symbols` to `\"${BUILD_DIR%\u002FBuild\u002F*}\u002FSourcePackages\u002Fcheckouts\u002Ffirebase-ios-sdk\u002FCrashlytics\u002Frun\"`. See troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Firebase Crashlytics: dSYM Upload Script\" and common_pods_mapping.md (`references\u002Fcommon_pods_mapping.md`) for the full script and input files list.\n\n### 5.3 Deintegrate CocoaPods\n\n**Option A: Full deintegration** (if CocoaPods was used ONLY for KMP dependencies):\n\nBefore deleting files, run `git status --short` and verify the paths. If unsure, move files to a backup location instead of deleting immediately.\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\npod deintegrate\nrm -rf Podfile Podfile.lock Pods\u002F\n# Remove the workspace that matches your app xcodeproj name\nXCODEPROJ_NAME=$(basename \"$(find . -maxdepth 1 -name \"*.xcodeproj\" -type d | grep -v Pods | head -1)\" .xcodeproj)\nrm -rf \"${XCODEPROJ_NAME}.xcworkspace\"\n# Return to project root\ncd ..\n# Remove the migrated module podspec only (for example, shared.podspec)\n# If unknown, list candidates and remove the matching one explicitly:\nls -1 *.podspec\n# rm -f shared.podspec\n```\n\nThis cleanup snippet is self-contained and does not assume `XCODEPROJ_PATH` or `GRADLE_PROJECT_PATH` from the earlier one-off migration command are still available in your shell.\n\nIf `pod deintegrate` is not available, see troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual CocoaPods Deintegration from pbxproj\" for the full list of references to remove. Also remove `Pods\u002F` from `.gitignore` and delete the `.xcworkspace` directory.\n\n**Option B: Partial removal** (if other non-KMP CocoaPods dependencies remain):\n\nRemove only the KMP pod line from the `Podfile` and re-run pod install:\n\n```ruby\ntarget 'iosApp' do\n  # Remove this line:\n  pod 'shared', :path => '..\u002Fshared'\n  # Keep other non-KMP pods\nend\n```\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp && pod install\n```\n\n> **Tip:** Consider migrating remaining pods to SPM too — most popular iOS libraries support it natively. Add them in Xcode via File → Add Package Dependencies, then fully deintegrate CocoaPods once all pods are replaced.\n\n### 5.4 Manual integration (if automatic fails)\n\nSee troubleshooting.md (`references\u002Ftroubleshooting.md`) § \"Manual Xcode Integration Steps\" for the 5-step manual setup (build phase, sandboxing, linkage package).\n\n---\n\n## Phase 6: Remove CocoaPods from Gradle\n\nNow that the iOS project is reconfigured, remove the CocoaPods plugin and block from **all** modules that used it (not just the primary one):\n\n### 6.1 Remove CocoaPods plugin\n\n```kotlin\nplugins {\n    \u002F\u002F REMOVE: kotlin(\"native.cocoapods\")\n    alias(libs.plugins.kotlinMultiplatform)  \u002F\u002F Keep\n}\n```\n\n### 6.2 Remove cocoapods block\n\nDelete the entire `cocoapods { ... }` block from `build.gradle.kts`. The `swiftPMDependencies {}` block and `binaries.framework {}` configuration added in Phase 3 replace it. Also delete any generated `.podspec` files from the module directory (e.g., `shared\u002Fshared.podspec`) — these were generated by the CocoaPods plugin and are no longer needed.\n\n### 6.3 Remove deprecated gradle.properties entries\n\nIf found in Phase 1.1, remove from `gradle.properties`:\n\n```properties\n# REMOVE — no longer needed after migrating away from CocoaPods (KT-64096)\nkotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true\n```\n\n### 6.4 Clean up CocoaPods-related extras\n\nReview the extras identified in Phase 1 step 12. Podspec metadata, `noPodspec()`, CocoaPods task hooks, and `Pods.xcodeproj` patching code are **safe to remove** without user consultation. Non-standard pod configurations (`extraOpts`, `moduleName`), custom cinterop `defFile` setups, and CocoaPods-specific compiler\u002Flinker flags **require analysis** — consult the user if unsure whether SPM handles them automatically.\n\nSee cocoapods_extras_patterns.md (`references\u002Fcocoapods_extras_patterns.md`) for the full categorized list with examples.\n\n---\n\n## Phase 7: Verification\n\n**Do NOT stop until the application builds successfully.** This phase is iterative — if any step fails, diagnose the error, fix it (consulting troubleshooting.md (`references\u002Ftroubleshooting.md`) and re-checking Phases 2–6), and re-run the failing step. Repeat until the build succeeds or the issue is clearly outside the migration scope (pre-existing bug, unrelated tooling problem). Do NOT write the migration report (Phase 8) until the build succeeds.\n\n### 7.1 Compile Kotlin code\n\nCompile the migrated module to verify Kotlin sources are correct:\n\n```bash\n.\u002Fgradlew :moduleName:compileKotlinIosSimulatorArm64\n```\n\nIf compilation fails with unresolved references, check import transformations (Phase 4) and SwiftPM dependency declarations (Phase 3.2). Common causes: missing `importedClangModules`, wrong Clang module names, preserved bundled klib imports that should have been transformed (or vice versa).\n\n### 7.2 Link framework\n\n```bash\n.\u002Fgradlew :moduleName:linkDebugFrameworkIosSimulatorArm64\n```\n\nIf linking fails, check that all required SPM products are declared and that version constraints resolve correctly. Linking errors about missing symbols often indicate a product was omitted from `swiftPMDependencies` or a version mismatch caused API removal.\n\n### 7.3 Build iOS\u002FmacOS Xcode project\n\nAfter the Gradle steps succeed, build the Xcode project to verify the full application compiles. Use `-project *.xcodeproj` if all CocoaPods were removed (Option A), or `-workspace *.xcworkspace` if non-KMP CocoaPods remain (Option B):\n\n```bash\ncd \u002Fpath\u002Fto\u002FiosApp\n# Discover schemes and build (replace -project\u002F-workspace as needed; for macOS use -destination 'platform=macOS'):\nxcodebuild -project *.xcodeproj -list -json 2>\u002Fdev\u002Fnull | python3 -c \"import sys,json; schemes=json.load(sys.stdin)['project']['schemes']; [print(s) for s in schemes]\"\nxcodebuild -project *.xcodeproj -scheme \"\u003CAppScheme>\" -destination 'generic\u002Fplatform=iOS Simulator' ARCHS=arm64 build\n```\n\n**If `checkSandboxAndWriteProtection` fails** — sandboxing was not disabled in Phase 5.1. Go back and apply the sandboxing fix from Phase 5.1, then retry.\n\n**If the pre-migration build was not verified** (Phase 1.0 fallback was used), warn the user:\n> Note: The pre-migration build could not be fully verified. If build errors appear now, some may be pre-existing issues unrelated to the migration. Compare errors against the pre-migration build output to distinguish migration issues from prior problems.\n\n### If the build fails\n\n**Do NOT revert the migration.** Read the error log, re-check Phases 2-6, and consult troubleshooting.md (`references\u002Ftroubleshooting.md`). If unsure, present options to the user — do not silently undo migration work. Fix the issue and re-run the failing verification step. Keep iterating until the build succeeds.\n\n---\n\n## Phase 8: Migration Report\n\nAfter the build succeeds, write a comprehensive `MIGRATION_REPORT.md` in the project root. Use the template in migration_report_template.md (`references\u002Fmigration_report_template.md`).\n\nThe report must include:\n1. **Pre-Migration State** — CocoaPods dependencies (name, version, `linkOnly`), framework config, `cocoapods.*` imports, non-KMP pods, atypical configuration\n2. **Migration Steps** — exact changes per phase with before\u002Fafter snippets for non-trivial changes\n3. **Import Transformations** — table of every import change, clearly marking preserved `cocoapods.*` imports and which bundled klib provides them\n4. **Errors Encountered** — structured `Error #N` entries: phase, exact symptom, root cause, fix, generalizable flag\n5. **Non-Trivial Decisions** — `isStatic` changes, preserved imports, framework search paths, trade-offs\n6. **Files Changed** — complete list grouped by type (Gradle, Kotlin, Xcode, created, deleted)\n\n---\n\n## Additional Resources\n\n- DSL Reference (`references\u002Fdsl_reference.md`) - Full swiftPMDependencies syntax\n- Common Pods Mapping (`references\u002Fcommon_pods_mapping.md`) - Pod to SPM mapping table\n- CocoaPods Extras Patterns (`references\u002Fcocoapods_extras_patterns.md`) - Detection and cleanup patterns for CocoaPods workarounds\n- Troubleshooting (`references\u002Ftroubleshooting.md`) - Issues, solutions, rollback\n- Migration Report Template (`references\u002Fmigration_report_template.md`) - Post-migration report template\n",{"name":5,"license":15,"metadata":44,"description":7},{"author":45,"version":46},"JetBrains","1.0.0","master","c2e410e11df4d80d885e0ecf0583ef3c926df736",".ai\u002Fskills\u002Fofficial_kotlin_kotlin_tooling_cocoapods_spm_migration",0,"https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory","https:\u002F\u002Fgithub.com\u002FiDorgham","Dorgham.me","hey I'm Dorgham \r\nI code, I create, and AI codes back. \r\nMaybe we can give AI the chance!! now we begin. 🚀🤖\r\n... . . . git commit -m \"Hello, Future\" ","2026-05-04 18:39:09",{"source":8,"skillName":5,"commands":57,"prompt":67,"zipAvailable":68},[58,61,64],{"tool":59,"command":60},"npx","npx skills add iDorgham\u002FWorkspace-Factory --skill kotlin-tooling-cocoapods-spm-migration",{"tool":62,"command":63},"bunx","bunx skills add iDorgham\u002FWorkspace-Factory --skill kotlin-tooling-cocoapods-spm-migration",{"tool":65,"command":66},"pnpm","pnpm dlx skills add iDorgham\u002FWorkspace-Factory --skill kotlin-tooling-cocoapods-spm-migration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002F.ai\u002Fskills\u002Fofficial_kotlin_kotlin_tooling_cocoapods_spm_migration\u002Fskill.md",true,[],[71,105,127,149,169,192],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":83,"publishedAt":104},"01M71P8WVBMB2X3D24R0YT0B0E","vercel-react-view-transitions","Guide for implementing smooth, native-feeling animations using React's View Transition API (`\u003CViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter\u002Fexit of components, animate list reorder, implement directional (forward\u002Fback) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view transitions, `startViewTransition`, `ViewTransition`, transition types, or asks about animating between UI states in React without third-party animation libraries.","MIT","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_view_transitions\u002Fskill.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103],"react","vercel react view transitions","view","react view transitions","vercel","transitions","shared","back","Animation","css","types","states","element","implementing","when","components","api","route","create","libraries","2026-11-10 13:02:02",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":112,"publishedAt":104},"01M71P8TDGHZ289TSAC5VTG2EW","vercel-react-native-skills","React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_native_skills\u002Fskill.md",[111],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[84,113,30,88,114,115,116,117,97,118,98,119,99,120,121,122,123,124,125,126],"react native","vercel react native skills","react native skills","modules","performance","apps","tasks","mobile","expo","list","mobile performance","platform","animations","for",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":134,"publishedAt":104},"01M71P8QK4JF5BYRGYDDGPZQG9","vercel-react-best-practices","React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React\u002FNext.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_best_practices\u002Fskill.md",[133],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[84,135,136,88,137,117,138,98,139,119,99,140,141,142,143,144,145,146,147,148],"react best practices","vercel react best practices","best practices","writing","code","data fetching","react components","next","refactoring","data","patterns","Optimization","guidelines","triggers",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":156,"publishedAt":104},"01M71P8HVEA70K5N6ZVJCG2ED3","vercel-composition-patterns","React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_composition_patterns\u002Fskill.md",[155],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[157,88,158,145,159,160,161,162,148,163,164,165,98,166,119,99,167,168,100,84],"Composition","composition patterns","vercel composition patterns","react composition patterns","react 19","render","boolean","component architecture","use","reusable","architecture","react composition",{"skillNo":170,"name":171,"nameZh":6,"description":172,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":173,"categories":174,"keywords":178,"publishedAt":104},"01M71P60XXKKP222ZFJRG7R373","supabase-postgres-best-practices","Postgres performance optimization and best practices from Supabase. Use this skill when writing, reviewing, or optimizing Postgres queries, schema designs, or database configurations.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_supabase_supabase_postgres_best_practices\u002Fskill.md",[175],{"categoryNo":176,"categoryName":177,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000010","后端与接口",[179,180,181,182,137,183,184,185,126,146,117,186,187,138,188,165,189,190,191,98],"postgres best practices","supabase","postgres","supabase postgres best practices","categories","postgres performance","advanced","correct","schema","impact","Rules","critical","database",{"skillNo":193,"name":194,"nameZh":6,"description":195,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":196,"categories":197,"keywords":199,"publishedAt":215},"01M71P2ZCEJD0PKC458YTP1FJW","portable-text-serialization","Render and serialize Portable Text to React, Svelte, Vue, Astro, HTML, Markdown, and plain text. Use when implementing Portable Text rendering in any frontend framework, building custom serializers for non-standard block types, converting Portable Text to HTML strings server-side, converting Portable Text to Markdown, extracting plain text from Portable Text, or troubleshooting rendering issues with marks, blocks, lists, or custom types.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_sanity_io_portable_text_serialization\u002Fskill.md",[198],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[200,201,202,203,204,94,205,162,206,97,207,208,98,84,209,210,211,212,213,214],"text","portable text serialization","portable","serialization","extracting","strings","issues","frontend","svelte","sanity","astro","server","markdown","rendering","vue","2026-11-10 10:56:23"]