glendix is the JavaScript-target build and rendering bridge for Mendix
Pluggable Widgets written in Gleam.
Its package boundary is explicit:
- glendix owns Pluggable Widgets Tools orchestration, widget definition editing, external npm React bindings, and the Lustre-to-React bridge;
- mendraw owns Mendix client values and bindings generated from installed
.mpkassets; - mxpak owns Marketplace search, package download, cache, lockfiles, and workspace deduplication;
- glendam owns generic browser automation.
Glendix does not implement Marketplace access or browser automation.
[dependencies]
glendix = ">= 5.1.0 and < 6.0.0"Add mendraw only when the project uses Mendix client values or installed MPK
components, and add/use mxpak only when package acquisition is required.
A widget project's package.json normally includes the Mendix Pluggable Widgets
Tools and their React peer dependencies.
Glendix can isolate Mendix Pluggable Widgets Tools from the project's package manager and JavaScript runtime:
[javascript]
runtime = "bun"
[tools.glendix]
pm = "bun"
compatibility = "experimental-native"pm |
Gleam runtime | Dependency install |
|---|---|---|
npm |
node |
npm install |
yarn |
node |
yarn install |
pnpm |
node |
pnpm install |
bun |
bun |
bun install |
deno |
deno |
hoisted manual deno install with the required lifecycle scripts allowed |
In this mode, Glendix invokes the installed Pluggable Widgets Tools CLI with the
selected runtime and places temporary node, npm, and npx compatibility
shims only on that child process's PATH. The shims satisfy the tool's hard
Node/npm checks and route supported install, run, and exec calls back to the
selected package manager. They are removed after the command; no global binary,
lockfile, or package-manager setting is replaced. Interactive npm lockfile
migration is disabled, so the selected manager's lockfile remains authoritative.
This is an explicit experimental compatibility mode, not a complete npm
emulator. npm and Bun projects must allow or trust the lifecycle scripts
required by the Mendix toolchain, Yarn projects must use the node-modules
linker, and pnpm projects must allow the same native build scripts. Deno
projects must grant their Gleam commands the required permissions and allow
those scripts during install. Invoke dependency modules with an explicit
matching runtime, for example
gleam run -m glendix/build --runtime bun or --runtime deno; use
--runtime node for npm, Yarn, and pnpm.
import mendraw/mendix
import redraw
import redraw/dom/attribute
import redraw/dom/html
pub fn widget(props: mendix.JsProps) -> redraw.Element {
let title = mendix.get_string_prop(props, "title")
html.section([attribute.class("widget")], [html.text(title)])
}This example composes Glendix with Mendraw in the application. Glendix itself remains independently usable for external React bindings and Lustre rendering.
import glendix/lustre as glendix_lustre
import gleam/int
import lustre/effect
import lustre/element
import lustre/element/html
import lustre/event
import redraw
type Model { Model(count: Int) }
type Message { Increment }
fn update(model: Model, message: Message) -> #(Model, effect.Effect(Message)) {
case message {
Increment -> #(Model(model.count + 1), effect.none())
}
}
fn view(model: Model) -> element.Element(Message) {
html.button([event.on_click(Increment)], [
html.text("Count: " <> int.to_string(model.count)),
])
}
pub fn component() -> redraw.Element {
glendix_lustre.use_tea(#(Model(0), effect.none()), update, view)
}Configure exports in gleam.toml:
[tools.glendix.bindings]
recharts = ["PieChart", "Pie"]Install the npm package, then run gleam run -m glendix/install. Glendix owns
both component lookup and element construction; Mendraw is not required:
import gleam/result
import glendix/binding
import redraw
import redraw/dom/attribute
pub fn pie_chart(
attributes attributes: List(attribute.Attribute),
children children: List(redraw.Element),
) -> Result(redraw.Element, binding.BindingError) {
use module <- result.try(binding.module("recharts"))
use component <- result.try(binding.resolve(module, "PieChart"))
Ok(binding.element(component, attributes, children))
}binding.element_ creates an element with children only, and
binding.void_element creates one without children.
Package acquisition is a separate step owned by mxpak:
[tools.mxpak]
mode = "extract"
[tools.mxpak.widgets.Charts]
version = "3.0.0"mxp install
gleam run -m mendraw/install
gleam run -m glendix/install
gleam run -m glendix/buildmxp installwrites package assets tobuild/widgets/.mendraw/installgenerates typed MPK bindings.glendix/installinstalls JavaScript dependencies and generates Glendix npm bindings.glendix/buildcreates the production.mpk.
Projects that do not use Marketplace widgets omit the first two steps.
| Command | Responsibility |
|---|---|
gleam run -m glendix/install |
Install JS dependencies and generate Glendix npm bindings |
gleam run -m glendix/define |
Edit widget property definitions |
gleam run -m glendix/dev |
Run the development build/server |
gleam run -m glendix/build |
Build a production .mpk |
gleam run -m glendix/start |
Connect to the configured Mendix test project |
gleam run -m glendix/lint |
Run lint checks |
gleam run -m glendix/lint_fix |
Apply lint fixes |
gleam run -m glendix/release |
Run the release build |
gleam deps download
gleam format --check
gleam check
gleam build --warnings-as-errors
gleam docs build
gleam test --runtime bun