# iOS-Modular-Architecture: an OLX template for turning app features into pods

> This repository is a template iOS application in which features are extracted into local CocoaPods under a DevPods folder, with the README documenting the eight manual steps to carve a module out of the app, the trade-off being that the process is manual and the write-up lives in a Medium post rather than in the code.

**kudoleh/iOS-Modular-Architecture** — Template iOS application using Modular Architecture

- Repository: https://github.com/kudoleh/iOS-Modular-Architecture
- Website: https://tech.olx.com/modular-architecture-in-ios-c1a1e3bff8e9
- Stars: 850 · Forks: 135
- Language: Swift
- License: not declared
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/kudoleh-ios-modular-architecture

## A reference app where features live in DevPods

The repository is a template iOS application implemented with Modular Architecture, published by OLX engineering. The README states it can be used as a template project by replacing the item name Movie, which tells you the reference implementation is a movie search application and that the module structure is meant to be carried into another project rather than studied as an app.

The idea is that each feature becomes its own pod. The top level of the repository shows the shape of the result: an App/ directory for the application target, an App.xcodeproj and App.xcworkspace for the Xcode side, a DevPods/ directory holding the local module pods, a Pods/ directory, a Podfile with a Podfile.lock, plus AppUITests, SnapshotTests, a fastlane directory and a Gemfile with a lock file.

The dependency diagrams in the README, the module dependencies image and the version showing an Authentication module included as an initial scaling step, are the argument of the project. The images exist because the argument does not fit in a README, which is also where the deeper explanation lives: the README repeatedly points to a Medium post from the OLX engineering channel rather than documenting the rationale inline.

That is worth saying plainly before anything else. The repository is the artifact, the Medium post is the explanation, and the two videos linked from the README show the extraction of a networking service module and of the movies search feature module.

## The DevPods folder and the workspace as the assembly point

The mechanics turn on two directories and one file.

DevPods is where the modules live as local pods, and the README has you create it in the same folder as the app project with mkdir DevPods. Each module is generated with pod lib create ModuleName, choosing iOS as the platform, Swift as the language and Yes for including a demo app, with the test framework and view based testing skipped.

The Podfile is where the dependency graph is declared, and the README's first step is to set it up correctly: run pod init, uncomment platform :ios, '9.0' and change '9.0' to '14.0' or '15.0', add workspace 'AppName.xcworkspace' and project 'AppName.xcodeproj', then run pod install.

The template then makes the app workspace the single place where everything is built. The README's step 5 adds the module's example target to the workspace so a module can be developed from the same main app workspace:

```ruby
		target 'ModuleName_Example' do
			use_frameworks!
			project 'DevPods/ModuleName/Example/ModuleName.xcodeproj'
			
			module_name_pod
		end
```

with the pod itself referenced by a helper method in the Podfile:

```ruby
		def module_name_pod
		    pod 'ModuleName', :path => 'DevPods/ModuleName'
		end
```

That pattern, a local path dependency plus an example target in the app workspace, is what lets one Xcode workspace host the app and every module, which is the practical requirement that makes modularisation workable on a real team.

## Extracting a module takes eight documented steps

The README's core contribution is the step by step procedure, annotated with video timestamps.

Steps 1 and 2 cover setup, the CocoaPods initialisation of the app project and the creation of the DevPods folder and the module. Step 3 is fixing the generated example project, setting In Deployment Info to iOS 14.0 or 15.0, setting the Swift Language Version to Swift 5, removing the test target and test folder, and closing the example project, which the README notes is otherwise impossible from the app workspace.

Step 4 is cleanup of the generated DevPods/ModuleName folder: showing hidden files with Cmd and Shift and a period, then deleting the .git, .gitignore and .travis.yamls files along with the _Pod.xcodeproj, the Example Podfile, Podfile.lock, Pods and the example workspace.

Step 5 edits the app Podfile as shown above, and also moves the nested test targets outside the target 'App' so that the app target does not inherit the module's test dependencies.

Step 6 is the actual move. The Assets and Classes folders in the module are replaced by a single Module folder, and every file belonging to the feature, .swift files, .xcassets, .storyboard and .xcdatamodeld among them, is moved from the main app into that folder and deleted from the app target. The README advises doing this manually rather than through Xcode.

Step 7 covers dependencies and step 8 covers the compile errors that follow: adding import ModuleName where needed, changing internal types and functions to public, and re-initialising resources.

## The podspec decides what the module owns

The module's public surface is declared in its podspec, and the README is explicit that two settings matter.

The deployment target is set with s.ios.deployment_target = '14.0' or 15.0. More important is the source_files and resources pair, which is rewritten to point at the moved folder:

```ruby
	            s.source_files = 'MoviesSearch/Module/**/*.{swift}'
	            s.resources = "MoviesSearch/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}"
```

The resource list is a checklist of what a feature module typically owns: asset catalogs, JSON, storyboards, nibs and Core Data models.

