Building a WidgetKit Widget
Create a home-screen widget with a timeline.
Building a WidgetKit Widget is a free Swift Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What a Widget Is
A widget is a small, glanceable view that lives on the Home Screen, Lock Screen, or in StandBy. It is not a mini-app — it cannot scroll or run arbitrary code. It displays a snapshot of data that the system refreshes on a schedule you provide via WidgetKit.
import WidgetKit
import SwiftUI
// A widget = configuration + timeline of entries
// + a SwiftUI view that renders one entryThe Widget Extension Target
Widgets ship in a separate Widget Extension target, not the main app. It has its own bundle and runs in its own process. You add it via Xcode's Widget Extension template, which scaffolds the configuration and provider.
import WidgetKit
// File > New > Target > Widget Extension
// The extension declares one or more widgets
// in a WidgetBundle if you have several.The Widget Type
A widget conforms to the Widget protocol and exposes a body that returns a configuration. The configuration ties together a kind identifier, a timeline provider, and the view that renders each entry.
import WidgetKit
import SwiftUI
struct WeatherWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(
kind: "WeatherWidget",
provider: WeatherProvider()) { entry in
WeatherView(entry: entry)
}
.configurationDisplayName("Weather")
.description("Shows the current forecast.")
}
}Static vs AppIntent Configuration
StaticConfiguration is for widgets with no user options. AppIntentConfiguration lets users customize the widget (pick a city, an account) through an App Intent. Choose static for fixed content, intent-based for configurable widgets.
import WidgetKit
// StaticConfiguration -> no user choices
// AppIntentConfiguration -> user-editable parameters
let kinds = "static vs configurable"
_ = kindsThe Timeline Entry
Each point in time the widget can show is a TimelineEntry — a struct with a date plus whatever data your view needs. The provider supplies a sequence of these entries.
import WidgetKit
struct WeatherEntry: TimelineEntry {
let date: Date
let temperature: Int
let condition: String
}The Widget View
The view is plain SwiftUI but constrained: no scrolling, limited interactivity, and it must look right at several fixed sizes. Read the entry and lay out a clean glanceable summary.
import SwiftUI
import WidgetKit
struct WeatherView: View {
let entry: WeatherEntry
var body: some View {
VStack {
Text(entry.condition)
Text("\(entry.temperature) degrees")
.font(.title)
}
}
}Supported Families
Declare which sizes you support with supportedFamilies: .systemSmall, .systemMedium, .systemLarge, the Lock Screen .accessoryRectangular/.accessoryCircular, and more. Adapt the layout per family using the widget family environment.
import WidgetKit
import SwiftUI
// .configurationDisplayName(...)
// .supportedFamilies([.systemSmall, .systemMedium,
// .accessoryRectangular])
let families = "declare supported sizes"
_ = familiesAdapting to Family
Read @Environment(\.widgetFamily) inside the view to branch layouts — a compact small widget versus a richer medium one — without writing separate widgets.
import SwiftUI
import WidgetKit
struct AdaptiveView: View {
@Environment(\.widgetFamily) var family
let entry: WeatherEntry
var body: some View {
if family == .systemSmall {
Text("\(entry.temperature)")
} else {
Text("\(entry.condition) \(entry.temperature)")
}
}
}Container Background
Modern widgets must declare their background with containerBackground(for: .widget) so the system can render them correctly across contexts like StandBy and the Lock Screen. Without it the widget may be rejected or look wrong.
import SwiftUI
import WidgetKit
struct Bg: View {
var body: some View {
Text("Hi")
.containerBackground(for: .widget) {
Color.blue
}
}
}Sharing Data With the App
The widget process is separate, so it cannot read the app's in-memory state. Share data through an App Group — a shared container both targets can access — typically a shared UserDefaults suite or a file in the group container.
import Foundation
let shared = UserDefaults(
suiteName: "group.com.example.app")
// App writes; widget reads the same suite.
_ = sharedReloading the Widget
When the app's data changes, tell WidgetKit to refresh by calling WidgetCenter.shared.reloadTimelines(ofKind:) (or reloadAllTimelines()). This nudges the system to ask your provider for a fresh timeline.
import WidgetKit
func refreshWidget() {
WidgetCenter.shared.reloadTimelines(
ofKind: "WeatherWidget")
}Quick Check
Recall how a widget shares data with its host app.
Recap
You built a WidgetKit widget:
- Widgets live in a separate extension and conform to
Widget, returning aWidgetConfiguration. - Use
StaticConfigurationorAppIntentConfiguration, aTimelineEntry, and a constrained SwiftUI view. - Declare
supportedFamilies, adapt viawidgetFamily, and add acontainerBackground. - Share data through an App Group and refresh with
WidgetCenter.reloadTimelines.
Frequently asked questions
Is the “Building a WidgetKit Widget” lesson free?
Yes — the full text of “Building a WidgetKit Widget” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Building a WidgetKit Widget”?
Create a home-screen widget with a timeline. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Building a WidgetKit Widget” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Building a WidgetKit Widget
- Timeline Providers and Snapshots
- App Extensions Overview
- App Intents and Shortcuts