widgetkit

dpearson2699/swift-ios-skills · updated Apr 8, 2026

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill widgetkit
0 commentsdiscussion
summary

$22

skill.md

WidgetKit and ActivityKit

Build home screen widgets, Lock Screen widgets, Live Activities, Dynamic Island presentations, Control Center controls, and StandBy surfaces for iOS 26+.

See references/widgetkit-advanced.md for timeline strategies, push-based updates, Xcode setup, and advanced patterns.

Contents

Workflow

1. Create a new widget

  1. Add a Widget Extension target in Xcode (File > New > Target > Widget Extension).
  2. Enable App Groups for shared data between the app and widget extension.
  3. Define a TimelineEntry struct with a date property and display data.
  4. Implement a TimelineProvider (static) or AppIntentTimelineProvider (configurable).
  5. Build the widget view using SwiftUI, adapting layout per WidgetFamily.
  6. Declare the Widget conforming struct with a configuration and supported families.
  7. Register all widgets in a WidgetBundle annotated with @main.

2. Add a Live Activity

  1. Define an ActivityAttributes struct with a nested ContentState.
  2. Add NSSupportsLiveActivities = YES to the app's Info.plist.
  3. Create an ActivityConfiguration in the widget bundle with Lock Screen content and Dynamic Island closures.
  4. Start the activity with Activity.request(attributes:content:pushType:).
  5. Update with activity.update(_:) and end with activity.end(_:dismissalPolicy:).

3. Add a Control Center control

  1. Define an AppIntent for the action.
  2. Create a ControlWidgetButton or ControlWidgetToggle in the widget bundle.
  3. Use StaticControlConfiguration or AppIntentControlConfiguration.

4. Review existing widget code

Run through the Review Checklist at the end of this document.

Widget Protocol and WidgetBundle

Widget

Every widget conforms to the Widget protocol and returns a WidgetConfiguration from its body.

struct OrderStatusWidget: Widget {
    let kind: String = "OrderStatusWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: OrderProvider()) { entry in
            OrderWidgetView(entry: entry)
        }
        .configurationDisplayName("Order Status")
        .description("Track your current order.")
        .supportedFamilies([.systemSmall, .systemMedium])
    }
}

WidgetBundle

Use WidgetBundle to expose multiple widgets from a single extension.

@main
struct MyAppWidgets: WidgetBundle {
    var body: some Widget {
        OrderStatusWidget()
        FavoritesWidget()
        DeliveryActivityWidget()   // Live Activity
        QuickActionControl()       // Control Center
    }
}

Configuration Types

Use StaticConfiguration for non-configurable widgets. Use AppIntentConfiguration (recommended) for configurable widgets paired with AppIntentTimelineProvider.

// Static
StaticConfiguration(kind: "MyWidget", provider: MyProvider()) { entry in
    MyWidgetView(entry: entry)
}
// Configurable
AppIntentConfiguration(kind: "ConfigWidget", intent: SelectCategoryIntent.self,
                       provider: CategoryProvider()) { entry in
    CategoryWidgetView(entry: entry)
}

Shared Modifiers

Modifier Purpose
.configurationDisplayName(_:) Name shown in the widget gallery
.description(_:) Description shown in the widget gallery
.supportedFamilies(_:) Array of WidgetFamily values
.supplementalActivityFamilies(_:) Live Activity sizes (.small, .medium)

TimelineProvider

For static (non-configurable) widgets. Uses completion handlers. Three required methods:

struct WeatherProvider: TimelineProvider {
    typealias Entry = WeatherEntry

    func placeholder(in context: Context) -> WeatherEntry {
        WeatherEntry(date: .now, temperature: 72, condition: "Sunny")
    }

    func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) {
        let entry = context.isPreview
            ? placeholder(in: context)
            : WeatherEntry(date: .now, temperature: currentTemp, condition: currentCondition)
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {
        Task {
            let weather = await WeatherService.shared.fetch()
            let entry = WeatherEntry(date: .now, temperature: weather.temp, condition: weather.condition)
            let nextUpdate = Calendar.current.date(byAdding: .hour, value: 1, to: .now)!
            completion(Timeline(entries: [entry], policy: .after(nextUpdate)))
        }
    }
}

AppIntentTimelineProvider

For configurable widgets. Uses async/await natively. Receives user intent configuration.

struct CategoryProvider: AppIntentTimelineProvider {
    typealias Entry = CategoryEntry
    typealias Intent = SelectCategoryIntent

    func placeholder(in context: Context) -> CategoryEntry {
        CategoryEntry(date: .now, categoryName: "Sample", items: [])
    }

    func snapshot(for config: SelectCategoryIntent, in context: Context) async -> CategoryEntry {
        let items = await DataStore.shared.items(for: config.category)
        return CategoryEntry(date: .now, categoryName: config.category.name, items: items)
    }

    func timeline(for config: SelectCategoryIntent

Discussion

Product Hunt–style comments (not star reviews)
  • No comments yet — start the thread.
general reviews

Ratings

4.766 reviews
  • Shikha Mishra· Dec 28, 2024

    Registry listing for widgetkit matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Nia Bhatia· Dec 28, 2024

    Useful defaults in widgetkit — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Henry Farah· Dec 16, 2024

    Registry listing for widgetkit matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Harper Desai· Dec 4, 2024

    We added widgetkit from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Camila Gonzalez· Dec 4, 2024

    I recommend widgetkit for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Anika Kapoor· Nov 23, 2024

    widgetkit fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.

  • Luis Reddy· Nov 23, 2024

    Useful defaults in widgetkit — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Rahul Santra· Nov 19, 2024

    Keeps context tight: widgetkit is the kind of skill you can hand to a new teammate without a long onboarding doc.

  • Daniel Robinson· Nov 19, 2024

    I recommend widgetkit for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Chen Rahman· Nov 7, 2024

    Keeps context tight: widgetkit is the kind of skill you can hand to a new teammate without a long onboarding doc.

showing 1-10 of 66

1 / 7