Two caveats come with it. If the module has a Core Data model with the xcdatamodel extension, it has to be converted to xcdatamodeld by adding a model version. And when you create a new group inside Development Pods/ModuleName with Xcode, Xcode places the folder in the wrong place outside the Module folder, so it has to be moved by hand in Finder and then pod install has to be run again.

That is the texture of the whole approach. The rules are simple, but the tool does not enforce them, and the failure mode is a folder in the wrong place that only shows up at build time.

## Dependency direction, and the protocol escape hatch

Dependencies are declared in the module's podspec, and the README shows both kinds side by side:

```ruby
        # internal dependency (module you have created before)
        s.dependency 'ModuleName2' 

        # external dependency 3rd party framework 
        s.dependency 'PromiseKit'
```

An internal dependency points at a module you extracted earlier, and an external one at a third party framework. Both are podspec declarations, so the graph is described in one place per module.

The interesting case is the one where the dependency is not ready. The README says that if you have not yet extracted a dependency and need it in this module, you can delegate the functionality to the main app: create an interface using a protocol and implement it inside the main app, and it will be injected from the main app into the DIContainer of the module.

The example is concrete. If a module needs to open a chat, you create a protocol interface inside the module with a function openChat(forUserId:inView:) and implement it in the main app. Closures or delegation can be used instead.

This is the part of the design that makes the template work in practice rather than in theory. A strict module graph is the destination, but the destination is reached through a dependency injection container, and a module can ask for something the app has not yet given it. The cost is that protocol boundaries drawn under time pressure tend to leak, and the README does not say what happens when two modules need the same delegated capability.

## Snapshot tests are pinned to one simulator

The requirements section is where this repository stops being a pure template.

The toolchain requirements are Xcode 14+, Swift 5.7+, iOS 15.0+ and CocoaPods 1.16+. The snapshot test detail is more specific still: the reference images in SnapshotTests/ReferenceImages_64 are recorded on the iPhone 17e simulator at 390 by 844 pt. The README tells you to run the tests on that device, or to re-record them, by setting recordMode = true in MoviesListViewTests, after changing the UI or the simulator.

That is a normal, well known property of snapshot testing, but it has a practical consequence for anyone adopting this repository: the reference images are not portable. On a different simulator, a different device size or a different rendering of a component, the tests will fail until someone re-records them, and the re-recorded images become part of your commit.

The repository also carries a fastlane directory, a Gemfile with a lock file for the Ruby tooling, and a .travis.yml, which points to continuous integration having been configured in the Travis era rather than the current GitHub Actions default that most new projects inherit.

The licence field for the project is recorded as unknown and there is no licence file among the top level entries, which is worth raising with the authors before you copy the structure into a proprietary app. There are no GitHub releases, and the last push was on 2026-10-12.

## Conclusion

iOS-Modular-Architecture fits an iOS team that wants a concrete, worked example of feature modules as local pods, and it fits a team that already uses CocoaPods and is willing to follow a manual eight step procedure to move a feature across. It is the wrong choice if you need Swift Package Manager, if you want the module boundary to be enforced by the compiler rather than by review, or if your team cannot absorb a workflow where every extracted feature needs podspec edits and a Podfile change. Before adopting it, read the Medium post that the README links repeatedly, and confirm the toolchain matches, since the requirements are Xcode 14+, Swift 5.7+, iOS 15.0+ and CocoaPods 1.16+.

## FAQ

### What is the kudoleh iOS-Modular-Architecture repository?

It is a template iOS application implemented with Modular Architecture, from OLX engineering, that can be used as a starting point by replacing the item name Movie. Features are extracted into local CocoaPods held in a DevPods folder, and the README documents the procedure with linked videos.

### How do you add a new module to this iOS modular architecture template?

The README gives eight steps: set up the app project with pod init and pod install, create a DevPods folder and a module with pod lib create ModuleName, fix the generated example project's deployment target and Swift version, clean up the generated files, edit the app Podfile to reference the local pod and add the example target, move the feature files into a Module folder and update the podspec, declare internal and external dependencies, and finally fix the resulting compile errors by importing the module and marking needed types public.

### How do you handle a module dependency that has not been extracted yet?

The README says to delegate that functionality to the main app: create an interface using a protocol inside the module, implement it in the main app, and it will be injected from the main app into the DIContainer of the module. Closures or delegation can be used as well.

## Sources

- [Issues](https://github.com/kudoleh/iOS-Modular-Architecture/issues)
- [kudoleh/iOS-Modular-Architecture on GitHub](https://github.com/kudoleh/iOS-Modular-Architecture)
- [Project website](https://tech.olx.com/modular-architecture-in-ios-c1a1e3bff8e9)
- [README](https://github.com/kudoleh/iOS-Modular-Architecture/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kudoleh-ios-modular-architecture
