Skip to main content

Conventions

The conventions below are enforced by code review, not tooling. If you add code that breaks them, expect a follow-up PR.

Target placement

Every new file lives in exactly one target:

File needs…TargetFolder
Only Foundation (or pure Swift)MatrixSwiftBaseCoreSources/MatrixSwiftBaseCore/
SwiftUI / UIKit / AppKit / PhotosUI / MessageUI / LottieMatrixSwiftBaseUISources/MatrixSwiftBaseUI/

Rules:

  • UI code may import MatrixSwiftBaseCore. Core code must never reference UI types.
  • If a helper has a pure-Foundation core and a SwiftUI sugar wrapper, split them: put the Foundation part in Core, the SwiftUI sugar in UI.
  • A consumer importing only Core never compiles or links any UI code. Don't break this invariant.

File naming

KindPatternExample
Helper<Topic>Helper.swiftDateHelper.swift, CryptoHelper.swift
Extension<Type>Ext.swiftArrayExt.swift, DateExt.swift
Manager (stateful, often @MainActor / ObservableObject)<Name>Manager.swiftKeychainManager.swift
SwiftUI componentdescriptive PascalCaseCardContainer.swift, LoadingView.swift
ViewModifier<Name>Modifier.swiftBorderRadiusModifier.swift
Style<Name>Style.swiftPressableButtonStyle.swift

Helper class shape

public final class FooHelper {
public init() {}
public static func bar() { /* … */ }
}

Static methods unless state is needed. The public init() {} is there so consumers can mock with subclasses if they need to.

Platform guards

The library targets four platforms. When using an API that doesn't exist everywhere, guard:

#if canImport(UIKit)
import UIKit
// UIKit-specific code
#elseif canImport(AppKit)
import AppKit
// AppKit-specific code
#endif

#if os(iOS) || os(tvOS) || os(visionOS)
// iOS-family only
#endif

#if !os(watchOS)
// Everything except watchOS
#endif

Prefer canImport(UIKit) over os(iOS) when you only need the framework to be present (matters for Mac Catalyst and visionOS).

Commit style

Conventional Commits, enforced by the pre-commit hook (feat:, fix:, chore:, docs:, refactor:, test:, build:, ci:, perf:, style:, revert:).

One-time hook install:

brew install pre-commit
pre-commit install --install-hooks

This wires up swiftlint --fix on commit and commit-message validation.

Linting

.swiftlint.yml is intentionally lenient — many rules disabled (force_unwrapping, line_length, identifier_name, cyclomatic_complexity, etc.). Don't re-enable disabled rules without asking. file_length warns at 500 lines, errors at 1200.