本文へ移動
cccskills
無料GitHub で公開

relevancekit

Increase widget visibility on Apple Watch using RelevanceKit. Use when providing contextual relevance signals for watchOS widgets, declaring time-based or location-based relevance, combining multiple relevance providers, or helping the system surface the right widget at the right time on watchOS 26.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md15.0 KB
  • references/relevancekit-patterns.md19.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

RelevanceKit

Provide on-device contextual clues that increase a widget's visibility in the Smart Stack on Apple Watch. RelevanceKit tells the system when a widget is relevant -- by time, location, fitness state, sleep schedule, or connected hardware -- so the Smart Stack can surface the right widget at the right moment. Targets Swift 6.3 / watchOS 26+.

Beta-sensitive. RelevanceKit shipped with watchOS 26. Re-check Apple documentation before making strong claims about API availability or behavior.

See references/relevancekit-patterns.md for complete code patterns including relevant widgets, timeline provider integration, grouping, previews, and permission handling.

Contents

Overview

watchOS uses two mechanisms to determine widget relevance in the Smart Stack:

  1. Timeline provider relevance -- implement relevance() on an existing AppIntentTimelineProvider to attach RelevantContext clues to timeline entries. Available across platforms; only watchOS acts on the data.
  2. Relevant widget -- use RelevanceConfiguration with a RelevanceEntriesProvider to build a widget driven entirely by relevance clues. The system creates individual Smart Stack cards per relevant entry. watchOS 26+ only.

Choose a timeline provider when the widget always has data to show and relevance is supplementary. Choose a relevant widget when the widget should only appear when conditions match, or when multiple cards should appear simultaneously (e.g., several upcoming calendar events).

Key Types

TypeModuleRole
RelevantContextRelevanceKitA contextual clue (date, location, fitness, sleep, hardware)
WidgetRelevanceWidgetKitCollection of relevance attributes for a widget kind
WidgetRelevanceAttributeWidgetKitPairs a widget configuration with a RelevantContext
WidgetRelevanceGroupWidgetKitControls grouping behavior in the Smart Stack
RelevanceConfigurationWidgetKitWidget configuration driven by relevance clues (watchOS 26+)
RelevanceEntriesProviderWidgetKitProvides entries for a relevance-configured widget (watchOS 26+)
RelevanceEntryWidgetKitData needed to render one relevant widget card (watchOS 26+)

Setup

Import

import RelevanceKit
import WidgetKit

Platform Availability

RelevantContext is declared across platforms (iOS 17+, watchOS 10+), but RelevanceKit functionality only takes effect on watchOS. Calling the API on other platforms has no effect. RelevanceConfiguration, RelevanceEntriesProvider, and RelevanceEntry are watchOS 26+ only.

Permissions

Certain relevance clues require the user to grant permission to both the app and the widget extension:

ClueRequired Permission
.location(inferred:)Location access
.location(_:) (CLRegion)Location access
.location(category:)Location access
.fitness(_:)HealthKit workout/activity rings permission
.sleep(_:)HealthKit sleepAnalysis permission
.hardware(headphones:)None
.date(...)None

Request permissions in both the main app target and the widget extension target.

Relevance Providers

Option 1: Timeline Provider with Relevance

Add a relevance() method to an existing AppIntentTimelineProvider. This approach shares code across iOS and watchOS while adding watchOS Smart Stack intelligence.

struct MyProvider: AppIntentTimelineProvider {
    // ... snapshot, timeline, placeholder ...

    func relevance() async -> WidgetRelevance<MyWidgetIntent> {
        let attributes = events.map { event in
            let context = RelevantContext.date(
                from: event.startDate,
                to: event.endDate
            )
            return WidgetRelevanceAttribute(
                configuration: MyWidgetIntent(event: event),
                context: context
            )
        }
        return WidgetRelevance(attributes)
    }
}

Option 2: RelevanceEntriesProvider (watchOS 26+)

Build a widget that only appears when conditions match. The system calls relevance() to learn when the widget matters, then calls entry() with the matching configuration to get render data.

struct MyRelevanceProvider: RelevanceEntriesProvider {
    func relevance() async -> WidgetRelevance<MyWidgetIntent> {
        let attributes = events.map { event in
            WidgetRelevanceAttribute(
                configuration: MyWidgetIntent(event: event),
                context: RelevantContext.date(event.date, kind: .scheduled)
            )
        }
        return WidgetRelevance(attributes)
    }

