spotlight-indexing
Generates Core Spotlight indexing infrastructure for making app content searchable via system Spotlight with rich attributes and deep link integration. Use when user wants to index content for Spotlight search, Siri suggestions, or system-wide searchability.
What this skill does
# Spotlight Indexing Generator
Generate production Core Spotlight indexing infrastructure — makes app content searchable via Spotlight (and Siri suggestions). Indexes items with rich attributes, handles search continuation into your app, and manages index lifecycle.
## When This Skill Activates
Use this skill when the user:
- Asks to "add spotlight search" or "spotlight indexing"
- Mentions "core spotlight" or "CSSearchableItem"
- Wants to make "searchable content" or "index content" for system search
- Asks about "system search" integration or "Siri suggestions"
- Wants content to appear in Spotlight results
- Mentions "NSUserActivity" for search or handoff
## Pre-Generation Checks
### 1. Project Context Detection
- [ ] Check deployment target (iOS 16+ / macOS 13+)
- [ ] Check Swift version (requires Swift 5.9+)
- [ ] Check for @Observable support (iOS 17+ / macOS 14+)
- [ ] Identify source file locations
### 2. Existing CoreSpotlight Detection
Search for existing Spotlight code:
```
Glob: **/*Spotlight*.swift, **/*Searchable*.swift, **/*CSSearchable*.swift
Grep: "CoreSpotlight" or "CSSearchableIndex" or "CSSearchableItem"
```
If existing Spotlight code found:
- Ask if user wants to replace or augment it
- If augmenting, identify what's missing and generate only those pieces
### 3. Deep Linking Detection
Search for existing deep link or navigation setup:
```
Grep: "NavigationPath" or "onOpenURL" or "NSUserActivity" or "DeepLink"
```
If deep linking exists:
- Integrate SpotlightSearchHandler with existing router
- If not, generate standalone handler with guidance on wiring it up
### 4. Entitlements Check
Verify CoreSpotlight doesn't require special entitlements (it doesn't — it's a standard framework), but check if the app uses App Groups for shared index across extensions.
## Configuration Questions
Ask user via AskUserQuestion:
1. **Content types to index?**
- Articles / blog posts (titles, body text, authors)
- Products (name, description, price, images)
- Contacts / people (name, phone, email)
- Tasks / reminders (title, due date, priority)
- Custom (user describes their model)
2. **Include thumbnails?**
- Yes — index thumbnail images alongside text attributes
- No — text-only attributes (smaller index, faster)
3. **Indexing strategy?**
- Batch indexing (index all content at once, e.g., on first launch or sync)
- Incremental indexing (index items as they're created/updated/deleted)
- Both (batch for initial load, incremental for changes)
4. **Include Siri suggestions / shortcuts?**
- Yes — make content eligible for Siri suggestions and predictions
- No — Spotlight search only
## Generation Process
### Step 1: Read Templates
Read `templates.md` for production Swift code.
Read `patterns.md` for architecture guidance and best practices.
### Step 2: Create Core Files
Generate these files:
1. `SpotlightIndexable.swift` — Protocol any model can conform to
2. `SpotlightIndexManager.swift` — Actor wrapping CSSearchableIndex with batching
3. `SpotlightAttributeBuilder.swift` — Fluent builder for CSSearchableItemAttributeSet
### Step 3: Create Integration Files
4. `SpotlightSearchHandler.swift` — Handles NSUserActivity continuation from Spotlight taps
### Step 4: Create Optional Files
Based on configuration:
- `SpotlightSyncModifier.swift` — If incremental indexing selected (ViewModifier for auto index/deindex)
- Add NSUserActivity + eligibleForSearch if Siri suggestions selected
### Step 5: Determine File Location
Check project structure:
- If `Sources/` exists -> `Sources/SpotlightIndexing/`
- If `App/` exists -> `App/SpotlightIndexing/`
- Otherwise -> `SpotlightIndexing/`
## Output Format
After generation, provide:
### Files Created
```
SpotlightIndexing/
├── SpotlightIndexable.swift # Protocol for indexable models
├── SpotlightIndexManager.swift # Actor-based index management
├── SpotlightAttributeBuilder.swift # Fluent attribute builder
├── SpotlightSearchHandler.swift # Handle Spotlight tap continuation
└── SpotlightSyncModifier.swift # Auto index/deindex ViewModifier (optional)
```
### Integration with Content Creation/Update
**Make a model searchable:**
```swift
// Conform your model to SpotlightIndexable
struct Article: SpotlightIndexable {
let id: UUID
let title: String
let body: String
let author: String
let tags: [String]
var spotlightID: String { id.uuidString }
var spotlightTitle: String { title }
var spotlightDescription: String { String(body.prefix(300)) }
var spotlightKeywords: [String] { tags + [author] }
var spotlightThumbnailData: Data? { nil }
var spotlightDomainIdentifier: String { "com.myapp.articles" }
}
```
**Index on create, remove on delete:**
```swift
func createArticle(_ article: Article) async throws {
try await repository.save(article)
await SpotlightIndexManager.shared.index(items: [article])
}
func deleteArticle(_ article: Article) async throws {
try await repository.delete(article)
await SpotlightIndexManager.shared.remove(identifiers: [article.spotlightID])
}
```
**Batch reindex (e.g., on first launch):**
```swift
func reindexAllContent() async {
let articles = await repository.fetchAll()
await SpotlightIndexManager.shared.reindexAll(items: articles, domain: "com.myapp.articles")
}
```
**Handle Spotlight tap (App or Scene delegate):**
```swift
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onContinueUserActivity(CSSearchableItemActionType) { activity in
SpotlightSearchHandler.shared.handle(activity)
}
}
}
}
```
**Auto index/deindex with ViewModifier:**
```swift
struct ArticleDetailView: View {
let article: Article
var body: some View {
ScrollView {
Text(article.body)
}
.spotlightIndexed(article) // Indexes on appear, deindexes on disappear
}
}
```
### Testing
```swift
@Test
func indexAndRetrieveItem() async throws {
let manager = SpotlightIndexManager(index: MockSearchableIndex())
let article = Article(id: UUID(), title: "Test", body: "Body", author: "Author", tags: ["swift"])
await manager.index(items: [article])
#expect(manager.indexedCount == 1)
}
@Test
func batchIndexChunksCorrectly() async throws {
let mockIndex = MockSearchableIndex()
let manager = SpotlightIndexManager(index: mockIndex, batchSize: 10)
let items = (0..<25).map { makeArticle(index: $0) }
await manager.index(items: items)
#expect(mockIndex.indexCallCount == 3) // 10 + 10 + 5
}
@Test
func handleSpotlightContinuation() async throws {
let handler = SpotlightSearchHandler()
let activity = NSUserActivity(activityType: CSSearchableItemActionType)
activity.userInfo = [CSSearchableItemActivityIdentifier: "article-123"]
let itemID = handler.extractItemID(from: activity)
#expect(itemID == "article-123")
}
```
## Common Patterns
### Index Item on Create
Every time a model is created or updated, index it immediately:
```swift
await SpotlightIndexManager.shared.index(items: [newItem])
```
### Remove on Delete
When content is deleted, remove it from the index:
```swift
await SpotlightIndexManager.shared.remove(identifiers: [item.spotlightID])
```
### Batch Reindex
After app update or data migration, reindex all content:
```swift
await SpotlightIndexManager.shared.reindexAll(items: allItems, domain: "com.myapp.articles")
```
### Handle Search Continuation
When user taps a Spotlight result, the app receives an NSUserActivity. Extract the item ID and navigate:
```swift
.onContinueUserActivity(CSSearchableItemActionType) { activity in
if let id = activity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
navigationPath.append(Route.detail(id: id))
}
}
```
## Gotchas
### Index Size Limits
- CSSearchableIndex has no hard documented limit, but Apple recommeRelated in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.