Skip to content

ChiefVenzox/NotebookFlowKit

Repository files navigation

NotebookFlowKit

NotebookFlowKit is a lightweight Swift Package for rendering JSON-defined onboarding, survey, quiz, setup wizard, and learning flows as native SwiftUI screens.

Design a flow in Jupyter or Python, export it as JSON, add the JSON file to your app bundle, and render it without hardcoding every screen.

Requirements

  • Swift Package Manager
  • iOS 16+
  • macOS 13+
  • SwiftUI
  • No external dependencies

Installation

Add NotebookFlowKit to your app in Xcode:

  1. Open File > Add Package Dependencies.
  2. Enter this repository URL.
  3. Add the NotebookFlowKit library to your app target.

Or add it to Package.swift:

.package(url: "https://github.com/ChiefVenzox/NotebookFlowKit.git", from: "0.1.0")
.product(name: "NotebookFlowKit", package: "NotebookFlowKit")

JSON Flow

Add a JSON file such as starter_flow.json to your app target:

{
  "name": "StarterFlow",
  "screens": [
    {
      "id": "welcome",
      "type": "text",
      "title": "Welcome",
      "subtitle": "Let's personalize your app",
      "next": "goal"
    },
    {
      "id": "goal",
      "type": "choice",
      "title": "What is your goal?",
      "options": ["Focus", "Fitness", "Learning"],
      "next": "name"
    },
    {
      "id": "name",
      "type": "input",
      "title": "What should we call you?",
      "next": "done"
    },
    {
      "id": "done",
      "type": "completion",
      "title": "You're ready",
      "subtitle": "Your setup is complete"
    }
  ]
}

Supported screen types:

  • text
  • choice
  • multiChoice
  • input
  • completion

Aliases such as multi_choice, single_choice, text_input, and done are also accepted.

Conditional Navigation

Use a string next value for linear flows:

{
  "id": "goal",
  "type": "choice",
  "title": "What is your goal?",
  "options": ["Focus", "Fitness", "Learning"],
  "next": "name"
}

Use an object next value for answer-based branching:

{
  "id": "goal",
  "type": "choice",
  "title": "What is your goal?",
  "options": ["Focus", "Fitness", "Learning"],
  "next": {
    "Fitness": "fitness_setup",
    "Learning": "learning_setup",
    "default": "focus_setup"
  }
}

For single choice screens, the selected option is matched against the route keys. For multi-choice screens, the first selected option with a matching route wins. default is used when no route matches.

SwiftUI Usage

import SwiftUI
import NotebookFlowKit

struct OnboardingView: View {
    var body: some View {
        NotebookFlowView(fileName: "starter_flow") { result in
            print(result.answers)
        }
    }
}

You can also render an in-memory flow:

let flow = NotebookFlow(
    name: "StarterFlow",
    screens: [
        FlowScreen(id: "welcome", type: .text, title: "Welcome", next: "goal"),
        FlowScreen(id: "goal", type: .choice, title: "What is your goal?", options: ["Focus", "Learning"], next: "done"),
        FlowScreen(id: "done", type: .completion, title: "You're ready")
    ]
)

NotebookFlowView(flow: flow) { result in
    print(result.answers)
}

Collected answers are returned as [String: FlowAnswer], keyed by screen ID:

let goal = result.choice("goal")
let name = result.text("name")
let topics = result.choices("topics")

You can still inspect raw answers directly:

print(result.answers)

NotebookFlowKit shows a basic progress bar by default. Disable it if your app already has its own progress UI:

NotebookFlowView(
    fileName: "starter_flow",
    showsProgress: false,
    onComplete: { result in
        print(result.answers)
    }
)

Python/Jupyter Helper

Use Python/notebook_flow.py in a notebook or Python script:

from notebook_flow import NotebookFlow

flow = NotebookFlow("StarterFlow")
flow.text("welcome", title="Welcome", subtitle="Let's personalize your app", next="goal")
flow.choice("goal", title="What is your goal?", options=["Focus", "Fitness", "Learning"], next="name")
flow.input("name", title="What should we call you?", next="done")
flow.completion("done", title="You're ready", subtitle="Your setup is complete")
flow.export("starter_flow.json")

Branching flows can pass a Python dictionary as next:

flow.choice(
    "goal",
    title="What is your goal?",
    options=["Focus", "Fitness", "Learning"],
    next={
        "Fitness": "fitness_setup",
        "Learning": "learning_setup",
        "default": "focus_setup",
    },
)

AI-generated SwiftUI flows

NotebookFlowKit can generate NotebookFlow values from natural language prompts through a provider-agnostic interface. The package does not include an LLM provider and does not depend on OpenAI, Anthropic, Gemini, or any other AI SDK. You connect your own API client by conforming to NotebookFlowLLMProvider.

The generated text is cleaned, decoded as NotebookFlow JSON, and validated before it is returned for rendering.

import NotebookFlowKit

struct MockLLMProvider: NotebookFlowLLMProvider {
    func generate(prompt: String) async throws -> String {
        """
        {
          "name": "Onboarding",
          "screens": [
            {
              "id": "welcome",
              "type": "text",
              "title": "Welcome",
              "next": "goal"
            },
            {
              "id": "goal",
              "type": "choice",
              "title": "What is your main goal?",
              "options": ["Focus", "Fitness", "Learning"],
              "next": "done"
            },
            {
              "id": "done",
              "type": "completion",
              "title": "You're ready"
            }
          ]
        }
        """
    }
}

let generator = NotebookFlowAIGenerator(provider: MockLLMProvider())
let flow = try await generator.generateFlow(
    from: "Create a short onboarding flow for a personal productivity app."
)

You can render the generated flow like any other in-memory flow:

NotebookFlowView(flow: flow) { result in
    print(result.answers)
}

Validation

NotebookFlowLoader validates JSON before rendering:

  • the flow must contain at least one screen
  • screen IDs must be unique
  • next values must point to existing screens
  • choice and multi-choice screens must include options

Examples

  • Examples/starter_flow.json
  • Examples/conditional_flow.json
  • Examples/DemoNotebookFlowView.swift

Tests

Run the package tests:

swift test

Author

Created by ChiefVenzox.

Website: www.hnmlabs.com

About

Render Jupyter/Python-defined JSON flows as native SwiftUI onboarding, survey, quiz, and setup screens.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors