All skills

Code generator skills that produce production-ready Swift code for common app components. Use when user wants to add logging, analytics, onboarding, review prompts, networking, authentication, paywalls, settings, persistence, error monitoring, CI/CD pipelines, localization, push notifications, deep linking, testing, accessibility, widgets, feature flags, app icons, image caching, pagination, HTTP caching, share cards, social export, subscription lifecycle, referral systems, watermarks, streak tracking, milestone celebrations, what's new screens, lapsed user re-engagement, usage insights, variable rewards, consent flows, account deletion, permission priming, force updates, state restoration, debug menus, offline queues, feedback forms, announcement banners, quick win sessions, Spotlight indexing, App Clips, screenshot automation, background processing, app extensions, data export, or SwiftUI preview sample data and variant matrices.

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/generators

This session only. Nothing lands on disk.

milestone-celebrationSKILL.md

≈3.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Milestone Celebration Generator

Generate a production milestone celebration system with confetti particle animations via CAEmitterLayer, achievement badge views with locked/unlocked states, a celebration overlay with spring animations, haptic feedback, and optional shareable achievement cards — all triggered automatically when users hit key thresholds.

When This Skill Activates

Use this skill when the user:

  • Asks to "add celebrations" or "celebrate achievements"
  • Wants "confetti animation" or "particle effects for milestones"
  • Mentions "achievement badges" or "badge unlock animation"
  • Asks about "milestone rewards" or "progress milestones"
  • Wants to "celebrate achievement" or "trigger celebration on threshold"
  • Asks about "level-up animation" or "gamification celebrations"

Pre-Generation Checks

1. Project Context Detection

  • Check Swift version (requires Swift 5.9+)
  • Check deployment target (iOS 17+ / macOS 14+ for @Observable, spring animations, sensoryFeedback)
  • Check for UIKit availability (iOS — CAEmitterLayer for confetti, haptics)
  • Identify source file locations

2. Conflict Detection

Search for existing celebration/animation code:

