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 skills add https://github.com/rshankras/claude-code-apple-skills --skill milestone-celebration
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:
ShareLinkRead 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 modelapp-store/originality-check before submitting.generators/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 engagementCreate beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.
Downloads videos from YouTube and other platforms for offline viewing, editing, or archival. Handles various formats and quality options.
Lightweight WSI tile extraction and preprocessing. Use for basic slide processing tissue detection, tile extraction, stain normalization for H&E images. Best for simple pipelines, dataset preparation, quick tile-based analysis. For advanced spatial proteomics, multiplexed imaging, or deep learning pipelines use pathml.
Microscopy data management platform. Access images via Python, retrieve datasets, analyze pixels, manage ROIs/annotations, batch processing, for high-content screening and microscopy workflows.
Python library for working with DICOM (Digital Imaging and Communications in Medicine) files. Use this skill when reading, writing, or modifying medical imaging data in DICOM format, extracting pixel data from medical images (CT, MRI, X-ray, ultrasound), anonymizing DICOM files, working with DICOM metadata and tags, converting DICOM images to other formats, handling compressed DICOM data, or processing medical imaging datasets. Applies to tasks involving medical image analysis, PACS systems, radiology workflows, and healthcare imaging applications.
This skill should be used when working with pre-trained transformer models for natural language processing, computer vision, audio, or multimodal tasks. Use for text generation, classification, question answering, translation, summarization, image classification, object detection, speech recognition, and fine-tuning models on custom datasets.
Take rshankras/milestone-celebration from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.