Self-contained units of functionality with explicit contracts.
A Forsetti module is a structured bundle that declares its identity, requirements, capabilities, and UI contributions through typed Swift protocols. The runtime manages the full module lifecycle from discovery through deactivation.
Anatomy of a Module
Every module conforms to a core protocol that the runtime uses to discover, validate, and activate it.
protocol ForsettiModule {
/// Unique module identifier
var identifier: ModuleIdentifier { get }
/// Module version
var version: SemanticVersion { get }
/// Platform and host compatibility requirements
var compatibility: CompatibilityDescriptor { get }
/// Required entitlements for activation
var entitlements: [Entitlement] { get }
/// Dependencies on other modules
var dependencies: [ModuleDependency] { get }
/// Lifecycle callbacks
func activate(context: ActivationContext) async throws
func deactivate() async
}
Module Contracts
Identity
Every module has a unique identifier and semantic version. The identifier is a reverse-domain string that prevents naming collisions. The version follows semantic versioning and is used for dependency resolution and compatibility checks.
Compatibility Descriptor
Declares the minimum and maximum platform versions, required OS features, and host application version ranges. The runtime evaluates these constraints before activation and rejects modules that cannot run in the current environment.
Entitlements
Modules declare the entitlements they require for activation. Entitlements are named capabilities that the host application grants or revokes. This enables feature gating, tiered licensing, and role-based access control at the module level.
Dependencies
Modules can declare dependencies on other modules by identifier and version range. The runtime resolves dependencies before activation and ensures modules are activated in the correct order. Circular dependencies are detected and rejected.
Module Lifecycle
A module transitions through defined states as the runtime processes it. Each state has clear entry and exit conditions.
Module bundle found and manifest read. The runtime knows it exists but has not evaluated it.
Compatibility checks passed. The module is confirmed to be structurally sound and compatible with the current environment.
Required entitlements are present. The module is authorized for activation under the current policy.
Module is fully initialized, services are registered, and UI contributions are available to the host application.
Module has been gracefully shut down. Services are unregistered, UI contributions withdrawn, and resources released.
UI Contribution Model
Modules contribute SwiftUI views to host-defined extension points through a structured contribution protocol.
Extension Points
The host application declares named extension points in its UI hierarchy. Extension points define the type of content they accept, ordering rules, and layout constraints.
Contributions
Modules register contributions that target specific extension points. Each contribution provides a SwiftUI view factory, a priority value, and metadata the host can use for filtering or grouping.
Mediation
The runtime collects contributions from all active modules, resolves ordering, and delivers them to the host. The host renders contributions within its own layout without knowing which module provided each one.
// Module contributing a sidebar item
struct AnalyticsModule: ForsettiModule {
func activate(context: ActivationContext) async throws {
context.contribute(
to: .sidebar,
priority: 100
) {
AnalyticsSidebarView()
}
}
}
Standard Extension Points
| Extension Point | Description | Content Type |
|---|---|---|
.sidebar |
Primary sidebar navigation items | NavigationItem |
.toolbar |
Toolbar actions and controls | ToolbarContent |
.dashboard |
Dashboard panels and widgets | DashboardPanel |
.settings |
Module settings and preferences | SettingsPane |
.inspector |
Inspector/detail panel content | InspectorContent |
.menu |
Application menu commands | MenuCommand |
Start building modules.
Read the documentation for step-by-step guides on creating your first module, defining contracts, and contributing UI.
