Skip to content

formspec-swift: SwiftUI renderer for iOS/macOS #5

Description

@mikewolfd

Motivation

iOS and macOS apps need to render formspec forms as native SwiftUI views. A Swift Package that bridges to formspec-engine via a hidden WKWebView provides full spec compliance without reimplementing the engine in Swift.

Architecture

Three layers:

  1. Bridge — Hidden WKWebView loads an HTML bundle (esbuild'd formspec-engine JS + inlined WASM). Swift sends EngineCommand JSON messages, receives EngineEvent JSON messages via WKScriptMessageHandler.
  2. State@Observable classes (FieldState, FormState) updated from bridge events. SwiftUI views react automatically via observation.
  3. RendererFormspecForm view walks the LayoutNode tree. Component map ([String: any FormspecComponent]) provides default SwiftUI components, overridable by the consumer.

Scope

  • Swift Package (SPM) targeting iOS 17+ / macOS 14+
  • Hidden WKWebView bridge with typed EngineCommand/EngineEvent protocol
  • @observable state objects (FieldState, FormState, LayoutNode)
  • Auto-renderer that walks LayoutNode tree with component map
  • Default SwiftUI components for core field types
  • XCTest suite for bridge, state, and renderer layers

Status

Implementation plan and design spec complete. Initial code in packages/formspec-swift/.

Key References

  • Design spec: thoughts/specs/2026-03-25-formspec-swift-design.md
  • Implementation plan: thoughts/plans/2026-03-25-formspec-swift.md

Tech

  • Swift 5.9+, SwiftUI, iOS 17+ @observable
  • WKWebView, WKScriptMessageHandler
  • esbuild for HTML bundle
  • XCTest

Acceptance Criteria

  • Swift Package builds and resolves via SPM
  • Hidden WKWebView bridge initializes formspec-engine and processes commands
  • State objects update reactively from engine events
  • Auto-renderer produces native SwiftUI views from a formspec definition
  • Component map is overridable by consumers
  • XCTest suite covers bridge, state, and renderer layers

Part of #4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions