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.

preview-data-generatorpreview-data-patterns.md

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

Preview Sample Data Patterns

Reference for the preview-data-generator skill: how to design canvas sample data, the edge cases that matter, SwiftData seeding, and the modern shared-data APIs.

The Edge-Case Catalog

Test fixtures optimize for minimal, assertion-friendly objects. Preview data optimizes for visual stress — the cases that expose layout bugs. Generate these for any non-trivial model:

Case Why it matters Example accessor
Realistic The happy path you design against .preview
Empty collection Empty states are the most-forgotten screen .previewEmpty
Single item Lists that assume "many" break at 1 .previewOne
Many items Spacing, scrolling, performance .previewList (10-20)
Long strings Truncation, wrapping, button overflow .previewLongTitle
Missing/optional nil image, no subtitle, no avatar .previewNoImage
Extremes 0, negative, 9,999+, huge numbers .previewMaxedOut
Loading / Error The non-success UI states (see state matrix) view-level, not model-level

Design the .preview Namespace

Put canvas data in an extension on the model, in a #if DEBUG file so it never ships:

#if DEBUG
import Foundation

extension Article {
    static var preview: Article {
        Article(
            id: UUID(),
            title: "Designing for the Smallest Screen",
            author: "Mei Chen",
            body: String(repeating: "Lorem ipsum dolor sit amet. ", count: 30),
            imageURL: URL(string: "https://picsum.photos/seed/news/600/400"),
            readMinutes: 6,
            isBookmarked: false
        )
    }

    static var previewLongTitle: Article {
        preview.with(title: "An Extraordinarily, Almost Unreasonably Long Headline That Will Wrap Onto Several Lines")
    }
    static var previewNoImage: Article  { preview.with(imageURL: nil) }
    static var previewBookmarked: Article { preview.with(isBookmarked: true) }

    static var previewList: [Article] {
        ["Swift 6 Concurrency", "Liquid Glass in Practice", "Shipping on a Weekend",
         "The 20-Minute Code Review", "Designing Empty States"]
            .map { preview.with(id: UUID(), title: $0) }
    }
    static var previewEmpty: [Article] { [] }
}
#endif

The .with(...) helper

A tiny copy-helper keeps edge cases one line each instead of re-specifying every field:

#if DEBUG
extension Article {
    func with(
        id: UUID? = nil, title: String? = nil, author: String? = nil,
        imageURL: URL?? = nil, isBookmarked: Bool? = nil
    ) -> Article {
        Article(
            id: id ?? self.id,
            title: title ?? self.title,
            author: author ?? self.author,
            body: self.body,
            imageURL: imageURL ?? self.imageURL,   // double optional → can set to nil explicitly
            readMinutes: self.readMinutes,
            isBookmarked: isBookmarked ?? self.isBookmarked
        )
    }
}
#endif

Reuse test-data-factory, Don't Duplicate

If the project already has a fixture factory (from testing/test-data-factory), build previews on top of it:

#if DEBUG
extension Article {
    // Reuse the factory for base fields; previews only override what's visually interesting.
    static var preview: Article { .fixture(title: "Designing for the Smallest Screen") }
    static var previewList: [Article] { (1...12).map { .fixture(id: UUID(), title: "Article \($0)") } }
}
#endif

Detection: Grep "static func fixture" in the project. If present, prefer it. If absent, generate the .preview data standalone (and optionally suggest adding a factory for tests).

SwiftData: In-Memory Seeded Container

A @Model-backed view needs a container, not a struct. Build an in-memory one seeded with sample data — it never touches the real store:

#if DEBUG
import SwiftData

@MainActor
let previewContainer: ModelContainer = {
    let container = try! ModelContainer(
        for: Article.self,
        configurations: ModelConfiguration(isStoredInMemoryOnly: true)
    )
    for article in Article.previewSeed {
        container.mainContext.insert(article)
    }
    return container
}()
#endif

// Usage:
#Preview {
    ArticleListView()
        .modelContainer(previewContainer)
}

iOS 18 / Xcode 16: PreviewModifier (build the data once, cache it)

PreviewModifier lets every preview share one expensive context (a seeded container, a configured environment) that Xcode builds once and caches — instead of rebuilding per preview:

#if DEBUG
import SwiftUI
import SwiftData

struct SampleData: PreviewModifier {
    // Built once, cached, shared across all previews that use this modifier.
    static func makeSharedContext() async throws -> ModelContainer {
        let container = try ModelContainer(
            for: Article.self,
            configurations: ModelConfiguration(isStoredInMemoryOnly: true)
        )
        Article.previewSeed.forEach { container.mainContext.insert($0) }
        return container
    }

    func body(content: Content, context: ModelContainer) -> some View {
        content.modelContainer(context)
    }
}

extension PreviewTrait where T == Preview.ViewTraits {
    static var sampleData: Self { .modifier(SampleData()) }
}
#endif

// Usage — clean and shared:
#Preview(traits: .sampleData) { ArticleListView() }
#Preview("Dark", traits: .sampleData) { ArticleListView().preferredColorScheme(.dark) }

Xcode 16: @Previewable for @State in previews

When a view needs live @State/@Bindable (toggles, selection, text), @Previewable lets it live directly in the #Preview body — no wrapper view:

#Preview("Interactive") {
    @Previewable @State var query = ""
    SearchBar(text: $query)
}

Mocking a ViewModel for Previews

If the view owns an @Observable ViewModel that fetches data, generate a preview instance pinned to a state instead of letting it hit the network:

#if DEBUG
extension ArticleListViewModel {
    static var previewLoaded: ArticleListViewModel {
        let vm = ArticleListViewModel(service: .noop)
        vm.state = .loaded(Article.previewList)
        return vm
    }
    static var previewEmpty: ArticleListViewModel { let vm = ArticleListViewModel(service: .noop); vm.state = .empty; return vm }
    static var previewError: ArticleListViewModel { let vm = ArticleListViewModel(service: .noop); vm.state = .error("No connection"); return vm }
}
#endif

.noop is a do-nothing conformance to the view model's service protocol — reuse the same protocol the app already defines for swappable services (see generators/networking-layer).

Rules

  • ✅ Always wrap preview data in #if DEBUG
  • ✅ Reuse .fixture() if it exists; otherwise keep .preview self-contained
  • ✅ Use stable seed strings for image URLs (e.g. picsum.photos/seed/...) so previews don't flicker
  • ✅ For SwiftData, always isStoredInMemoryOnly: true — never seed the real store
  • ❌ Don't hit the live network in a preview — pin the ViewModel/service to a state
  • ❌ Don't ship preview data — #if DEBUG is non-negotiable

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