    func entry(
        configuration: MyWidgetIntent,
        context: Context
    ) async throws -> MyRelevanceEntry {
        if context.isPreview {
            return .preview
        }
        return MyRelevanceEntry(event: configuration.event)
    }

    func placeholder(context: Context) -> MyRelevanceEntry {
        .placeholder
    }
}

Time-Based Relevance

Time clues tell the system a widget matters at or around a specific moment.

Single Date

RelevantContext.date(eventDate)

Date with Kind

DateKind provides an additional hint about the nature of the time relevance:

KindUse
.defaultGeneral time relevance
.scheduledA scheduled event (meeting, flight)
.informationalInformation relevant around a time (weather forecast)
RelevantContext.date(meetingStart, kind: .scheduled)

Date Range

// Using from/to
RelevantContext.date(from: startDate, to: endDate)

// Using DateInterval
RelevantContext.date(interval: dateInterval, kind: .scheduled)

// Using ClosedRange
RelevantContext.date(range: startDate...endDate, kind: .default)

Location-Based Relevance

Inferred Locations

The system infers certain locations from a person's routine. No coordinates needed.

RelevantContext.location(inferred: .home)
RelevantContext.location(inferred: .work)
RelevantContext.location(inferred: .school)
RelevantContext.location(inferred: .commute)

Requires location permission in both the app and widget extension.

Specific Region

import CoreLocation

let region = CLCircularRegion(
    center: CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090),
    radius: 500,
    identifier: "apple-park"
)
RelevantContext.location(region)

Point-of-Interest Category (watchOS 26+)

Indicate relevance near any location of a given category. Returns nil if the category is unsupported.

import MapKit

if let context = RelevantContext.location(category: .beach) {
    // Widget is relevant whenever the person is near a beach
}

Fitness and Sleep Relevance

Fitness

// Relevant when activity rings are incomplete
RelevantContext.fitness(.activityRingsIncomplete)

// Relevant during an active workout
RelevantContext.fitness(.workoutActive)

Requires HealthKit workout/activity permission.

Sleep

// Relevant around bedtime
RelevantContext.sleep(.bedtime)

// Relevant around wakeup
RelevantContext.sleep(.wakeup)

Requires HealthKit sleepAnalysis permission.

Hardware Relevance

// Relevant when headphones are connected
RelevantContext.hardware(headphones: .connected)

No special permission required.

Combining Signals

Return multiple WidgetRelevanceAttribute values in the WidgetRelevance array to make a widget relevant under several different conditions.

func relevance() async -> WidgetRelevance<MyIntent> {
    var attributes: [WidgetRelevanceAttribute<MyIntent>] = []

    // Relevant during morning commute
    attributes.append(
        WidgetRelevanceAttribute(
            configuration: MyIntent(mode: .commute),
            context: .location(inferred: .commute)
        )
    )

    // Relevant at work
    attributes.append(
        WidgetRelevanceAttribute(
            configuration: MyIntent(mode: .work),
            context: .location(inferred: .work)
        )
    )

    // Relevant around a scheduled event
    for event in upcomingEvents {
        attributes.append(
            WidgetRelevanceAttribute(
                configuration: MyIntent(eventID: event.id),
                context: .date(event.date, kind: .scheduled)
            )
        )
    }

    return WidgetRelevance(attributes)
}

Order matters. Return relevance attributes ordered by priority. The system may use only a subset of the provided relevances.

Widget Integration

Relevant Widget with RelevanceConfiguration

@available(watchOS 26, *)
struct MyRelevantWidget: Widget {
    var body: some WidgetConfiguration {
        RelevanceConfiguration(
            kind: "com.example.relevant-events",
            provider: MyRelevanceProvider()
        ) { entry in
            EventWidgetView(entry: entry)
        }
        .configurationDisplayName("Events")
        .description("Shows upcoming events when relevant")
    }
}

Associating with a Timeline Widget

When both a timeline widget and a relevant widget show the same data, use associatedKind to prevent duplicate cards. The system replaces the timeline widget card with relevant widget cards when they are suggested.

RelevanceConfiguration(
    kind: "com.example.relevant-events",
    provider: MyRelevanceProvider()
) { entry in
    EventWidgetView(entry: entry)
}
.associatedKind("com.example.timeline-events")

Grouping

WidgetRelevanceGroup controls how the system groups widgets in the Smart Stack.

// Opt out of default per-app grouping so each card appears independently
WidgetRelevanceAttribute(
    configuration: intent,
    group: .ungrouped
)

