Skip to content

Monitor App

The Monitor App is a built-in web interface for interacting with the workflow engine during development. It provides a real-time view of workflow definitions, executions, jobs, and registered workers.

Integration roadmap

The Monitor App runs on the Neops Web Client’s session and has no sign-in of its own. Set WEBCLIENT_ORIGIN on the container to the web client’s exact origin; with it unset the app reports that it has no session. The app calls the engine from the browser, so its own origin has to be listed in the engine’s NEOPS_CORS_ORIGINS. Its functionality will be integrated into the web client in a future release. For now, it is the primary UI for workflow management and execution monitoring.

Deployment

The container image serves the static build with nginx and reads three environment variables at start (rest/monitor-app/docker-entrypoint.d/40-runtime-config.sh). All three are rendered into /config.js, which the page loads before the app bundle, so no rebuild is needed to change them.

Variable Meaning
ENGINE_BASE_URL Browser-facing base URL of the engine, e.g. https://engine.example.com. Unset: the compile-time default.
WEBCLIENT_ORIGIN Exact origin of the Neops Web Client the app takes its session from. Unset: no session.
MONITOR_BASE_PATH Path prefix the app is published under, e.g. /workflows. Unset: the origin root.

Session modes

How the app obtains an access token depends on where it is served relative to WEBCLIENT_ORIGIN. The two are compared as origins, and the mode is chosen once per page load (rest/monitor-app/src/lib/auth/token-provider.ts).

  • Another origin (host relay). The app is opened from the web client, in an iframe or a popup, and asks the host window for a token over postMessage. The host answers with the bare JWT and its expiry, the app asks again ahead of expiry and on a 401, and a logout in the web client is relayed as a message. Opened directly, with no host window, the app has no session.
  • The web client’s own origin (shared session). Served from the same origin, for instance under https://neops.example.com/workflows, the app reads the web SDK’s access token straight from the shared localStorage key token and follows the storage event for that key, so a refresh or a logout in any web client tab reaches it. The refresh token is never read, and the key is never written: the SDK’s cross-tab logout listens on it. Without a token the app asks the user to sign in to the web client and picks the session up as soon as that happens.

Base path

SvelteKit fixes its base path at build time, and the image is built once. MONITOR_BASE_PATH therefore works on the served HTML instead: the reverse proxy in front strips the prefix, nginx keeps serving from /, and at container start the entrypoint rewrites every .html file of the build so the browser requests <prefix>/_app/..., <prefix>/config.js and <prefix>/favicon.svg and the SvelteKit runtime base carries the prefix. The rewrite always starts from pristine copies taken at image build (/html.template/), so a restart with a different value cannot stack prefixes, and the value is validated as one or more /segment parts from [A-Za-z0-9._~-] with no trailing slash and no . or .. segment.

The rewrite is tied to SvelteKit’s HTML output

The entrypoint uses sed with a fixed set of patterns: href="/_app/, import("/_app/, href="/favicon.svg", src="/config.js" and a line that is exactly base: "" inside the inline __sveltekit_<hash> script. The client bundle reads base from that global at runtime, which is what makes the rewrite reach $app/paths and the router. Nothing in CI checks this, so after a SvelteKit or adapter upgrade compare a built build/index.html with those patterns and run the image with MONITOR_BASE_PATH=/workflows before releasing.

What You Can Do

  • Browse workflow definitions – See all registered workflows with their versions, steps, and schemas
  • Trigger executions – Execute workflows with custom parameters and entity scopes
  • Monitor executions – Watch execution state transitions in real time (NEW → RUNNING → COMPLETED)
  • Inspect jobs – See which jobs are pending, polled, or completed, and which worker handled each job
  • View workers – See online workers and their registered function blocks

Quick Start

Follow the Quick Start to start PostgreSQL, the Monitor App, and the engine. Then open http://localhost:5173 in your browser.

  1. Ensure the workflow engine is running (see Setup)
  2. Start the Monitor App:

    make run-monitor
    

    Or directly:

    cd rest/monitor-app && npm run dev
    
  3. Open http://localhost:5173 in your browser

Key Screens

Workflow Definitions

Lists all registered workflow definitions. From here you can:

  • View the full YAML definition of each workflow
  • See the version history
  • Deploy new workflow definitions
  • Trigger an execution directly

Executions

The execution view shows all workflow executions with their current state. Click an execution to see:

  • The current state in the lifecycle (with color coding)
  • Individual jobs and their status per device
  • Step-by-step progress
  • Error details for failed steps
  • DB updates that will be applied

Workers

Shows all registered workers with their status (online, unreachable, offline) and which function blocks each worker provides. Useful for debugging when jobs are not being picked up.

Importing Workflows

The Monitor App accepts workflow definitions in JSON format. Since we recommend authoring workflows in YAML for readability, convert before importing:

yq -o=json my-workflow.workflow.yaml > my-workflow.workflow.json

Paste the raw workflow JSON into the Monitor App’s definition editor — the app handles the API wrapping automatically.

Quick conversion alternatives

  • yq (recommended): yq -o=json < workflow.yaml – install via brew install yq or see github.com/mikefarah/yq
  • Online: json2yaml.com converts both directions
  • Python: python -c "import yaml, json, sys; json.dump(yaml.safe_load(sys.stdin), sys.stdout, indent=2)" < workflow.yaml
Technology

The Monitor App is built with Svelte and communicates with the engine via browser-side HTTP requests to the REST API (defaulting to http://localhost:3030, configurable in the app’s Settings page). When started via Docker Compose, it runs as a static production build served by nginx. For local development (make run-monitor), it runs as a Vite dev server with hot-reload.


Next: Your First Workflow – deploy and execute a workflow end to end.