relevancekit
RelevanceKit provides on-device contextual signals that increase Apple Watch widget visibility in the Smart Stack by declaring time-based, location-based, fitness, sleep, or hardware relevance. Use this skill when building watchOS 26+ widgets that need intelligent surfacing based on when and where users are relevant, combining multiple relevance providers to help the system display appropriate widgets at optimal times in the Smart Stack.
git clone --depth 1 https://github.com/dpearson2699/swift-ios-skills /tmp/relevancekit && cp -r /tmp/relevancekit/skills/relevancekit ~/.claude/skills/relevancekitSKILL.md
# RelevanceKit
Provide on-device contextual clues that increase a widget's visibility in the
Apple Watch Smart Stack. RelevanceKit tells the system *when* a widget is
relevant by time, location, fitness state, sleep schedule, or connected hardware.
Targets Swift 6.3 / watchOS 26+.
> **Beta-sensitive.** Re-check Apple documentation before making strong RelevanceKit availability or behavior claims.
See [references/relevancekit-patterns.md](references/relevancekit-patterns.md) for complete relevant-widget, timeline provider, grouping, preview, and permission patterns.
## Contents
- [Overview](#overview)
- [Setup](#setup)
- [Relevance Providers](#relevance-providers)
- [Boundary Routing](#boundary-routing)
- [Time-Based Relevance](#time-based-relevance)
- [Location-Based Relevance](#location-based-relevance)
- [Fitness and Sleep Relevance](#fitness-and-sleep-relevance)
- [Hardware Relevance](#hardware-relevance)
- [Combining Signals](#combining-signals)
- [Widget Integration](#widget-integration)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## 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
| Type | Module | Role |
|---|---|---|
| `RelevantContext` | RelevanceKit | A contextual clue (date, location, fitness, sleep, hardware) |
| `WidgetRelevance` | WidgetKit | Collection of relevance attributes for a widget kind |
| `WidgetRelevanceAttribute` | WidgetKit | Pairs a widget configuration with a `RelevantContext` |
| `WidgetRelevanceGroup` | WidgetKit | Controls grouping behavior in the Smart Stack |
| `RelevanceConfiguration` | WidgetKit | Widget configuration driven by relevance clues (watchOS 26+) |
| `RelevanceEntriesProvider` | WidgetKit | Provides entries for a relevance-configured widget (watchOS 26+) |
| `RelevanceEntry` | WidgetKit | Data needed to render one relevant widget card (watchOS 26+) |
`RelevanceConfiguration`, `RelevanceEntriesProvider`, and `RelevanceEntry` are
WidgetKit APIs. Keep them in this skill's scope only when they are part of the
watchOS relevant-widget workflow that exposes RelevanceKit clues.
## Setup
### Import
```swift
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. Timeline-provider `relevance()` is available on
iOS 18+, macOS 15+, visionOS 26+, and watchOS 11+ for shared provider code.
`RelevanceConfiguration`, `RelevanceEntriesProvider`, and `RelevanceEntry` are
watchOS 26+ only.
### Permissions
Certain relevance clues require authorization or target setup:
| Clue | Required Permission |
|---|---|
| `.location(inferred:)` | Containing app requests location access; widget extension declares `NSWidgetWantsLocation` |
| `.location(_:)` (CLRegion) | Containing app requests location access; widget extension declares `NSWidgetWantsLocation` |
| `.location(category:)` | Containing app requests location access; widget extension declares `NSWidgetWantsLocation` |
| `.fitness(.workoutActive)` | HealthKit access to `HKWorkoutType` |
| `.fitness(.activityRingsIncomplete)` | HealthKit access to `appleExerciseTime`, `appleMoveTime`, and `appleStandTime` |
| `.sleep(_:)` | HealthKit `sleepAnalysis` permission |
| `.hardware(headphones:)` | None |
| `.date(...)` | None |
Add location purpose strings to the containing app's `Info.plist`, not only the
widget extension. In widget code, check `CLLocationManager.isAuthorizedForWidgetUpdates`
before relying on location clues. For fitness and sleep clues, enable HealthKit
and request the exact read types in the app and widget extension target that
provides relevance.
## 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.
```swift
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.
```swift
@available(watchOS 26.0, *)
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: .schDiscover 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.
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.
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.
Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, AlarmButton stop and snooze actions, authorization, state observation, countdown widget-extension handoff, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.
Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store Connect experiences, size/capability constraints, NSUserActivity routing, SKOverlay promotion, App Group/keychain handoff, ephemeral notifications, location confirmation, and full-app migration. Use when creating App Clips or wiring App Clip invocation, experience configuration, or full-app handoff.
Implement App Intents for Siri, Shortcuts, Spotlight, widgets, Control Center, and Apple Intelligence on iOS. Covers AppIntent actions, AppEntity and EntityQuery models, AppShortcutsProvider phrases, IndexedEntity Spotlight indexing, WidgetConfigurationIntent, SnippetIntent, and assistant schemas. Use when exposing app actions or entities to system surfaces.
Optimize App Store product pages for search visibility and conversion. Use for App Store Optimization (ASO), keyword research, app name/subtitle/keyword-field strategy, conversion-focused descriptions and promotional text, screenshot captions and ordering, Custom Product Pages with assigned search keywords, In-App Events, Product Page Optimization tests, localized metadata, ratings/review strategy, and in-app review prompt timing with RequestReviewAction or AppStore.requestReview. Also use when routing ASO vs App Store review, privacy/ATT, or StoreKit implementation boundaries.
Prepare for App Store review and prevent rejections. Covers App Store review guidelines, app rejection reasons, PrivacyInfo.xcprivacy privacy manifest requirements, required API reason codes, in-app purchase IAP and StoreKit rules, App Store Guidelines compliance, ATT App Tracking Transparency, EU DMA Digital Markets Act, HIG compliance checklist, app submission preparation, review preparation, metadata requirements, entitlements, widgets, and Live Activities review rules. Use when preparing for App Store submission, fixing rejection reasons, auditing privacy manifests, implementing ATT consent flow, configuring StoreKit IAP, or checking HIG compliance.