// Named group -- only one widget from the group appears at a time
WidgetRelevanceAttribute(
    configuration: intent,
    group: .named("weather-alerts")
)

// Default system grouping
WidgetRelevanceAttribute(
    configuration: intent,
    group: .automatic
)

RelevantIntent (Timeline Provider Path)

When using a timeline provider, also update RelevantIntentManager so the system has relevance data between timeline refreshes.

import AppIntents

func updateRelevantIntents() async {
    let intents = events.map { event in
        RelevantIntent(
            MyWidgetIntent(event: event),
            widgetKind: "com.example.events",
            relevance: RelevantContext.date(from: event.start, to: event.end)
        )
    }
    try? await RelevantIntentManager.shared.updateRelevantIntents(intents)
}

Call this whenever relevance data changes -- not only during timeline refreshes.

Previewing Relevant Widgets

Use Xcode previews to verify appearance without simulating real conditions.

// Preview with sample entries
#Preview("Events", widget: MyRelevantWidget.self, relevanceEntries: {
    [EventEntry(event: .surfing), EventEntry(event: .meditation)]
})

// Preview with relevance configurations
#Preview("Relevance", widget: MyRelevantWidget.self, relevance: {
    WidgetRelevance([
        WidgetRelevanceAttribute(configuration: MyIntent(event: .surfing),
                                 context: .date(Date(), kind: .scheduled))
    ])
})

// Preview with the full provider
#Preview("Provider", widget: MyRelevantWidget.self,
         relevanceProvider: MyRelevanceProvider())

Testing

Enable WidgetKit Developer Mode in Settings > Developer on the watch to bypass Smart Stack rotation limits during development.

Common Mistakes

  • Ignoring return order. The system may only use a subset of relevance attributes. Return them sorted by priority (most important first).
  • Missing permissions in widget extension. Location, fitness, and sleep clues require permission in both the app and the widget extension. If only the app has permission, the clues are silently ignored.
  • Using RelevanceKit API expecting iOS behavior. The API compiles on all platforms but only has effect on watchOS.
  • Duplicate Smart Stack cards. When offering both a timeline widget and a relevant widget for the same data, use .associatedKind(_:) to prevent duplication.
  • Forgetting placeholder and preview entries. RelevanceEntriesProvider requires both placeholder(context:) and a preview branch in entry(configuration:context:) when context.isPreview is true.
  • Not calling updateRelevantIntents. When using timeline providers, calling this only inside timeline() means the system has stale relevance data between refreshes. Update whenever data changes.
  • Ignoring nil from location(category:). This factory returns an optional. Not all MKPointOfInterestCategory values are supported.

Review Checklist

  • import RelevanceKit is present alongside import WidgetKit
  • RelevantContext clues match the app's actual data model
  • Relevance attributes are ordered by priority
  • Permissions requested in both app target and widget extension for location/fitness/sleep clues
  • RelevanceEntriesProvider implements entry, placeholder, and relevance
  • context.isPreview handled in entry(configuration:context:) to return preview data
  • .associatedKind(_:) used when a timeline widget and relevant widget show the same data
  • RelevantIntentManager.updateRelevantIntents called when data changes (timeline provider path)
  • location(category:) nil return handled
  • WidgetKit Developer Mode used for testing
  • Widget previews verify appearance across display sizes

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

When the user wants to A/B test App Store product page elements to improve conversion rate. Also use when the user mentions "A/B test", "product page optimization", "test my screenshots", "test my icon", "conversion rate optimization", "CPP", or "custom product pages". For screenshot design, see screenshot-optimization. For metadata optimization, see metadata-optimization.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Discover and configure Bluetooth and Wi-Fi accessories using AccessorySetupKit. Use when presenting a privacy-preserving accessory picker, defining discovery descriptors for BLE or Wi-Fi devices, handling accessory session events, migrating from CoreBluetooth permission-based scanning, or setting up accessories without requiring broad Bluetooth permissions.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

alarmkit

無料

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, and Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, AlarmButton stop and snooze actions, authorization, state observation, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

When the user wants to optimize their Google Play Store listing — title, short description, full description, keywords, ratings, or Play Store-specific features. Use when the user mentions "Google Play", "Android", "Play Store", "Play Console", "short description", "full description indexed", "Google Play ASO", or wants Google Play-specific keyword, creative, or ratings strategy. For iOS App Store optimization, see aso-audit and metadata-optimization.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

JordanCoin のスキルをすべて見る

このスキルの問題を報告する