Skip to content

Getting started with Helix

Helix turns Spiral’s real-time optimisation into a complete workforce-management system, shaped to your operation through configuration and code extensions. This guide takes you from nothing to a running Helix with your own first domain file. For the architecture behind it, see the Helix technical overview.

  • podman (or docker) — Helix is delivered as a single container image.
  • Access to the Honeywick container registry and the @helix/client-sdk npm package (we provide credentials).
  • A Spiral licence (SPIRAL_LICENCE) — the optimiser will not start without it.
  • Node.js — to build your client extension.

Helix ships registry-only: one container image carries everything the runtime needs (the Spiral optimiser, the CRUD/dispatch backend, the web apps) plus the host-side launcher, helixctl.

Terminal window
podman login registry.gitlab.com
./helix/runtime/helixctl pull # latest core for your pinned SDK line

If you don’t yet have helixctl, fetch the bootstrap stub from the image:

Terminal window
podman run --rm --entrypoint cat \
registry.gitlab.com/honeywick-consulting/helix/helixcore:sdk-0.1 /app/helixctl-bootstrap \
> helix/runtime/helixctl && chmod +x helix/runtime/helixctl

Your client repo pins a floating SDK tag (e.g. sdk-0.1) in helix/runtime/VERSION — so helixctl pull always brings the latest core built for your SDK line, not a fixed version.

You customise Helix in your own client repo, against the published @helix/client-sdk and the image — the helixCore source is not needed. From the repo root (the directory that holds helix/):

Terminal window
./helix/runtime/helixctl <CLIENT> dev # e.g. ./helix/runtime/helixctl AA dev

This runs the container as a single node, mounts your helix/, runs vite build --watch on your extension, and prints a URL. The loop:

  1. Edit your domain file (<CLIENT>.domain.json), clientConfig.tsx, or a component.
  2. The bundle rebuilds in ~1 second.
  3. Refresh the browser.

To ship: npm run build:clientpublish-<CLIENT>.sh <version>helixctl deploy on the node → helixctl <CLIENT> run.

Most behaviour is data, not code — authored in your domain file. Reach for the code extension (clientConfig.tsx, backend hooks) only for what configuration can’t express.

The domain file (<CLIENT>.domain.json) is a stream of JSONC directives, read in order to build the reference data and rules for your operation:

DirectivePurpose
includePull in an environment variable or file. Domain and map files are referenced by bare filename, resolved relative to the client directory.
setGlobal settings — resolutions and the ignore lists (fields kept out of Spiral).
defineReference data — stopParams, resourceParams, projectParams, customerParams, contractParams. Each array entry is keyed by key into reference.define.<type>.
helixApplication-level Helix config (e.g. Contact-Centre search paths).

A minimal domain needs little more than a set block and one stop type:

// my.domain.json — a starting point
{"set":{ "atResolution":"5km", "hostClockResolution":"00:01:00" }},
{"define":{"stopParams":[
{ "key":"default",
"helix":{ "icon":"Car", "lineLetter":"J" } // how the stop appears in the apps
}
]}},
{"define":{"resourceParams":[ { "key":"default" } ]}}

Each stopParams entry’s helix block drives the UI for that stop type — icon, lineLetter, per-state colours, the add-stop menu, warning and option templates. Add more types with "clone":"default" to inherit and extend. The reference documents every field.

From here you grow the file — more stop, resource and customer types, then business rules and quality gates. The How-To guides cover the client extension and backend hooks in depth.