Hotwire Native v1.3
Lazy loading tabs, UISearchTab, Large Titles, custom error views, and a whole lotta bug fixes.
Hey everyone, Hotwire Native v1.3 just dropped with a huge release notes entry.
And that’s just for iOS! Here’s the stuff that matters, including the breaking changes you’ll need to accommodate in your app to upgrade today.
iOS
iOS saw the majority of the work this release, mostly focused on adding customization options to the included native pieces and reaching API parity with Android.
Lazy loading native tabs
Native tabs can now be lazy-loaded, meaning launching the app won’t hit your server with 5+ network requests. When enabled, each tab’s content loads the first time the user opens it. Note that this is a breaking change, as it was moved from Hotwire.config.lazyLoadTabs.
HotwireTabBarController(lazyLoadTabs: true)Search tabs
For users running iOS 26, you can use the new UISearchTab to show a floating tab off to the right. Tapping this opens the tab’s content as usual. The only difference is the special placement.
HotwireTab(
title: “Search”,
image: UIImage(systemName: “magnifyingglass”),
url: URL(string: “...”)!,
isSearchTab: true
)Large titles
A long-awaited fix for “large titles” was also merged, enabling proper behavior when customizing the navigation controller used by Hotwire Native.
class CustomNavigationController: HotwireNavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.prefersLargeTitles = true
}
}
Hotwire.config.defaultNavigationController = { CustomNavigationController() }Custom error views
Native error views can now be fully customized, even with SwiftUI.
Hotwire.config.makeCustomErrorView = { error, handler in
AnyView(MyErrorView(error: error, onRetry: handler))
}
struct MyErrorView: View {
let error: Error
let onRetry: ErrorPresenter.Handler?
var body: some View {
// ...
}
}Also, TurboError is gone, replaced by a structured HotwireNativeError (HTTPError / LoadError / WebError), and a retry handler is now always supplied. So if you referenced those directly in your codebase you’ll need to update them.
There were also a bunch of bug fixes that were finally merged, including commits from six new contributors! Check out the full release notes for all the details.
Android
Android’s big improvement was the addition of lazy-loaded tabs, to match the behavior on iOS. There were also a lot of under-the-hood bug fixes and cleanup, including resolving some weird crashes that one of my clients was experiencing.
The only breaking changes for Android are around HotwireDestination.customRouteDecision() and some logging cleanup.
Hotwire.config.debugLoggingEnabled is removed, replaced by a pluggable Hotwire.config.logger. Set logger.logLevel = HotwireLogLevel.DEBUG for debug output. See the full release notes for more.
Demo app
The Hotwire Native demo app was improved to work with the new changes across both platforms and now acts as a test bed for reproducing bugs. This should make it a bit easier for me and the other maintainers of Hotwire Native to identify and fix issues faster.
If you upgrade to v1.3 and run into any issues please let me know. I’m sure v1.3.1 isn’t far behind!
P.S. Who’s heading to RubyConf next week? I’m hosting a Ruby Native workshop on Wednesday and I’d love to meet you IRL! Hit reply and let me know so we can grab a beverage together.




