Skip to content
AB

How I Structure a Large SwiftUI Application by Feature

Keep state, views, domain rules, and data implementations close to the product capability they serve.

Ashish BhakhandPublished

Folders named Views, Models, and Services work until each contains dozens of unrelated files. Understanding one feature then requires searching the entire project.

I organize SwiftUI code around product capabilities:

Code
Features/Workout/
  Store/
  Views/
  Components/
  Domain/
  Data/

Store owns state transitions and effect coordination. Views render state and send actions. Domain contains pure decisions. Data implements network, persistence, and cache boundaries.

Shared code must earn its place in Core. Networking primitives and typed errors are cross-cutting. A workout formatter still belongs to Workout even if another screen happens to reuse it.

The dependency direction matters more than folder names:

Code
View → Feature → Client boundary → API / SwiftData / cache

Views never perform storage or network work. Reducers do not construct concrete services. Feature clients hide implementation choices while keeping available operations explicit.

I also avoid creating every directory for a small feature. A simple screen may need one feature file and one view. Structure should reveal real complexity, not predict imaginary complexity.

Feature-first organization improves deletion and ownership. Removing a product capability has a visible boundary, and opening its folder shows the complete flow. SwiftUI supplies the rendering system; a growing product still needs a map for where decisions belong.

← Back to all writing