rshankras/claude-code-apple-skills5 files

Watchos

watchOS development guidance including SwiftUI for Watch, Watch Connectivity, complications, and watch-specific UI patterns. Use for watchOS code review, best practices, or Watch app development.

Specification
Skill ID
rshankras/claude-code-apple-skills/watchos
Publisher
rshankras
Repository
claude-code-apple-skills
Installs
0
Files
5
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

rshankras/claude-code-apple-skills/watchosInstalls these files
  • SKILL.md
  • complications.md
  • health-fitness.md
  • watch-connectivity.md
  • widgets-for-watch.md

What this skill tells the agent

watchOS Development

Comprehensive guidance for watchOS app development with SwiftUI, Watch Connectivity, and complications.

When This Skill Activates

Use this skill when the user:

  • Is building a watchOS app or Watch extension
  • Asks about Watch Connectivity (iPhone ↔ Watch sync)
  • Needs help with complications or ClockKit
  • Wants to implement watch-specific UI patterns
  • Asks about WidgetKit complications or migrating from ClockKit to WidgetKit
  • Wants to build watch face complications (accessoryCircular, accessoryRectangular, accessoryCorner, accessoryInline)
  • Asks about HealthKit on watchOS, workout sessions, heart rate, or fitness tracking
  • Needs Extended Runtime sessions for background workout tracking
  • Wants to build watchOS widgets or Smart Stack widgets
  • Asks about widget relevance, Smart Stack ordering, or widget suggestions
  • Needs to share widgets cross-platform between iOS and watchOS
  • Asks about watchOS accessibility — VoiceOver, AssistiveTouch, or Dynamic Type on the Watch

Key Principles

1. Watch-First Design

  • Glanceable content - users look for seconds, not minutes
  • Quick interactions - 2 seconds or less
  • Essential information only - no scrolling walls of text
  • Large touch targets - minimum 38pt height

2. Independent vs Companion

  • Prefer independent Watch apps when possible
  • Use Watch Connectivity for data sync, not as dependency
  • Cache data locally for offline access
  • Handle connectivity failures gracefully

3. Performance

  • Minimize background work (battery)
  • Use complication updates sparingly
  • Prefer timeline-based content over live updates
  • Keep views lightweight

watchOS Design Rules (WWDC20/23)

The Ten-Second Test

Design for roughly ten seconds of attention: "if you had ten seconds of someone's attention, which information would you surface?" Launch directly into that detail view — chosen by location, recency, or frequency — and make it so unmistakable it needs no title.

Three Foundational Layouts

LayoutUse ForNotes
DialDense at-a-glance statusUp to 4 corner controls; .scenePadding(.horizontal) to align with the bezel
InfographicCharts + metricsOne chart with supporting numbers
ListScrollable findingWhen the user must locate an item

Navigation Model

  • Prefer vertical pagination via the Digital Crown between purposeful, single-screen-height pages — horizontal paging is "more difficult to navigate".
  • Prefer the two-level Source List pattern with NavigationSplitView: always initialize the selection so the app launches straight to detail, and leave the source list untitled.
  • Reach for NavigationStack only when neither fits — and hierarchical navigation should remember the last destination across launches.
  • The Digital Crown anchors navigation, scrolling, and precision input, but ALWAYS back it up with touch.
// Source List: launch to detail, not the list
NavigationSplitView {
    List(rooms, selection: $selectedRoom) { room in  // source list stays untitled
        Text(room.name)
    }
} detail: {
    RoomView(room: selectedRoom)
}
// Initialize selectedRoom (last used / most relevant) so launch lands on detail

Backgrounds and Materials

  • Backgrounds must carry utility — recognition or information (a solar gradient tracking the sun, a state change from black to orange) — never mere flourish.
  • Four vibrant full-screen materials (Ultra Thin → Thick) pair with Primary–Quaternary vibrant foreground styles and vibrant semantic colors to keep content legible over any background.