Glob: **/*Confetti*.swift, **/*Celebration*.swift, **/*Achievement*.swift, **/*Milestone*.swift, **/*Badge*.swift
Grep: "CAEmitterLayer" or "CAEmitterCell" or "UINotificationFeedbackGenerator" or "confetti" or "celebration"

If existing celebration or gamification library found (e.g., custom confetti, third-party particle libraries):

  • Ask if user wants to replace or integrate with it
  • If keeping, advise on best practices instead of generating

3. Platform Detection

Determine if generating for iOS (UIKit-based confetti + haptics) or macOS (Core Animation confetti, no haptics) or both (cross-platform with feature gates).

Configuration Questions

Ask user via AskUserQuestion:

  1. Celebration type? (multi-select)

    • Confetti burst (full-screen particle animation)
    • Badge unlock (icon reveal with glow animation)
    • Level-up (progress ring fill + title transition)
    • Custom (user defines their own celebration style)
  2. Haptic feedback?

    • Yes — success haptic on celebration trigger (recommended)
    • No — silent celebrations only
  3. Shareable achievement card?

    • Yes — render achievement as image for social sharing via ShareLink
    • No — in-app celebration only
  4. Sound effects?

    • Yes — play system sound or bundled audio on celebration
    • No — visual only

Generation Process

Step 1: Read Templates

Read templates.md for production Swift code.

Step 2: Create Core Files

Generate these files:

  1. Milestone.swift — Model with id, title, description, threshold, icon, unlock state. Codable + Sendable.
  2. MilestoneTracker.swift — @Observable class tracking progress toward milestones, checking thresholds, triggering celebrations. Persists unlock state via UserDefaults or file storage.
  3. ConfettiView.swift — UIViewRepresentable wrapping CAEmitterLayer for confetti particle animation. Configurable colors, duration, density. Respects Reduce Motion.

Step 3: Create UI Files

  1. CelebrationOverlay.swift — Full-screen overlay combining confetti + badge reveal + congratulations message. Auto-dismisses after configurable duration. Uses withAnimation(.spring).
  2. MilestoneBadgeView.swift — Individual badge view with locked/unlocked states, SF Symbol icon, progress ring for partial progress.
  3. MilestoneCollectionView.swift — Grid layout of all milestones showing locked/unlocked state with progress indicators.

Step 4: Create Optional Files

Based on configuration:

  • HapticManager.swift — If haptic feedback selected (thin wrapper around UINotificationFeedbackGenerator / UIImpactFeedbackGenerator)
  • ShareableMilestoneCard.swift — If shareable selected (renders milestone as image via ImageRenderer + ShareLink)

Step 5: Determine File Location

Check project structure:

  • If Sources/ exists -> Sources/MilestoneCelebration/
  • If App/ exists -> App/MilestoneCelebration/
  • Otherwise -> MilestoneCelebration/

Output Format

After generation, provide:

Files Created

MilestoneCelebration/
├── Milestone.swift              # Model with threshold, icon, unlock state
├── MilestoneTracker.swift       # @Observable tracker with persistence
├── ConfettiView.swift           # CAEmitterLayer confetti animation
├── CelebrationOverlay.swift     # Full-screen celebration overlay
├── MilestoneBadgeView.swift     # Badge with locked/unlocked + progress ring
├── MilestoneCollectionView.swift # Grid of all milestones
├── HapticManager.swift          # Celebration haptics (optional)
└── ShareableMilestoneCard.swift # Achievement share card (optional)

Integration Steps

Trigger celebration on threshold:

struct WorkoutCompleteView: View {
    @State private var tracker = MilestoneTracker()
    @State private var celebratingMilestone: Milestone?

    var body: some View {
        VStack {
            // ... workout summary content ...

            Button("Save Workout") {
                saveWorkout()
                let newCount = totalWorkouts + 1
                if let milestone = tracker.checkThreshold(value: newCount, category: .workouts) {
                    celebratingMilestone = milestone
                }
            }
        }
        .overlay {
            if let milestone = celebratingMilestone {
                CelebrationOverlay(milestone: milestone) {
                    celebratingMilestone = nil
                }
            }
        }
    }
}

Badge collection screen:

struct ProfileView: View {
    @State private var tracker = MilestoneTracker()

    var body: some View {
        NavigationStack {
            ScrollView {
                MilestoneCollectionView(
                    milestones: tracker.allMilestones,
                    columns: 3
                )
            }
            .navigationTitle("Achievements")
        }
    }
}

Share an achievement:

struct MilestoneDetailView: View {
    let milestone: Milestone
    @State private var showShareCard = false

    var body: some View {
        VStack {
            MilestoneBadgeView(milestone: milestone, size: .large)
            Text(milestone.title).font(.title2.bold())
            Text(milestone.milestoneDescription).foregroundStyle(.secondary)

            if milestone.isUnlocked {
                Button("Share Achievement") {
                    showShareCard = true
                }
                .buttonStyle(.borderedProminent)
            }
        }
        .sheet(isPresented: $showShareCard) {
            ShareableMilestoneCard(milestone: milestone, brandName: "FitApp")
        }
    }
}

Testing

@Test
func milestoneUnlocksAtThreshold() {
    let tracker = MilestoneTracker(store: InMemoryMilestoneStore())
    let milestone = Milestone(
        id: "first-10",
        title: "First 10",
        milestoneDescription: "Complete 10 workouts",
        threshold: 10,
        iconName: "flame.fill"
    )
    tracker.register(milestone)

    let result = tracker.checkThreshold(value: 10, for: milestone.id)
    #expect(result != nil)
    #expect(result?.isUnlocked == true)
    #expect(result?.unlockedDate != nil)
}

@Test
func milestoneDoesNotUnlockBelowThreshold() {
    let tracker = MilestoneTracker(store: InMemoryMilestoneStore())
    let milestone = Milestone(
        id: "first-10",
        title: "First 10",
        milestoneDescription: "Complete 10 workouts",
        threshold: 10,
        iconName: "flame.fill"
    )
    tracker.register(milestone)

    let result = tracker.checkThreshold(value: 9, for: milestone.id)
    #expect(result == nil)
}

@Test
func confettiRespectsReduceMotion() {
    // When Reduce Motion is enabled, ConfettiView should not emit particles
    let config = ConfettiConfiguration(reduceMotionOverride: true)
    #expect(config.shouldAnimate == false)
}

@Test
func celebrationOverlayAutoDismisses() async throws {
    // Verify overlay dismisses after the configured duration
    let expectation = XCTestExpectation(description: "Dismissed")
    let duration: TimeInterval = 0.5
    // Test that the onDismiss callback fires after duration
}

Common Patterns

Trigger Celebration on Threshold

Best for: fitness, learning, productivity apps.

  • Define milestones with numeric thresholds (10 workouts, 100 pages read, 7-day streak)
  • MilestoneTracker checks values against registered milestones
  • Celebration fires only on the first crossing — subsequent calls are no-ops
  • Persist unlock state so celebrations do not repeat

Badge Collection View

Best for: gamification, loyalty, progression systems.

  • Grid of all milestones: locked ones are dimmed/grayscale, unlocked ones are vibrant
  • Progress ring shows how close user is to unlocking each badge
  • Tapping a badge shows detail view with full description and share option
  • Counter showing "12 of 20 unlocked" at the top

Share Achievement

Best for: social apps, fitness, competitions.

  • Render the unlocked badge + title + metric as a shareable image
  • Use ImageRenderer at @2x scale for Retina quality
  • Include app branding and optional QR code for deep linking
  • Integrate with ShareLink for native share sheet

Gotchas

CAEmitterLayer Performance on Older Devices

  • Confetti with many particles (200+) can drop frames on A11 and older chips
  • Cap birthRate at 50-80 for smooth 60fps on most devices
  • Use emitterCells with only 3-5 distinct shapes to reduce GPU draw calls
  • Stop emission after burst duration — do not leave the emitter running indefinitely
  • Profile with Instruments (Core Animation template) if users report frame drops

Reduce Motion Accessibility

  • Always check UIAccessibility.isReduceMotionEnabled before starting particle animations
  • When Reduce Motion is on: skip confetti, show a static badge reveal or a simple fade-in instead
  • Use @Environment(\.accessibilityReduceMotion) in SwiftUI for reactive updates
  • Provide an equally rewarding experience without animation — the badge reveal and message still appear

Haptic Feedback on Non-Supporting Devices

  • UINotificationFeedbackGenerator is a no-op on devices without a Taptic Engine (e.g., iPod touch, iPad)
  • Always guard with CHHapticEngine.capabilitiesForHardware().supportsHaptics before preparing generators
  • On macOS, haptics are not available — gate with #if canImport(UIKit) and #if os(iOS)
  • Use .sensoryFeedback(.success, trigger:) modifier on iOS 17+ for a simpler SwiftUI-native approach

Sound Effect Considerations

  • Use AudioServicesPlaySystemSound for lightweight celebration sounds (no audio session needed)
  • Respect the device silent/mute switch — AudioServicesPlaySystemSound honors it automatically
  • For custom sounds, keep files under 30 seconds and use CAF or WAV format
  • Do not play sounds when Reduce Motion is enabled (some users enable it for sensory reasons)

Persistence Edge Cases

  • If the app is terminated between unlocking a milestone and persisting it, the user may see the celebration again
  • Use UserDefaults for simple unlock flags or a lightweight JSON file for full milestone state
  • For SwiftData or CoreData apps, consider storing unlock state alongside the user's data model
  • Sync unlock state via CloudKit if the app supports multiple devices

App Store Guidelines

  • Guideline 4.5.4: Milestone-announcement pushes ("you're 1 away from a badge!") are promotional — explicit opt-in consent and an in-app opt-out are required.
  • Guideline 2.3.1: Screenshots showing badges and achievements must reflect what the app actually awards — aspirational metadata is a rejection risk.
  • Guideline 4.3 (Spam): Celebrations don't differentiate a thin app. If this is one of several similar apps on your account, run app-store/originality-check before submitting.

References

  • templates.md — All production Swift templates
  • Related: generators/streak-tracker — Streak tracking pairs naturally with milestone celebrations
  • Related: generators/share-card — Shareable achievement card rendering and social sharing
  • Related: generators/variable-rewards — Variable reward schedules for deeper engagement

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The 'generators' skill provides a robust set of templates and workflows for generating Swift code for iOS and macOS applications. Security analysis identified a surface for indirect prompt injection because the skill reads local project files to adapt its generation logic. It also utilizes dynamic execution by generating and running local Swift scripts to create application icons and uses shell commands to process images and audit project code. All external references are to well-known, established services.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: MEDIUM · 1 issue

  • Runlayer7mo

    59/179 files flagged

  • ZeroLeaks5mo

    Scan incomplete

Signed by skilld at 30e898f. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 2 months ago
What it can do
Reads files Edits files Runs commands
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 7 allowed tools
ReadWriteEditGlobGrepBashAskUserQuestion

README badge

README badge for rshankras/claude-code-apple-skills/generators