Skip to content

Microapps Architecture: SPM Basics (Swift)

A SwiftUI guide for coding agents. Also covers swift package manager modules, package swift targets, modularize ios app, reduce compile time xcode, feature module setup, public access modifier module.

Microapps architecture splits an app into one Swift Package Manager module per feature, so Xcode recompiles only changed modules and each feature can run as its own app. This first part sets up the package that holds every module.

One Package, Many Modules

Create one Swift package (File -> New -> Package, for example MyAppLibrary) in the project root and add it to the app project. All modules live in it, so the watch app or a widget can depend on just the modules it needs instead of the whole codebase. The package has no project file: the folder structure under Sources/ and Tests/ is the structure.

Package.swift Declares the Modules

import PackageDescription

let package = Package(
  name: "MyAppLibrary",
  platforms: [.iOS(.v15)],
  products: [
    .library(name: "DesignSystem", targets: ["DesignSystem"])
  ],
  dependencies: [
    .package(url: "https://github.com/mecid/SwiftUICharts", from: "0.6.3")
  ],
  targets: [
    .target(name: "DesignSystem", dependencies: ["SwiftUICharts"]),
    .testTarget(name: "DesignSystemTests", dependencies: ["DesignSystem"]),
  ]
)

The parts: platforms sets the supported OS versions, products lists what other projects can import, dependencies lists external packages, and targets are the modules the compiler builds independently. A module is just a folder in Sources/ whose name matches its target; tests go in a matching folder under Tests/.

Public Is the Module Boundary

Swift defaults to internal, which keeps code invisible outside its module. Mark exactly the types and functions a module means to expose with public; everything else stays private to the module, which makes the boundary explicit.

import SwiftUI

public struct MainButtonStyle: PrimitiveButtonStyle {
  public func makeBody(configuration: Configuration) -> some View {
    Button(configuration)
      .controlSize(.large)
      .buttonStyle(.borderedProminent)
  }
}

extension PrimitiveButtonStyle where Self == MainButtonStyle {
  public static var main: Self { .init() }
}

Add the DesignSystem library under the app target's Frameworks, Libraries, and Embedded Content to import it. Later parts of the series cover feature modules, resources and localization, and dependency injection.

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-spm-basics" })
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