Skip to content

Get started

A state machine, designed for UIs. Every interface starts as a description: open/closed, hovered, dragging, on this event, go there. That description is pure intent, and it rarely changes. What changes is the code you write to express it, tangled into whatever framework you happen to be using. Dunky turns the description into the thing that actually runs: an agnostic machine that holds the behavior and nothing else, portable everywhere JavaScript does, and built for heavy load.

AGNOSTIC SUBSTRATE
🫏 βš™οΈ >> 🧠 >> πŸ”Œ >> ✨
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ dunky β”‚ β”‚ machine β”‚ β”‚ binding β”‚ β”‚ behavior β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ the engine β”‚ β”‚ states + β”‚ β”‚ neutral wire β”‚ β”‚ live feature β”‚
β”‚ that runs β”‚ β”‚ events + β”‚ β”‚ agnostic β”‚ β”‚ on DOM / β”‚
β”‚ machines β”‚ β”‚ logic β”‚ β”‚ events/attrs β”‚ β”‚ TUI / RN β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
powers decides connects appears

I’ve spent the last decade building design systems. New company, new tech stack, new framework, but always the same story: rebuild the button, the tooltip, the dialog, the combobox. From scratch. Again.

The behaviors never really changed. Focus management, keyboard navigation, ARIA roles, state transitions, it’s all been documented by the W3C for years. The ARIA Authoring Practices Guide literally has the recipe. Yet every new project meant reinventing the same wheel, just with whatever fancy hammer was trending that quarter.

The final boss? Trying to port a full component library to a collaborative whiteboard running on a canvas engine.

No DOM, yet, a tooltip is still a tooltip. A menu still needs arrow-key navigation. A dialog still needs to trap focus. The primitives don’t care about your rendering layer. The behaviors are the same. They always are.

That’s when I finally got fed up and started 🫏 Dunky.

The cost isn’t the core, it’s everything around it: bending behavior you already understand to fit each platform and framework’s quirks. The DOM fires keydown; React Native has no key events. React wants state in a hook; the canvas wants a frame loop. The state graph is identical, but the wiring is rewritten from scratch every time. The wiring never compounds: you re-solve the same integration against a slightly different host, forever.

The old dream is write once, render everywhere, and it breaks for an honest reason: the render genuinely should differ. A tooltip can’t hover on a touch screen. aria-* is a DOM contract; React Native speaks accessibilityRole. Force one render across all of them and you get a component that’s slightly wrong everywhere.

What’s actually the same across every target was never the render, it’s the behavior. That’s the part worth writing once.

The β€œwrite it once, run it everywhere” dream isn’t new. What is new is that AI-assisted development makes behavior-driven primitives dramatically more powerful. When your components are pure state machines with typed inputs and outputs, an AI can reason about them precisely, generate implementations, write tests, migrate between versions, without hallucinating framework-specific magic.

Properly specified behavior is a gift to AI tooling. And properly driven AI is a gift back.

Dunky splits the problem into three independent layers:

LayerPackageJob
Behavior@dunky.dev/state-machineWhat a component does
Styles@dunky.dev/style-engineHow it looks
Render@dunky.dev/react-state-machine (and friends)Where it renders

You’re here for layer one.

The state machine defines behavior once, keyboard interactions, focus, ARIA, transitions, and that logic runs identically in every render substrate. πŸŽ‰