# Druid gives Defold a component model for GUI nodes, and its input stack decides which widget wins

> Insality/druid is a Lua UI framework for the Defold engine that attaches logic to nodes you place in the Defold GUI editor, with buttons, scroll views, lists, text and blockers, reusable widgets built from a .gui file plus a .lua file, and a stack based input system where the most recently created component is checked first. It is MIT licensed and installed by adding two library URLs to game.project.

**Insality/druid** — Powerful Defold UI component framework

- Repository: https://github.com/Insality/druid
- Website: https://insality.github.io/druid/
- Stars: 603 · Forks: 61
- Language: Lua
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/insality-druid

## Logic goes on top of nodes you already placed in the GUI editor

Druid is a UI component framework for the Defold engine, and the mental model it asks for is specific.

You build the window in the Defold GUI editor, and you attach a logic to the nodes, whether that logic is a button, a scroll view, a data list or one of your own components. The documentation states it directly: to make UI you need to place nodes in the Defold GUI editor, then attach a logic to them.

That is different from the usual GUI code-first frameworks, where a script builds the widget tree at run time. Here the visual layout is a Defold GUI asset, and Druid binds behaviour to the nodes inside it by id.

The example in the documentation is a shop window laid out as a tree, with a title, a close button, a scroll view containing a scroll content node that holds a cloned row prefab, and a buy button. The scroll view is the size of the window and the content node is taller than the view, which is how a scrolling list is expressed in Defold.

The ids are then assigned to the components in the init function of the GUI script:

```lua
self.druid = druid.new(self)

self.druid:new_text("title", "Shop")
self.druid:new_button("close", self.on_close)
self.druid:new_scroll("scroll", "content")
self.druid:new_button("buy", self.on_buy)
```

The Druid instance is created from the script itself, and each call binds a component to a node id. new_text takes an id and a string, new_button takes an id and a callback, and new_scroll takes the id of the view and the id of its content.

The whole point of that arrangement is that the layout lives in the editor, where a designer can move it, and the behaviour lives in Lua, where a programmer can change it, and neither has to know much about the other.

## A widget is a .gui file next to a .lua file

The reusable unit in Druid is called a widget, and its definition is pleasantly small: a .gui file plus a .lua file.

The example given is a health bar, where the .gui file contains the root, the fill and the label nodes. The matching .lua file initialises the components for those nodes:

```lua
function M:init()
	self.progress = self.druid:new_progress("fill", "x")
	self.label = self.druid:new_text("label")
end
```

The progress component is created against the fill node with an axis argument of "x", and the text component against the label node.

To use it, you add the health_bar.gui template to your screen and initialise it with the new_widget function, passing the widget module and its id:

```lua
self.health_bar = self.druid:new_widget(health_bar, "health_bar")
```

This is the part that makes Druid composable. A widget is a self contained piece of interface with its own layout asset and its own script, and the parent screen does not need to know how it is built internally, only that it can be created by id.

The same pattern applies to your own components. The feature list describes widgets as a reusable piece being a .gui plus a .lua, and the components as logic over nodes you already placed inside the GUI, which includes a button, a scroll view, infinity lists, input and many others.

The live examples linked from the documentation are the fastest way to see the range, because they are the same components the framework ships with, running in a browser.

## Input is a stack, and the newest component is checked first

The input model is the most consequential design decision in the framework, and it is stated in one line in the feature list: input is stack based, with priority, and the last created is checked first.

That ordering rule solves a real problem in game UI. When a modal panel opens over a scrollable list, the panel must receive the tap even if the list is underneath it, and the list must not scroll. With a stack where the most recently created component is consulted first, opening a panel is a matter of creating it, and dismissing it is a matter of removing it.

It also explains the existence of the Blocker component, described as logic over a GUI node whose job is to not pass any user input below the node's area size. A blocker is how you reserve an area of the screen for input without putting a visible widget there.

The events side of the framework is built on a separate project, Defold Event, and the feature list says callbacks go through it. That is a design choice worth noticing: the event system is not part of Druid, it is a dependency, which is also why the setup instructions ask you to add two library URLs rather than one.

The base usage pattern in the documentation shows the whole lifecycle. A gui_script requires the druid module, creates a Druid instance in init, creates the components, and then forwards the standard Defold callbacks to the instance: final calls druid:final, update calls druid:update with the delta time, on_message calls druid:on_message, and on_input returns druid:on_input so the framework can consume the input before it reaches your game code.

That last one is the hook that makes the input stack work, since a gui_script that forgets to return the result of on_input will break the priority order for everything underneath it.

## Installation is two URLs in game.project and a fetch

Druid is a Defold library, and Defold libraries are declared in the project file rather than installed with a package manager.

The instructions say to open your game.project file and add the listed lines to the dependencies field under the project section. There are two of them, because Druid depends on Defold Event. The first is the Defold Event archive:

```
https://github.com/Insality/defold-event/archive/refs/tags/21.zip
```

and the second is Druid itself:

```
https://github.com/Insality/druid/archive/refs/tags/1.4.0.zip
```

After that, you select Project, then Fetch Libraries, to update the library dependencies. The documentation notes that this happens automatically whenever you open a project, so you only need to do it manually if the dependencies change without reopening the project.

There is a shortcut, and it is worth knowing about. The documentation says the library can be installed from the Asset Store extension to skip this step, which is the Defold ecosystem's own distribution channel for library dependencies.

One thing to check before you start is the version. The URL given for Druid points at the 1.4.0 tag, while the release list in the documentation points to the releases page, and the most recent published release named in the repository metadata is 1.3.0 from 2026-08-27. If you copy the URL verbatim you may be ahead of, or behind, the release you would get from the releases page, so it is worth deciding which of the two you actually want and checking that the tag exists.

