skills/generators/widget-generator/SKILL.md
Generate WidgetKit widgets for iOS/macOS home screen and lock screen with timeline providers, interactive elements, and App Intent configuration. Use when adding widgets to an app.
npx skillsauth add rshankras/claude-code-apple-skills widget-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate a complete WidgetKit widget implementation with timeline providers, size-specific views, lock screen accessory widgets, interactive elements (iOS 17+), and App Intent configuration.
Use this skill when the user:
WidgetBundleSearch for existing widget code:
Glob: **/*Widget*.swift, **/*TimelineProvider*.swift
Grep: "WidgetKit" or "TimelineProvider" or "WidgetBundle" or "WidgetConfiguration"
If an existing widget extension is found:
WidgetBundle to extendIf a WidgetBundle already exists:
@main entry pointIf widget code with the same name exists:
Widgets require:
Ask user via AskUserQuestion:
What is this widget for? (freeform)
Which widget sizes should be supported?
What type of widget?
StaticConfiguration) -- content updated on a schedule, no user configurationAppIntentConfiguration, iOS 17+) -- user can choose what the widget displays via long-press editAppIntentConfiguration + Button/Toggle, iOS 17+) -- user can tap buttons or toggles directly on the widgetWhat is the data source?
How often should the widget update?
WidgetCenter.shared.reloadTimelines(ofKind:)Check project structure:
For widget extension files:
MyAppWidgets/)For shared data models (if using App Groups):
Sources/ or Shared/ exists --> place thereGenerate these files based on configuration answers:
{Name}Widget.swift -- Widget definition with configuration
Widget struct with StaticConfiguration or AppIntentConfiguration{Name}TimelineProvider.swift -- Timeline logic
TimelineProvider (static) or AppIntentTimelineProvider (configurable){Name}Entry.swift -- Timeline entry model
TimelineEntry struct with date and display data{Name}WidgetViews.swift -- Size-specific views
containerBackground for iOS 17+ removable backgrounds{Name}AppIntent.swift (if interactive or configurable)
WidgetConfigurationIntent for configurable widgetsAppIntent for interactive widget buttons/togglesUse the templates in templates.md and customize based on user answers:
After generation, provide:
MyAppWidgets/
├── {Name}Widget.swift # Widget definition + configuration
├── {Name}TimelineProvider.swift # Timeline provider with placeholder/snapshot/timeline
├── {Name}Entry.swift # TimelineEntry data model
├── {Name}WidgetViews.swift # Size-specific views for each family
├── {Name}AppIntent.swift # (if configurable/interactive) App Intent
└── (update WidgetBundle if needed)
Shared/
└── {Name}DataProvider.swift # (if App Groups) Shared data access
1. Add the widget extension target (if not present):
2. Enable App Groups (if sharing data with the main app):
group.com.yourcompany.yourapp)3. Register the widget in the WidgetBundle:
@main
struct MyAppWidgets: WidgetBundle {
var body: some Widget {
// Existing widgets...
{Name}Widget()
}
}
4. Trigger widget updates from the main app when data changes:
import WidgetKit
// Reload a specific widget
WidgetCenter.shared.reloadTimelines(ofKind: "{Name}Widget")
// Or reload all widgets
WidgetCenter.shared.reloadAllTimelines()
5. For App Group data sharing, write from the main app:
let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp")
sharedDefaults?.set(encodedData, forKey: "widgetData")
// Then trigger reload
WidgetCenter.shared.reloadTimelines(ofKind: "{Name}Widget")
#Preview with timeline entry data for rapid iteration.WidgetCenter.shared.getCurrentConfigurations to verify registered widgets..after(nextEventDate) policyButton(intent:) for each action (iOS 17+)Text(date, style: .timer) / Text(date, style: .relative) for automatic live updatescontainerBackground required (iOS 17+): All widget views must use .containerBackground(for: .widget) to support the system's removable background feature. Without this, widgets show a default placeholder background.AccessoryWidgetBackground() for backgrounds and keep designs simple with high contrast.Text(date, style: .timer) for countdowns; the system animates these for you.getTimeline must complete quickly. The system may terminate long-running providers.@main conflict: Only one @main per widget extension. If you have multiple widgets, use a WidgetBundle as the single @main entry point.AppIntent parameter values are stored by the system. Do not rely on UserDefaults for configuration state.#Preview(as: .systemSmall) for family-specific widget previews.development
Build, install, and launch an iOS app on a physical iPhone or iPad entirely from the command line (no Xcode GUI), using xcodebuild + devicectl. Use when the user wants to run, test, or screenshot their app on a real device without opening Xcode.
development
Comprehensive iOS development guidance including Swift best practices, SwiftUI patterns, UI/UX review against HIG, and app planning. Use for iOS code review, best practices, accessibility audits, or planning new iOS apps.
development
Build, install, launch, and screenshot an iOS app in the Simulator to verify a change visually. Use when the user wants to run the app, see a change live, screenshot the running app, or confirm a UI fix actually works (not just that it compiles).
development
Audits skills in this repo for consistency, API drift, and structural gaps. Produces a prioritized report grouped by severity (Critical/High/Medium/Low). Use when asked to "audit skills", "check the skill repo for drift", or when planning bulk skill cleanup. Read-only — does not apply fixes.