From hotwire-native
Build iOS/Android apps powered by a Rails backend using Hotwire Native. Use when working on a Hotwire Native project: iOS/Android setup, path configuration rules, web vs. bridge component vs. native screen decisions, Swift/Kotlin implementations, push notifications, or deployment. Includes verified real-world gotchas for hotwire-native-ios 1.2.2 that prevent the most common compile/runtime errors.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hotwire-native:hotwire-nativeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Verified versions:** hotwire-native-ios 1.2.2 · hotwire-native-android 1.2.8 (docs-sourced) · @hotwired/hotwire-native-bridge 1.2.2 · Rails 8.1
references/bridge-components-android.mdreferences/bridge-components-ios.mdreferences/bridge-components.mdreferences/deployment.mdreferences/native-screens-android.mdreferences/native-screens-ios.mdreferences/navigation-and-tabs.mdreferences/path-configuration.mdreferences/push-notifications.mdreferences/rails-integration.mdreferences/setup-android.mdreferences/setup-ios.mdreferences/troubleshooting.mdVerified versions: hotwire-native-ios 1.2.2 · hotwire-native-android 1.2.8 (docs-sourced) · @hotwired/hotwire-native-bridge 1.2.2 · Rails 8.1
One element on screen feels wrong → Bridge Component
Entire screen needs native (maps, camera, home screen) → Native Screen
Everything else → stay Web (change server-side, ship nothing)
Path config controls behavior without an app release:
| Need | Path config property |
|---|---|
| Modal (new/edit forms) | context: "modal" + pull_to_refresh_enabled: false |
| iOS native screen | view_controller: "map" → handle in NavigatorDelegate |
| Android native Fragment | uri: "hotwire://fragment/native/map" → register in Application |
| Android default web | ".*" wildcard → uri: "hotwire://fragment/web" — must be first rule |
iOS has no wildcard requirement — it defaults to web. Android requires the wildcard explicitly, always first.
turbo-rails gem present? /new, /edit routes? HTTPS prod URL? Session cookie auth?XxxApp.swift + ContentView.swift → add hotwire-native-ios package → link to target (General → Frameworks) → add AppDelegate + SceneDelegate (see setup-ios.md)NSAllowsLocalNetworking = YES to Info.plist for simulator HTTPActionController::Base, not ApplicationController (see rails-integration.md)Navigator for HotwireTabBarController + HotwireTab.all (see navigation-and-tabs.md)unless hotwire_native_app? around nav/footer partials in RailsBridgeComponent + register in AppDelegate (see bridge-components-ios.md)NotificationTokenComponent (see push-notifications.md)ITSAppUsesNonExemptEncryption, bundle ID (see deployment.md)Load these on demand — SKILL.md loads first, reference files load when the question matches.
| Question / task | Load |
|---|---|
| Prepare Rails app for native clients | rails-integration.md |
| Path config JSON structure, rule ordering | path-configuration.md |
| iOS project bootstrap, UIKit lifecycle, ATS | setup-ios.md |
| Android project bootstrap, Gradle, wildcard rule | setup-android.md |
| Tab bar, modal vs push, snapshot cache | navigation-and-tabs.md |
| iOS native SwiftUI screen via path config | native-screens-ios.md |
| Android native Compose screen via path config | native-screens-android.md |
| Bridge component shared concepts (JS + HTML side) | bridge-components.md |
iOS BridgeComponent Swift implementation | bridge-components-ios.md |
Android BridgeComponent Kotlin implementation | bridge-components-android.md |
| APNs / FCM, Noticed gem, push token storage | push-notifications.md |
| TestFlight, Play Internal Testing, device URLs | deployment.md |
| Symptom → cause diagnosis | troubleshooting.md |
1. No-arg Navigator() removed — init requires configuration:
Navigator(configuration: .init(name: "main", startLocation: baseURL))
Call navigator.start() — not navigator.route(baseURL).
2. Modern Xcode App template uses SwiftUI lifecycle — no SceneDelegate exists.
Delete XxxApp.swift + ContentView.swift, create AppDelegate with @main + configurationForConnecting that assigns SceneDelegate.self programmatically.
3. No didUpdateBarButton delegate in 1.2.2 — get the host VC via:
delegate?.destination as? UIViewController
Then set navigationItem.rightBarButtonItems directly.
4. Bridge payload is in jsonData, not message.metadata — decode manually:
JSONDecoder().decode(ButtonData.self, from: Data(message.jsonData.utf8))
5. Swift 6: name override must be nonisolated
override nonisolated class var name: String { "button" }
6. Propshaft stale public/assets silently kills new bridge controllers — if a new JS file never loads: rm -rf public/assets (gitignored) and restart.
7. allow_browser versions: :modern returns 406 for path config fetch — fix: inherit path config controller from ActionController::Base.
8. Append to rightBarButtonItems (plural) — assigning to the singular overwrites existing buttons.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub cuongnc0211/rails_native_kit --plugin hotwire-native