Role-Based UI Separation and Mobile Optimization in a Rails 8 + Hotwire Native App

Running an iOS app built with Rails 8 + Hotwire Native, I hit a series of issues in a single day. What started as a small UI distortion spiraled into a full permission system redesign. Here’s the record. 1. Card Images Distorted in Mobile WebView Symptom Tournament discovery cards looked fine in a desktop browser, but badges and icons were squished inside the iOS app’s WKWebView (375px viewport). Root Cause The deployed view used a desktop-first layout (max-w-[1400px], responsive grid). The WKWebView rendered all of it in 375px, causing badge overlap. ...

2026-03-17 · 4 min read · Seunghan
Hotwire Native Ios Tab Bar Patterns

Hotwire Native iOS Tab Bar App — HotwireTabBarController Implementation and Debugging

Here are the problems encountered when switching from a single Navigator to the HotwireTabBarController pattern while wrapping a Rails app with Hotwire Native. Bugs that were invisible in the simulator surfaced on TestFlight, and local dev environment settings got tangled – multiple points where time was wasted. 1. HotwireTabBarController Basic Structure Instead of a single Navigator, each tab has its own independent Navigator and WKWebView. // AppTab.swift enum AppTab: String, CaseIterable { case home, ai, request var systemImage: String { switch self { case .home: return "house" case .ai: return "message" case .request: return "checkmark.circle" } } var selectedSystemImage: String { switch self { case .home: return "house.fill" case .ai: return "message.fill" case .request: return "checkmark.circle.fill" } } var url: URL { let base = AppDelegate.baseURL switch self { case .home: return base.appendingPathComponent("dashboard") case .ai: return base.appendingPathComponent("conversations") case .request: return base.appendingPathComponent("service_requests") } } var hotwireTab: HotwireTab { HotwireTab( title: "", image: UIImage(systemName: systemImage)!, selectedImage: UIImage(systemName: selectedSystemImage)!, url: url ) } } // SceneController.swift core part private lazy var tabBarController: HotwireTabBarController = { let controller = HotwireTabBarController(navigatorDelegate: self) controller.load(AppTab.allCases.map(\.hotwireTab)) // Show only tab icons, remove text controller.viewControllers?.forEach { vc in vc.tabBarItem.title = nil vc.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) (vc as? UINavigationController)?.delegate = self } return controller }() To remove tab titles and keep only icons, both tabBarItem.title = nil and imageInsets adjustment are needed. Setting only title to nil leaves the icon position unchanged, looking awkward. ...

2025-12-26 · 6 min read · Seunghan
Hotwire Native Webview 8 Fixes

Hotwire Native WebView Debugging Collection — 8 Common Issues When Wrapping Rails WebView in Native Apps

When wrapping a Rails app with Hotwire Native (Turbo Native) to build iOS/Android native apps, there are quite a few things that work fine in the browser but behave strangely in WebView. Here are the issues encountered during actual development and the fixes applied, all in one place. Most can be resolved with a few lines of CSS or one line in the path configuration JSON. 1. Double-Tap Zoom / 300ms Click Delay Symptoms Double-tapping a button quickly zooms the screen. Even a single tap feels slightly delayed (about 300ms). ...

2025-11-25 · 5 min read · Seunghan
Privacy Policy Terms Disclaimer Contact