Template: Feature Module
A self-contained, layered feature packaged as a Swift Package. Copy this structure for a new feature. See architecture/feature_module_architecture.md.
Folder Structure
text
{{Feature}}Feature/
├── Package.swift
├── Sources/{{Feature}}Feature/
│ ├── {{Feature}}Feature.swift // public entry: factory + root view
│ ├── Domain/
│ │ ├── {{Entity}}.swift
│ │ ├── {{Feature}}Repository.swift // protocol
│ │ └── Fetch{{Entity}}UseCase.swift
│ ├── Data/
│ │ ├── {{Entity}}DTO.swift
│ │ ├── {{Entity}}Mapper.swift
│ │ └── Remote{{Feature}}Repository.swift
│ └── Presentation/
│ ├── {{Feature}}ViewModel.swift
│ ├── {{Feature}}View.swift
│ └── Subviews/
└── Tests/{{Feature}}FeatureTests/
├── Fetch{{Entity}}UseCaseTests.swift
├── {{Feature}}ViewModelTests.swift
└── {{Entity}}MapperTests.swiftNaming Conventions
- Module:
{{Feature}}Feature(e.g.AccountsFeature). - One public entry type exposing a factory; everything else
internal. - Files named after their primary type.
Package.swift
swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "{{Feature}}Feature",
platforms: [.iOS(.v16)],
products: [.library(name: "{{Feature}}Feature", targets: ["{{Feature}}Feature"])],
dependencies: [
.package(path: "../CoreNetworking"),
.package(path: "../DesignSystem")
],
targets: [
.target(name: "{{Feature}}Feature", dependencies: ["CoreNetworking", "DesignSystem"]),
.testTarget(name: "{{Feature}}FeatureTests", dependencies: ["{{Feature}}Feature"])
]
)Public Entry (DI seam)
swift
import SwiftUI
import CoreNetworking
public enum {{Feature}}Feature {
public static func makeRootView(client: APIClient) -> some View {
let repository = Remote{{Feature}}Repository(client: client)
let useCase = Fetch{{Entity}}UseCase(repository: repository)
return {{Feature}}View(viewModel: {{Feature}}ViewModel(fetch: useCase))
}
}Conventions Embedded Here
- DI: dependencies passed into the factory; no singletons inside the module.
- Error handling: repository throws typed errors; ViewModel maps to a state enum.
- Testing: Domain + Presentation unit-tested; Data mapping tested with fixtures.
See the layer-specific templates: clean_architecture_feature, repository_layer, swiftui_screen, unit_test_template.