Skip to content

Repository files navigation

English | Korean | Japanese

glendix

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 .mpk assets;
  • 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.

Install

[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.

Experimental native package managers

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.

Basic widget

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.

Lustre bridge

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)
}

External npm React components

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.

Installed Marketplace widgets

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/build
  • mxp install writes package assets to build/widgets/.
  • mendraw/install generates typed MPK bindings.
  • glendix/install installs JavaScript dependencies and generates Glendix npm bindings.
  • glendix/build creates the production .mpk.

Projects that do not use Marketplace widgets omit the first two steps.

Commands

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

Development

gleam deps download
gleam format --check
gleam check
gleam build --warnings-as-errors
gleam docs build
gleam test --runtime bun

License

MIT License

Releases

Packages

Contributors

Languages