skills/generators/image-loading/SKILL.md
Generates an image loading pipeline with memory/disk caching, deduplication, and a CachedAsyncImage SwiftUI view. Use when user wants image caching, lazy image loading, or a replacement for AsyncImage.
npx skillsauth add taiberium/claude_code_setting image-loadingInstall 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 image loading pipeline with NSCache memory cache, LRU disk cache, request deduplication, image processing, and a drop-in CachedAsyncImage SwiftUI view.
Use this skill when the user:
Search for existing image loading:
Glob: **/*ImageCache*.swift, **/*ImageLoader*.swift, **/*ImagePipeline*.swift
Grep: "AsyncImage" or "UIImage" or "NSImage" or "ImageCache"
If third-party library found (Kingfisher, SDWebImage, Nuke):
Determine if generating for iOS (UIImage) or macOS (NSImage) or both (cross-platform typealias).
Ask user via AskUserQuestion:
Cache sizes?
Image processing?
Additional features? (multi-select)
Platform?
Read image-loading-patterns.md for architecture guidance.
Read templates.md for production Swift code.
Generate these files:
ImageCache.swift — Protocol for cache interfaceMemoryImageCache.swift — NSCache-based with configurable sizeDiskImageCache.swift — FileManager LRU with expirationImageDownloader.swift — Actor-based with deduplication + cancellationImagePipeline.swift — Orchestrator (cache → download → process → store)CachedAsyncImage.swift — Drop-in SwiftUI view replacementBased on configuration:
ImageProcessor.swift — If resize or thumbnail selectedImagePrefetcher.swift — If prefetching selectedCheck project structure:
Sources/ exists → Sources/ImageLoading/App/ exists → App/ImageLoading/ImageLoading/After generation, provide:
ImageLoading/
├── ImageCache.swift # Protocol for cache interface
├── MemoryImageCache.swift # NSCache-based memory cache
├── DiskImageCache.swift # LRU disk cache with expiration
├── ImageDownloader.swift # Actor-based downloader
├── ImagePipeline.swift # Orchestrator
├── ImageProcessor.swift # Resize, thumbnails (optional)
├── CachedAsyncImage.swift # SwiftUI view
└── ImagePrefetcher.swift # Collection prefetching (optional)
Drop-in replacement for AsyncImage:
// Before (no caching)
AsyncImage(url: user.avatarURL) { image in
image.resizable().aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
// After (with caching)
CachedAsyncImage(url: user.avatarURL) { image in
image.resizable().aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
In a List:
List(users) { user in
HStack {
CachedAsyncImage(url: user.avatarURL) { image in
image.resizable().frame(width: 44, height: 44).clipShape(Circle())
} placeholder: {
Circle().fill(Color.secondary.opacity(0.2)).frame(width: 44, height: 44)
}
Text(user.name)
}
}
With prefetching:
struct UsersListView: View {
let users: [User]
@State private var prefetcher = ImagePrefetcher()
var body: some View {
List(users) { user in
UserRow(user: user)
.onAppear { prefetcher.startPrefetching(urls: nearbyURLs(for: user)) }
.onDisappear { prefetcher.stopPrefetching(urls: [user.avatarURL]) }
}
}
}
With image processing:
CachedAsyncImage(
url: photo.url,
processing: .resize(targetSize: CGSize(width: 300, height: 300))
) { image in
image.resizable()
} placeholder: {
Color.secondary.opacity(0.2)
}
@Test
func cachedImageReturnedWithoutDownload() async throws {
let cache = InMemoryImageCache()
let downloader = MockImageDownloader()
let pipeline = ImagePipeline(cache: cache, downloader: downloader)
let testImage = PlatformImage.testImage
await cache.store(testImage, for: testURL)
let result = try await pipeline.image(for: testURL)
#expect(result != nil)
#expect(downloader.downloadCount == 0) // Cache hit
}
@Test
func deduplicatesConcurrentRequests() async throws {
let downloader = MockImageDownloader(delay: .milliseconds(100))
let pipeline = ImagePipeline(downloader: downloader)
async let image1 = pipeline.image(for: testURL)
async let image2 = pipeline.image(for: testURL)
let results = try await [image1, image2]
#expect(results.count == 2)
#expect(downloader.downloadCount == 1) // Only one download
}
generators/http-cache — General HTTP response cachinggenerators/pagination — Prefetch images in paginated liststools
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.