Skip to main content

Quickstart

Pick your path. Both take under 15 minutes.
Build a notes app with PrismArchitecture (state management), PrismUI (components), and PrismStorage (persistence).
Requires Swift 6.3+, Xcode 16.4+, iOS 26+. See Installation for details.

Create Your Project

1

Initialize a Swift package

mkdir notes-app && cd notes-app
swift package init --type executable
2

Add Prism to Package.swift

Package.swift
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "notes-app",
    platforms: [.iOS(.v17), .macOS(.v14)],
    dependencies: [
        .package(url: "https://github.com/byescaleira/prism.git", from: "4.4.0")
    ],
    targets: [
        .executableTarget(
            name: "notes-app",
            dependencies: [
                .product(name: "Prism", package: "prism")
            ]
        )
    ]
)
import Prism gives you PrismUI, PrismArchitecture, PrismNetwork, PrismStorage, and more.
3

Build

swift build

Define Your Feature

Prism uses the reducer pattern — state is a struct, changes happen through actions, side effects return via PrismEffect.
NotesFeature.swift
import Prism

struct Note: Identifiable, Codable, Sendable, Equatable {
    let id: UUID
    var title: String
    var body: String
    var createdAt: Date

    init(title: String, body: String) {
        self.id = UUID()
        self.title = title
        self.body = body
        self.createdAt = .now
    }
}

struct NotesFeature: PrismReducer {
    struct State: Sendable, Equatable {
        var notes: [Note] = []
        var draft = ""
    }

    enum Action: Sendable {
        case addNote
        case updateDraft(String)
        case deleteNote(UUID)
        case loaded([Note])
    }

    let storage = PrismDefaultsStore(suite: "com.app.notes")

    func reduce(into state: inout State, action: Action) -> PrismEffect<Action> {
        switch action {
        case .addNote:
            guard !state.draft.isEmpty else { return .none }
            let note = Note(title: state.draft, body: "")
            state.notes.insert(note, at: 0)
            state.draft = ""
            return .run { [notes = state.notes] _ in
                try storage.save(notes, forKey: "notes")
            }

        case .updateDraft(let text):
            state.draft = text
            return .none

        case .deleteNote(let id):
            state.notes.removeAll { $0.id == id }
            return .run { [notes = state.notes] _ in
                try storage.save(notes, forKey: "notes")
            }

        case .loaded(let notes):
            state.notes = notes
            return .none
        }
    }
}
The reducer is pure — all async work (storage, network) happens in effects. This makes state changes predictable and testable.

Build the UI

PrismUI provides ready-made components with design tokens and theming.
NotesView.swift
import Prism

struct NotesView: View {
    let store: PrismStore<NotesFeature.State, NotesFeature.Action>

    var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                // Input area
                HStack {
                    PrismTextField("New note...", text: Binding(
                        get: { store.state.draft },
                        set: { store.send(.updateDraft($0)) }
                    ))
                    PrismButton("Add", variant: .filled) {
                        store.send(.addNote)
                    }
                    .disabled(store.state.draft.isEmpty)
                }
                .padding()

                // Notes list
                List {
                    ForEach(store.state.notes) { note in
                        PrismListItem(note.title, subtitle: note.createdAt.formatted())
                    }
                    .onDelete { indexSet in
                        for index in indexSet {
                            store.send(.deleteNote(store.state.notes[index].id))
                        }
                    }
                }
            }
            .navigationTitle("Notes")
        }
    }
}

Wire It Up

NotesApp.swift
import Prism

@main
struct NotesApp: App {
    let store = PrismStore(
        initialState: NotesFeature.State(),
        reducer: NotesFeature()
    )

    var body: some Scene {
        WindowGroup {
            NotesView(store: store)
                .prismTheme(.default)
                .task {
                    let storage = PrismDefaultsStore(suite: "com.app.notes")
                    if let notes: [Note] = try? storage.load(forKey: "notes") {
                        store.send(.loaded(notes))
                    }
                }
        }
    }
}

Run It

swift run
Or open in Xcode: open Package.swift

What You Used

ModuleWhat for
PrismArchitecturePrismStore, PrismReducer, PrismEffect
PrismUIPrismButton, PrismTextField, PrismListItem
PrismStoragePrismDefaultsStore for persistence

Next Steps — Client

Add Networking

Sync notes to a remote API with type-safe endpoints and retry policies.

Middleware

Add logging, analytics, or undo/redo middleware to your store.

More Components

Explore cards, chips, charts, forms, and 100+ more SwiftUI components.

Encrypted Storage

Wrap your store with AES-GCM encryption for sensitive data.