The input side has its own requirement. Druid uses the /builtins/input/all.input_binding input bindings, so either set the Runtime, then Input, then Game Binding field in your game.project input section to that file, or add the specific bindings you need to your own input binding file.

## Library size is measured, and you can strip what you do not use

The size table is one of the more useful bits of practical information in the documentation, because UI libraries have a habit of being heavy.

The library size is calculated from the build report per platform. The full size, which contains all components, is 84.52 KB for HTML5 and 141.03 KB for desktop and mobile. The documentation adds the important caveat that the full size contains all components and that they can be stripped out in the build process if you do not need them.

So the figure to plan against is the worst case, and the number you will actually ship is smaller. That is a meaningful difference for an HTML5 build, where every kilobyte is download, and for a mobile build where it competes with your art and audio.

The repository supports that story. There is a settings_deployer directory at the top level, which suggests the build process can apply settings, and a .defignore file, which is Defold's mechanism for excluding files from the build. Combined with the strip instruction, that gives you two levers: exclude files you do not need, and let the build report tell you what is left.

For a project that will ship on mobile, the sensible thing is to add Druid, build once, and read the report before committing to the framework, rather than trusting the number in the table.

## The component list and the documentation layout

The component catalogue is where you find out whether the framework covers the screens you need, and it is a table rather than a narrative.

The components listed are Button, described as logic over a GUI node that handles user click interactions including click, long click and double click; Text, logic over a GUI text node that by default fits the text inside the text node's size area with different adjust modes; Scroll, logic over two GUI nodes, an input and a content node, providing basic behaviour for scrollable content; Blocker, which stops input passing below its node area; and a Back Handler, which calls a callback on a user action. The table links each to an API page and to a live example.

The API documentation is organised into a quick reference and a set of deeper pages: the Druid instance returned by druid.new, a helper page described as a lot of useful functions, a Druid Color page of colour utility functions, and a widgets page.

The repository layout mirrors that. There is an api/ directory for the reference, a wiki/ directory with the basic usage guide, the advanced setup page and the widgets page, an example/ directory containing a full project with assets, components, templates, locales and examples, a templates/ directory at the top level, a test/ directory, and a druid/ directory holding the library source itself.

There is also a small set of quality signals visible in the tree: a .luacov configuration, a codecov.yml, a CI workflow badge, and a .defignore. The library source, the example project and the tests live in the same repository, which is convenient for contributors and means the example doubles as a working reference for how a real project wires Druid up.

## MIT terms, regular releases, and a documentation lag

The licence is MIT, which is the permissive choice and only requires keeping the copyright and licence notice in distributions. The project also carries a settings_deployer directory and a CONTRIBUTING.md, so there is a place where build configuration and contribution guidance live.

The release history is regular. The published versions are 1.3.0 from 2026-08-27, 1.2.5 from 2026-07-01 and 1.2.0 from 2026-02-24. That is a patch release, a feature release and another patch release over about six months, with the release badge pointing at the latest tag by date.

The repository is not archived and the last push was on 2026-10-17, close to the date of this writing, so the work is current.

The one inconsistency worth flagging is the version in the setup instructions. The dependency URL points at the 1.4.0 tag, while the newest published release named in the repository metadata is 1.3.0. Either the setup instructions were written against a newer tag than the one that appears in the release listing, or the tag in the instructions refers to something else. A reader who pastes the URL and finds nothing should check the releases page rather than assuming the project is broken.

Beyond that, the practical adoption path is short. Add the two dependencies, fetch them, point the input binding at the built-in file, create a Druid instance in the gui_script, and forward the lifecycle callbacks. Everything else is reading the quick API reference and picking the components you need.

## Conclusion

Use Druid if you are building a Defold game with a real interface, because it gives you a component model over GUI nodes, widgets you can reuse, and an input priority system that a raw GUI script does not provide. Do not expect it to be usable outside Defold, since it is built on Defold GUI nodes, Defold event handling and the Defold library dependency mechanism. Before adopting, add the two library dependencies to game.project and fetch them, then check the input binding setting, because Druid uses the built-in all.input_binding file and a project that has not configured that will not deliver taps to your components.

## FAQ

### What is Druid in the Defold ecosystem?

Druid is a Lua UI component framework for the Defold engine. You place nodes in the Defold GUI editor and attach logic to them, with components for buttons, text, scroll views, lists, blockers and back handling, plus reusable widgets.

### How do I install Druid in a Defold project?

Add the Defold Event and Druid archive URLs to the dependencies field under the project section of your game.project file, then select Project and Fetch Libraries. The documentation also mentions installing it from the Asset Store extension to skip that step.

### How does a Druid widget differ from a component?

A component is logic attached to a GUI node you placed in the editor, such as a button or a scroll view. A widget is a reusable piece consisting of a .gui file and a .lua file together, created through the new_widget function.

### How does Druid decide which component receives a tap?

Input handling is stack based with priority, and the last component created is checked first. That is why the framework includes a Blocker component, which stops input from passing below its node area.

### How large is the Druid library?

The documentation reports a full size of 84.52 KB for HTML5 and 141.03 KB for desktop and mobile, measured from the build report per platform, and notes that unused components can be stripped out during the build.

### What input bindings does Druid require?

Druid uses the built-in all.input_binding file. You either set the Game Binding field in the input section of game.project to that file, or add the specific bindings you need to your own input binding file.

## Sources

- [Insality/druid on GitHub](https://github.com/Insality/druid)
- [License: MIT](https://github.com/Insality/druid/blob/master/LICENSE)
- [Project website](https://insality.github.io/druid/)
- [README](https://github.com/Insality/druid/blob/master/README.md)
- [Releases](https://github.com/Insality/druid/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/insality-druid
