Instant snapshots from
SwiftUI #Previews

Prefire turns your #Preview blocks into snapshot tests, living docs & playbooks β€” automatically.

iOS playbook previews snapshot-testing Swift 6 SwiftUI tvOS UIKit Xcode Plugins iOS playbook previews snapshot-testing Swift 6 SwiftUI tvOS UIKit Xcode Plugins

Why Prefire?

The fastest way to create snapshot tests and living documentation from your existing SwiftUI previews

πŸ“Έ

Zero Boilerplate

Snapshot tests from your #Preview blocks β€” no extra code needed.

πŸ“š

Living Docs

Documentation that's always in sync with your UI components.

⚑️

Ultra-Fast Caching

Smart cache system prevents redundant parsing and speeds up builds.

🧩

SwiftUI & UIKit

Works seamlessly with both SwiftUI and legacy UIKit codebases.

πŸ”©

Flexible Integration

CLI, SPM plugin, Xcode plugin, or direct CI integration.

🧠

Flow Understanding

Track user stories, states, variants and complex UI flows.

Key Features

Everything you need for automated snapshot testing and visual documentation

🧠

Smart Preview Parsing

Understands #Preview, @Previewable, flows & variations automatically.

πŸ“Έ

Automatic Snapshots

Generates & executes pixel-perfect tests on every build automatically.

πŸ“š

Interactive Playbook

Beautiful browsable catalog for designers, QA, and stakeholders.

βš™οΈ

CLI & CI Ready

Runs in CI/CD pipelines with zero configuration required.

Installation

Choose the method that fits your workflow best

  1. Add Prefire via File β†’ Add Packages…
  2. Select your unit test target
  3. Attach PrefireTestsPlugin under Build Tool Plugins
  4. Build the target β€” snapshot tests are auto-generated
dependencies: [
    .package(url: "https://github.com/BarredEwe/Prefire", from: "4.0.0")
],
.testTarget(
    plugins: [
        .plugin(name: "PrefireTestsPlugin", package: "Prefire")
    ]
)
brew tap barredewe/prefire
brew install prefire

prefire tests
prefire playbook

Quick Start

Get up and running in less than 5 minutes

  1. 1

    Add Prefire to your Package.swift (see Installation above)

  2. 2

    Create a #Preview, e.g. #Preview { Button("Submit") }

  3. 3

    Run the test target β€” Prefire will generate & run snapshot tests automatically

How Prefire Works

A deep dive into the architecture and workflow

1

Parse Source Files

Scans all Swift files, detecting #Preview blocks and PreviewProviders with modifiers like .prefireEnabled().

2

Cache Models

Fingerprints AST & preview bodies (SHA-256 + timestamps) to skip work on unchanged files.

3

Generate Tests

Uses Stencil templates & your .prefire.yml to emit Swift tests.

4

Build Playbook

Creates PreviewModels.generated.swift grouping previews by UserStory and State.

Internal Architecture

  • πŸ”§
    PrefireCore β€” AST parsing, preview detection & caching layer
  • ⚑️
    PrefireGenerator β€” Stencil-based code generator for tests & models
  • πŸ’Ύ
    PrefireCacheManager β€” Unified fingerprint & file-cache logic
  • πŸ”Œ
    Plugins β€” Xcode & SPM integration points
  • πŸ› 
    prefire CLI β€” Manual tests / playbook commands

Usage Examples

Real-world examples of Prefire in action

#Preview {
  Text("Hello")
}

#Preview {
  LoginView()
    .previewUserStory(.auth)
    .previewState(.loading)
    .snapshot(delay: 0.3, precision: 0.95)
}

Combine .previewUserStory(), .previewState() & .snapshot() to define rich visual flows & quality checks.

Configuration

Customize generation with .prefire.yml at your project root

πŸ“„ Show Example Configuration
test_configuration:
  target: MyApp
  test_file_path: Tests/Generated/PreviewTests.swift
  simulator_device: "iPhone15,2"
  preview_default_enabled: true
  sources:
    - {PROJECT_DIR}/Sources/
  snapshot_devices:
    - iPhone 14
    - iPad
  imports:
    - SwiftUI
    - UIKit
  testable_imports:
    - MyApp

playbook_configuration:
  template_file_path: Templates/PreviewModels.stencil
  preview_default_enabled: true

Open Source

Prefire is fully open source and built by the community. Contributions, issues and stars are always welcome!

PRs, issues and feedback are highly appreciated β€” or just drop us a ⭐️!