skills/generators/milestone-celebration/SKILL.md
Generates achievement celebration UI with confetti animations, badge unlocks, progress milestones, haptic feedback, and optional share-to-social. Use when user wants to celebrate achievements, show confetti, display milestone badges, or trigger rewards on key thresholds.
npx skillsauth add taiberium/claude_code_setting milestone-celebrationInstall 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 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.
Use this skill when the user:
@Observable, spring animations, sensoryFeedback)UIKit availability (iOS — CAEmitterLayer for confetti, haptics)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):
Determine if generating for iOS (UIKit-based confetti + haptics) or macOS (Core Animation confetti, no haptics) or both (cross-platform with feature gates).
Ask user via AskUserQuestion:
Celebration type? (multi-select)
Haptic feedback?
Shareable achievement card?
ShareLinkSound effects?
Read templates.md for production Swift code.
Generate these files:
Milestone.swift — Model with id, title, description, threshold, icon, unlock state. Codable + Sendable.MilestoneTracker.swift — @Observable class tracking progress toward milestones, checking thresholds, triggering celebrations. Persists unlock state via UserDefaults or file storage.ConfettiView.swift — UIViewRepresentable wrapping CAEmitterLayer for confetti particle animation. Configurable colors, duration, density. Respects Reduce Motion.CelebrationOverlay.swift — Full-screen overlay combining confetti + badge reveal + congratulations message. Auto-dismisses after configurable duration. Uses withAnimation(.spring).MilestoneBadgeView.swift — Individual badge view with locked/unlocked states, SF Symbol icon, progress ring for partial progress.MilestoneCollectionView.swift — Grid layout of all milestones showing locked/unlocked state with progress indicators.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)Check project structure:
Sources/ exists -> Sources/MilestoneCelebration/App/ exists -> App/MilestoneCelebration/MilestoneCelebration/After generation, provide:
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)
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")
}
}
}
@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
}
Best for: fitness, learning, productivity apps.
MilestoneTracker checks values against registered milestonesBest for: gamification, loyalty, progression systems.
Best for: social apps, fitness, competitions.
ImageRenderer at @2x scale for Retina qualityShareLink for native share sheetbirthRate at 50-80 for smooth 60fps on most devicesemitterCells with only 3-5 distinct shapes to reduce GPU draw callsUIAccessibility.isReduceMotionEnabled before starting particle animations@Environment(\.accessibilityReduceMotion) in SwiftUI for reactive updatesUINotificationFeedbackGenerator is a no-op on devices without a Taptic Engine (e.g., iPod touch, iPad)CHHapticEngine.capabilitiesForHardware().supportsHaptics before preparing generators#if canImport(UIKit) and #if os(iOS).sensoryFeedback(.success, trigger:) modifier on iOS 17+ for a simpler SwiftUI-native approachAudioServicesPlaySystemSound for lightweight celebration sounds (no audio session needed)AudioServicesPlaySystemSound honors it automaticallyUserDefaults for simple unlock flags or a lightweight JSON file for full milestone stateSwiftData or CoreData apps, consider storing unlock state alongside the user's data modelgenerators/streak-tracker — Streak tracking pairs naturally with milestone celebrationsgenerators/share-card — Shareable achievement card rendering and social sharinggenerators/variable-rewards — Variable reward schedules for deeper engagementtools
Generates multi-step onboarding flows with persistence for iOS/macOS apps. Use when user wants to add onboarding, welcome screens, or first-launch experience.
tools
Generates an offline operation queue with persistence, automatic retry on connectivity, and conflict resolution. Use when user needs offline-first behavior, queued mutations, or pending operations that sync when back online.
development
Generates offer code distribution strategies and configuration guides for subscription and IAP promotions — including partner campaigns, influencer programs, and email re-engagement. Use when setting up offer codes for distribution.
tools
Generates a protocol-based networking layer with async/await, error handling, and swappable implementations. Use when user wants to add API client, networking, or HTTP layer.