> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prism.byescaleira.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Build your first Prism project — choose an iOS app with state management or a server API with database.

# Quickstart

Pick your path. Both take under 15 minutes.

<Tabs>
  <Tab title="iOS App">
    Build a **notes app** with PrismArchitecture (state management), PrismUI (components), and PrismStorage (persistence).

    <Info>
      Requires Swift 6.3+, Xcode 16.4+, iOS 26+. See [Installation](/installation) for details.
    </Info>

    ## Create Your Project

    <Steps>
      <Step title="Initialize a Swift package">
        ```bash theme={null}
        mkdir notes-app && cd notes-app
        swift package init --type executable
        ```
      </Step>

      <Step title="Add Prism to Package.swift">
        ```swift title="Package.swift" theme={null}
        // 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](/ui/theme), [PrismArchitecture](/architecture/store), [PrismNetwork](/network/client), [PrismStorage](/storage/overview), and more.
      </Step>

      <Step title="Build">
        ```bash theme={null}
        swift build
        ```
      </Step>
    </Steps>

    ## Define Your Feature

    Prism uses the [reducer pattern](/architecture/reducer) — state is a struct, changes happen through actions, side effects return via `PrismEffect`.

    ```swift title="NotesFeature.swift" theme={null}
    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
            }
        }
    }
    ```

    <Tip>
      The [reducer](/architecture/reducer) is pure — all async work (storage, network) happens in [effects](/architecture/advanced). This makes state changes predictable and testable.
    </Tip>

    ## Build the UI

    PrismUI provides [ready-made components](/ui/components) with [design tokens](/ui/tokens) and [theming](/ui/theme).

    ```swift title="NotesView.swift" theme={null}
    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

    ```swift title="NotesApp.swift" theme={null}
    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

    ```bash theme={null}
    swift run
    ```

    Or open in Xcode: `open Package.swift`

    ## What You Used

    | Module                                   | What for                                         |
    | ---------------------------------------- | ------------------------------------------------ |
    | [PrismArchitecture](/architecture/store) | `PrismStore`, `PrismReducer`, `PrismEffect`      |
    | [PrismUI](/ui/components)                | `PrismButton`, `PrismTextField`, `PrismListItem` |
    | [PrismStorage](/storage/defaults-disk)   | `PrismDefaultsStore` for persistence             |

    ## Next Steps — Client

    <CardGroup cols={2}>
      <Card title="Add Networking" icon="wifi" href="/network/client">
        Sync notes to a remote API with type-safe endpoints and retry policies.
      </Card>

      <Card title="Middleware" icon="layer-group" href="/architecture/middleware">
        Add logging, analytics, or undo/redo middleware to your store.
      </Card>

      <Card title="More Components" icon="palette" href="/ui/components">
        Explore cards, chips, charts, forms, and 100+ more SwiftUI components.
      </Card>

      <Card title="Encrypted Storage" icon="lock" href="/storage/encryption-compression">
        Wrap your store with AES-GCM encryption for sensitive data.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="Server API">
    Build a **bookmark manager API** with PrismServer — routing, database, validation, and middleware.

    <Info>
      Requires Swift 6.3+, macOS 26+. See [Installation](/installation) for details.
    </Info>

    ## Create Your Project

    <Steps>
      <Step title="Initialize a Swift package">
        ```bash theme={null}
        mkdir bookmarks-api && cd bookmarks-api
        swift package init --type executable
        ```
      </Step>

      <Step title="Add Prism to Package.swift">
        ```swift title="Package.swift" theme={null}
        // swift-tools-version: 6.0
        import PackageDescription

        let package = Package(
            name: "bookmarks-api",
            platforms: [.macOS(.v14)],
            dependencies: [
                .package(url: "https://github.com/byescaleira/prism.git", from: "4.4.0")
            ],
            targets: [
                .executableTarget(
                    name: "bookmarks-api",
                    dependencies: [
                        .product(name: "PrismServer", package: "prism")
                    ]
                )
            ]
        )
        ```
      </Step>

      <Step title="Build">
        ```bash theme={null}
        swift build
        ```
      </Step>
    </Steps>

    ## Write Your Server

    Replace `Sources/main.swift`:

    ```swift title="Sources/main.swift" theme={null}
    import PrismServer
    import Foundation

    let server = PrismHTTPServer(port: 8080)
    let db = try PrismDatabase(path: "bookmarks.db")

    // Migrations
    let migrator = PrismMigrator(database: db)
    try await migrator.migrate([
        PrismMigration(
            name: "create_bookmarks",
            up: """
                CREATE TABLE bookmarks (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    title TEXT NOT NULL,
                    url TEXT NOT NULL,
                    tags TEXT DEFAULT '',
                    created_at TEXT DEFAULT (datetime('now'))
                )
                """,
            down: "DROP TABLE bookmarks"
        )
    ])

    // Middleware
    await server.use(PrismCORSMiddleware())
    await server.use(PrismLoggingMiddleware())
    await server.use(PrismErrorMiddleware(includeStackTrace: true))

    // List
    await server.get("/bookmarks") { request in
        let rows = try await db.table("bookmarks")
            .orderBy("created_at", ascending: false)
            .get()
        return .json(rows)
    }

    // Create with validation
    await server.post("/bookmarks") { request in
        let validation = request.validateJSON { v in
            v.field("title", .required, .minLength(1), .maxLength(200))
            v.field("url", .required, .url)
        }
        if let errorResponse = validation.errorResponse() { return errorResponse }

        guard let body = request.body,
              let json = try? JSONSerialization.jsonObject(with: body) as? [String: Any] else {
            return PrismHTTPResponse(status: .badRequest, body: .text("Invalid JSON"))
        }

        let title = json["title"] as? String ?? ""
        let url = json["url"] as? String ?? ""
        let tags = json["tags"] as? String ?? ""

        let id = try await db.table("bookmarks").insert([
            "title": .text(title),
            "url": .text(url),
            "tags": .text(tags)
        ])
        return .json(["id": id, "created": true], status: .created)
    }

    // Get one
    await server.get("/bookmarks/:id") { request in
        let id = request.parameters["id"]!
        guard let row = try await db.table("bookmarks")
            .where("id", .text(id))
            .first() else {
            throw PrismAppError.notFound("Bookmark not found")
        }
        return .json(row)
    }

    // Delete
    await server.delete("/bookmarks/:id") { request in
        let id = request.parameters["id"]!
        let changes = try await db.table("bookmarks")
            .where("id", .text(id))
            .delete()
        guard changes > 0 else {
            throw PrismAppError.notFound("Bookmark not found")
        }
        return .json(["deleted": true])
    }

    print("Bookmarks API running on http://localhost:8080")
    try await server.start()
    try await Task.sleep(for: .seconds(.max))
    ```

    <Tip>
      Use `":memory:"` instead of `"bookmarks.db"` for an in-memory database during development. See [Database overview](/server/database/overview) for options.
    </Tip>

    ## Run It

    ```bash theme={null}
    swift run
    ```

    ## Test with curl

    <CodeGroup>
      ```bash title="Create" theme={null}
      curl -X POST http://localhost:8080/bookmarks \
        -H "Content-Type: application/json" \
        -d '{"title": "Swift.org", "url": "https://swift.org", "tags": "swift"}'
      ```

      ```bash title="List" theme={null}
      curl http://localhost:8080/bookmarks
      ```

      ```bash title="Get One" theme={null}
      curl http://localhost:8080/bookmarks/1
      ```

      ```bash title="Delete" theme={null}
      curl -X DELETE http://localhost:8080/bookmarks/1
      ```
    </CodeGroup>

    ## What You Used

    | Module                                    | What for                                                                                                              |
    | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
    | [PrismServer](/server/core/server)        | HTTP server, [routing](/server/core/routing), [request](/server/core/request)/[response](/server/core/response)       |
    | [Middleware](/server/middleware/cors)     | [CORS](/server/middleware/cors), [logging](/server/middleware/logging), [error handling](/server/core/error-handling) |
    | [Database](/server/database/overview)     | SQLite, [query builder](/server/database/queries), [migrations](/server/database/migrations)                          |
    | [Validation](/server/security/validation) | Request body validation rules                                                                                         |

    ## Next Steps — Server

    <CardGroup cols={2}>
      <Card title="Add Authentication" icon="lock" href="/server/middleware/auth">
        Protect endpoints with bearer tokens and session cookies.
      </Card>

      <Card title="Add WebSockets" icon="signal-stream" href="/server/realtime/websocket">
        Build real-time features with WebSocket rooms.
      </Card>

      <Card title="Add GraphQL" icon="diagram-project" href="/server/graphql/schema">
        Expose data through a GraphQL endpoint alongside REST.
      </Card>

      <Card title="Query Builder" icon="database" href="/server/database/queries">
        Go deeper with relationships, connection pools, and models.
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
