glitter-uikit โ Guide
Why this exists
glitter-uikit is an AppKit (native macOS) renderer for glitter. Its upstream source, glimmer-uikit, applies Reagent's model (ratoms, automatic dependency tracking, component-local state) to AppKit; this project deliberately applies a different model โ Replicant's single application-state atom, pure state -> hiccup view function, top-down re-render, and data-driven action-dispatch handlers โ the same model glitter itself applies to GTK4. This guide covers how that model was adapted to a native, retained-mode, Objective-C toolkit that has no DOM underneath it.
glitter-uikit is a whole alternative renderer, not a widget added to an existing registry: it implements glitter.protocols/IRender and IMemory for real AppKit views, exactly as glitter.gtk implements the same two protocols for GTK4. The two are siblings, chosen at mount!'s call site by which library an app requires โ glitter.core's reconciler itself knows nothing about either toolkit.
What glitter-uikit is
A .clj (Jolt/Chez Scheme host, not JVM) library:
(require '[glitter-uikit.app :as app]
'[glitter-uikit.appkit :as appkit]
'[glitter.core :as core])
(defonce state (atom {:count 0}))
(defn view [{:keys [count]}]
[:vbox {:spacing 12}
[:label {:label (str "Count: " count)}]
[:hbox {:spacing 8}
[:button {:label "+ 1" :on {:click [[:action/inc]]}}]]])
(defn execute-actions [_event actions]
(doseq [[kind] actions]
(case kind
:action/inc (swap! state update :count inc)
nil)))
(core/set-dispatch! execute-actions)
(defn -main [& _]
(app/run (fn [window] (appkit/mount! window view state))))
Every subsequent swap! on state fires mount!'s watcher, which routes the re-render through glitter-uikit.app/on-gui (marshalling onto the AppKit main thread when the swap! came from elsewhere) and calls view again; glitter.core's reconciler diffs the new hiccup against the previous vdom and issues the minimal set of IRender/ IMemory calls needed to bring the live AppKit view tree in sync.
Pages
Orientation
examples.mdโ the catalogue of all sixteen runnable namespaces: the eight interactive demos (counter,widgets,temperature,flights,timer,crud,circles,todo) with screenshots and what each shows about the model, plus an index of the eight live-AppKit smokes and the one property each one pins. Also why the screenshots are stills rather than animations for now.architecture.mdโ whyglitter-uikitis a whole alternative renderer rather than a registered widget, the singlereifyimplementing bothIRenderandIMemory(and the:extend-via-metadata-is-broken-under-Jolt finding behind that choice), the el atom that tracks a live view rather than handing the reconciler a raw pointer,mount!'s wiring, the data-driven event model this port adapted from glimmer-uikit's closure-based one, and the:ctor-always-gets-{}finding that shapes every widget spec.porting-and-attribution.mdโ the two sourcing buckets (ported from glimmer-uikit / ported from glitter) and every documented deviation, model adaptation, and defect fix in the port โNOTICE.mdis the authoritative ledger this page summarizes.
AppKit integration
appkit-widget-layer.mdโ the widget mapping layer, why it's shaped as it is, where AppKit is genuinely simpler than GTK (single-branchinsert-before, no suppression set needed) and where it needs more care (NSNotFoundraising uncaught, process-aborting exceptions; pointer-keyed registry cleanup) โ kept deliberately separate from which changes are model adaptations versus which are fixes for real defects in glimmer-uikit v0.1.0.app-loop-and-threading.mdโ theNSApplicationbootstrap,on-gui's three-way thread branch, the single long-livedCFRunLoopSource+ thunk-queue marshaller (and the atomic-drain fix that closed a dropped-callback race), and the flag-ordering defectmain_thread_smoke.cljcaught live.
Verify
testing-and-tasks.mdโ the headless unit suite and what each namespace in it covers, the live-AppKit smokes and what each one actually pins (reading the real AppKit tree, never this renderer's own bookkeeping), and the fulljolt/bbtask surface that runs them.limitations.mdโ every known v1 gap and the reasoning behind leaving each one unfixed for now, including the two gaps that are about how confidently something is known rather than what the code does.
See also
- glimmer-uikit โ the Reagent-style sibling this project forked its AppKit FFI/widget layer from.
- glitter โ the source of
glitter.core's reconciler and the GTK4 renderer this project mirrors the structure of. README.md(repo root) โ feature overview, quick start, requirements, and the fulljolt/bbcommand reference.CONTRIBUTING.md(repo root) โ conventions, gotchas, file map and scope.NOTICE.md(repo root) โ the authoritative file-by-file attribution ledger and the Known gaps listlimitations.mdexpands on.