Toolbars and Action Buttons

  • Toolbar placements: .topBarLeading, .topBarTrailing (moves the time to the center), and .bottomBar.
  • Bottom-of-detail action buttons are the most discoverable pattern. A red label signals destructive — add a confirmation if the data isn't recoverable.
  • The More button (ellipsis in a circular container: white at 85% opacity with a 1pt black outer glow at 50%) holds ONLY secondary actions — never a primary action.
  • Toolbar-revealed buttons belong only in scrolling views — scrolling is what makes them discoverable.

Accessibility on watchOS (WWDC21 10223)

Dynamic Type on the Watch

  • watchOS has 11 text styles; a fixed .font(.system(size: 24)) never scales — use .font(.title3) and friends.
  • Let text wrap: lineLimit(1) truncates at accessibility sizes — set the real maximum you support (.lineLimit(3)) or remove the limit.
  • Watch setup defaults text size to the closest match to the paired iPhone's setting — expect real users at accessibility sizes (WWDC21 10223).
  • Swap layout when wrapping gets crowded:
@Environment(\.sizeCategory) var sizeCategory

var body: some View {
    if sizeCategory < .extraExtraLarge {
        PlantViewHorizontal(plant: $plant)   // default layout
    } else {
        PlantViewVertical(plant: $plant)     // stacked layout for large sizes
    }
}

VoiceOver

  • NavigationLink combines its children's accessibility automatically — don't add extra grouping inside one; the whole row becomes a single element (WWDC21 10223).
  • Label icon+text rows so they read as meaning, not parts: .accessibilityLabel("Watering in five days") instead of "Drop, image. Five days." Label icon-only buttons too: .accessibilityLabel("Log \(task.name)") → "Log watering, button".
  • Steppers/counters: collapse [minus, value, plus] into one adjustable element. Put the changing number in the value — it is re-spoken on every change; the label is spoken only on navigation:
CustomCounter(value: value, increment: increment, decrement: decrement)
    .accessibilityElement()               // drops the +/- buttons as separate stops
    .accessibilityAdjustableAction { direction in
        switch direction {
        case .increment: increment()      // swipe up
        case .decrement: decrement()      // swipe down
        default: break
        }
    }
    .accessibilityLabel("\(task.name) frequency")
    .accessibilityValue("\(value) days")
  • Complications and dynamic notifications need the same treatment — they're extra content paths out of your app. Expand abbreviations ("Wednesday, March 9th", not "Wednesday Mar 9"), and label image complications or VoiceOver speaks the asset name (WWDC21 10223).

AssistiveTouch

Hand gestures drive the watch with zero screen touches: clench = tap, double-clench = action menu, pinch = next element, double-pinch = previous (WWDC21 10223). A cursor focuses only interactive elements — Button, Toggle, NavigationLink, views with tap gestures, accessibility actions, or actionable traits; static text and disabled elements are skipped.

// ✅ static text whose parent owns the tap gesture — make it a cursor stop
FreeDrinkInfoView()
    .accessibilityRespondsToUserInteraction(true)

// ✅ cursor frame == tappable area; enlarge tiny hit targets
NavigationLink(destination: EditView()) {
    Image(systemName: "ellipsis").symbolVariant(.circle)
}
.contentShape(Circle().scale(1.5))

VoiceOver custom actions appear in the AssistiveTouch action menu automatically. Supply a real icon via the Label form of .accessibilityAction { } label: { Label("Edit", systemImage: "ellipsis.circle") } — otherwise the menu falls back to the first letter of the action name (WWDC21 10223).

Architecture Patterns

App Structure

@main
struct MyWatchApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Navigation

// Use NavigationStack (watchOS 9+)
NavigationStack {
    List {
        NavigationLink("Item 1", value: Item.one)
        NavigationLink("Item 2", value: Item.two)
    }
    .navigationDestination(for: Item.self) { item in
        ItemDetailView(item: item)
    }
}

// TabView for main sections
TabView {
    HomeView()
    ActivityView()
    SettingsView()
}

Use this skill in a project

Open any RiverX project, search the Skills panel for rshankras/claude-code-apple-skills/watchos, and install it in one click.

Use this skill