Skip to content

Microapps Architecture: Feature Modules (Swift)

A SwiftUI guide for coding agents. Also covers feature module spm, foundation module design system, thin app coordinator, decoupled feature packages, microapp per feature.

Part two of the microapps series splits modules into two kinds. Foundation modules, such as the design system or networking layer, are imported everywhere. Feature modules each implement one complete product feature and can ship alone as a microapp.

Declaring a Feature Module

A feature module is one more target in the shared package, depending on the foundation modules it needs.

let package = Package(
  name: "MyAppLibrary",
  platforms: [.iOS(.v15)],
  products: [
    .library(name: "DesignSystem", targets: ["DesignSystem"]),
    .library(name: "Onboarding", targets: ["Onboarding"])
  ],
  targets: [
    .target(name: "DesignSystem"),
    .target(name: "Onboarding", dependencies: ["DesignSystem"]),
  ]
)

The module's public surface needs explicit public types and initializers, because memberwise initializers are internal by default:

public struct OnboardingItem: Hashable {
  let systemImage: String
  let title: String
  let body: String

  public init(systemImage: String, title: String, body: String) {
    self.systemImage = systemImage
    self.title = title
    self.body = body
  }
}

The view imports the foundation module for shared styles, for example import DesignSystem and .buttonStyle(.main) on its call-to-action button.

The App Target Is a Thin Coordinator

All feature logic lives in the modules. The app target only instantiates features and navigates between them.

import SwiftUI
import Onboarding
import DailySummary

struct RootView: View {
  @AppStorage("isFirstLaunch")
  var isFirstLaunch: Bool = true

  var body: some View {
    NavigationView {
      DailySummaryView(date: .now)
    }
    .sheet(isPresented: $isFirstLaunch) {
      OnboardingView(items: [
        .init(systemImage: "pills", title: "Pills", body: "Track your pills"),
        .init(systemImage: "heart", title: "Monitor", body: "Monitor your heart")
      ]) {
        isFirstLaunch = false
      }
    }
  }
}

A feature module can span several screens, for example a whole checkout flow. Because it is decoupled, a team can wrap it in a tiny host app and ship it through TestFlight for early QA feedback, without waiting for the rest of the product.

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-microapps-architecture-in-swift-feature-modules" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems