RouteComposer: a declarative replacement for coordinators in iOS
Protocol oriented, Cocoa UI abstractions based library that helps to handle view controllers composition, navigation and deep linking tasks in the iOS application. Can be used as the universal replacement for the Coordinator pattern.
At a glance
- What is it?
- RouteComposer is a Swift library that moves iOS navigation out of view controllers and into declarative composition objects, giving every screen deep linking by default. It installs through CocoaPods or Swift Package Manager and is aimed at teams that found coordinators too rigid.
- Who is it for?
- Adopt RouteComposer when your iOS app has grown enough that navigation logic is leaking into view controllers and deep links only work for a handful of screens, since the library makes the navigation stack a declarative composition and each step deep linkable by default. Leave it alone if your app has a simple push flow, because the protocol abstraction and the setup cost buy you nothing there, and note that it does not replace the storyboard mechanism, it sits beside it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why coordinators and storyboards both feel wrong at scale
The project starts by naming the two navigation options an iOS team normally has and by listing what each one costs. The built-in mechanism provided by Apple uses storyboards and segues, and the downside listed is that navigation in storyboards is relatively static, often requires extra navigation code inside the UIViewControllers, and leads to a good deal of boilerplate. The alternative, programmatic navigation written directly in code, forces coupling between UIViewControllers, or becomes complex depending on the design pattern you pick, with Router and Coordinator named as the two common choices.
That framing is the reason RouteComposer exists as a separate pattern rather than a helper around UIKit. The stated goal is to cut an application into small logical steps of navigation, provide the navigation configuration in a declarative way, remove navigation code from UIViewControllers, and allow the composition of view controllers to vary with application state. Every UIViewController is made deep-linkable out of the box, and user facing A/B tests can be run with different navigation and layout patterns.
One design goal deserves attention because it constrains everything else: the library is meant to work side by side with any other navigation mechanism already in the app, built-in or custom. It is an addition to your architecture rather than a replacement for the whole of it.
The six composition pieces that replace a coordinator class
The architecture is expressed as a set of protocols rather than a base class you subclass, which is what makes it protocol oriented. The documentation sections for the implementation are listed as Factory, Finder, Action, Routing Interceptor, Context Task and Post Routing Task, and the whole set is described as configuration you can vary.
Factory is how a view controller gets created for a given step. Finder is how an existing view controller in the navigation stack gets located, typically so you can act on it without pushing anything. Action is the piece that actually performs a navigation, and the interceptor, the context task and the post routing task are the extension points where cross cutting behaviour gets attached, before or after the routing happens. The context task, in particular, is the hook for passing values into a composed flow, which is the piece that normally forces a coordinator to hold shared state.
The claim this architecture supports is that navigation becomes a statement of intent, in the words of the Viz.ai testimonial quoted in the project, like saying go to x with y without worrying about the current state or the stack. The same user describes replacing an entire navigation system because coordinators and other flow control libraries led to mixing application logic with navigation, or produced massive coordinator classes.
Adding RouteComposer to a project with CocoaPods or SPM
Installation is a single dependency entry, and both supported package managers are documented. With CocoaPods you add the pod to your Podfile and then run pod install.
pod 'RouteComposer'After that, any Swift file that uses the library needs the import statement.
import RouteComposerWith Swift Package Manager, which the project describes as integrated into the swift compiler, you add the dependency to the dependencies value of your Package.swift.
dependencies: [
.package(url: "https://github.com/ekazaev/route-composer", .upToNextMajor(from: "2.10.4"))
]Note the version floor written into that snippet. It is an example value, not the current release, and the recent release history runs ahead of it with 2.22.3 published on 2026-09-22 after 2.22.2 on 2026-08-18 and 2.22.1 on 2026-01-21. The upToNextMajor requirement keeps you on the 2.x line, which is what you want if you are adopting the library now and do not want to absorb a future major version migration.
The project also ships an Example app that it says covers most general use cases, and the instructions for running it are specific: clone the repo and run pod install from the Example directory first. Carthage is listed as supported too, and the SwiftUI compatibility badge suggests the library can be used alongside SwiftUI screens.
Deep linking stops being a special case
The routing model and the deep link model are the same model, which is the practical payoff. In a coordinator implementation, deep linking usually becomes a parallel code path: a URL handler parses the incoming link, works out which coordinator should own it, and drives that coordinator manually. Every new screen that should be reachable from outside therefore needs work in two places.
Here, a navigation step is a description of a destination, and the same description resolves whether it came from a tap or from a URL. The stated benefit is that every UIViewController is deep linkable out of the box, and the topic list attached to the repository includes deeplink, deeplinks, universal-links and routing-engine, alongside coordinator, factory, finder and navigation.
Universal links are covered as well, so a link that resolves through an associated domain can be handed to the same composition machinery. The pieces the documentation exposes for this are the finder and the action protocols, which let you locate the existing stack state and then perform the transition, and the routing interceptor, which can veto or rewrite a transition before it happens. That interception point is where an app can enforce a login gate, handle an unknown route, or rewrite a stale deep link to a current version of the same screen.
Swapping in step by step instead of rewriting navigation
The library is described as usable as the universal replacement for the Coordinator pattern, and its components are deliberately small so that adoption can be incremental. A step needs a factory to build the screen and an action to present it, and a navigation call becomes a composition of those steps rather than a call into a long lived coordinator object.
Two features support gradual migration. The first is the side by side claim: because RouteComposer composes view controllers and does not take over the whole app, existing pushes inside storyboards or in code can stay where they are while the screens that need deep linking or parameter passing move over. The second is the container support. The documentation has a section on container view controllers, and the library requires familiarity with UIKit's view controller navigation stack intricacies only if you intend to implement your own containers and actions, which the requirements section states plainly. Everything else, it says, has no actual requirements.
That last point is worth taking at face value and also at its word. A team can start with a factory and an action per screen and get value without custom container work. A team that needs tab based flows, split views or modal stacks will be writing those container types itself, and that is where the real effort sits.
Where RouteComposer is the wrong choice
A library like this has a floor. If your app has a short linear navigation and a handful of screens, protocol abstractions and composition objects will cost more than they save, and the README's own argument about boilerplate only bites once the navigation surface is large.
There is a second boundary worth naming: the extension points are yours to implement. Custom containers and custom actions are not provided for the general case, and the requirements section points you at UIKit navigation stack internals to build them. A team that does not have someone comfortable in UIKit's container mechanics will find the hard parts of their app are the parts the library leaves open.
A third caution is about mixing. The library works next to storyboards and next to existing custom navigation, and that is a genuine strength, but a codebase that ends up with three navigation mechanisms in parallel will have exactly the coupling problem the library was written to remove. The protocol surface also has a learning curve, as one of the quoted testers notes, and the effort of learning it is only justified if you then adopt it widely.
Version cadence, platform support and the MIT terms
The repository is not archived and the last push was on 2026-09-22, matching the date of release 2.22.3. The earlier releases show a patch and a minor bump within a few months of each other, with 2.22.1 released on 2026-01-21 and 2.22.2 on 2026-08-18. The upstream dependency declaration also constrains the major version, so a 2.x pin is what a new adopter gets.
The platform targets are stated in the badges at the top of the project page, which record a Swift 6.3 language level and an iOS range from iOS 15 to iOS 27, and a SwiftUI compatible marker. The repository ships a podspec, a Package.swift, a .swiftlint.yml and a .swiftformat file, and it uses Jazzy for API documentation, with the generated docs hosted at ekazaev.github.io/route-composer and test coverage published through Codecov. A .travis.yml file and a .github directory are also present.
The licence is MIT, which is recorded both in the repository metadata and by a LICENSE file at the root, so there is no custom terms question to settle here. The MIT grant covers use, modification and redistribution of the library source with the notice retained, which is the standard arrangement for a dependency of this kind. It says nothing about the app you build with it, and it says nothing about the assets and copy in your own targets.
Editorial conclusion
Adopt RouteComposer when your iOS app has grown enough that navigation logic is leaking into view controllers and deep links only work for a handful of screens, since the library makes the navigation stack a declarative composition and each step deep linkable by default. Leave it alone if your app has a simple push flow, because the protocol abstraction and the setup cost buy you nothing there, and note that it does not replace the storyboard mechanism, it sits beside it. Verify first that your deployment target and Swift version match the supported range, that your existing deep link URLs can be expressed as composition steps, and that you are willing to own the custom container and action protocols if your UIKit stack needs them.
Frequently asked questions
How do I install RouteComposer in an iOS project?
With CocoaPods add pod 'RouteComposer' to your Podfile and run pod install, then import RouteComposer in the Swift files that use it. With Swift Package Manager add the .package(url: "https://github.com/ekazaev/route-composer", .upToNextMajor(from: "2.10.4")) entry to the dependencies value of your Package.swift.
Does RouteComposer replace the Coordinator pattern?
The project presents it as the universal replacement for the Coordinator pattern, built on protocol abstractions such as Factory, Finder, Action, Routing Interceptor, Context Task and Post Routing Task. It is also designed to work alongside storyboard based or custom navigation rather than requiring you to remove it.
How does RouteComposer handle deep links and universal links?
Because a navigation step is a declarative description of a destination, the same composition resolves a link as a tap, and every UIViewController is deep linkable out of the box. The routing interceptor is the documented extension point for handling or rewriting a transition before it happens.
What do I need to know to use RouteComposer?
The requirements section states there are no actual requirements to use the library. It adds that if you implement custom containers and actions you should be familiar with the library concepts and with UIKit's view controller navigation stack intricacies.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ekazaev-route-composer)Was this useful?