11 KiB
Installation and running the demo
Everything needed to get the LINE-1 Digital Twin running on a laptop and present it, including the copilot and the offline fallback.
If you only want the run-of-show — what to click and what to say — that is demo-script.md and the slide deck. This file is setup and operation.
1. Requirements
| Node.js | 20 or newer. Built and tested on 24.4.1. |
| npm | Ships with Node. Tested on 11.13.0. |
| Disk | ~250 MB for node_modules, plus models if you use Ollama. |
| GPU | Not required. The 3D view is primitives and runs on integrated graphics. |
| Internet | Only for npm install and the cloud copilot. The demo itself runs fully offline. |
Optional, for the fast local copilot:
| Ollama | Any recent version. Needed only for the Local copilot mode. |
Check what you have:
node -v && npm -v
2. Install
From the repository root — not from server/ or web/. This is an npm
workspaces repo, and one install at the root covers both packages.
npm install
Expect ~240 packages and about 25 seconds. There should be no build step and no native compilation.
3. Configure the copilot (optional)
The demo works with no configuration at all. With nothing set, the copilot falls back to a deterministic rule engine that answers instantly, offline, and never fails. Skip this section entirely if you just want to see the twin.
Copy the template and edit it:
cp .env.example .env
The server resolves a provider at startup in this order:
- OpenRouter if
OPENROUTER_API_KEYis set - Ollama if it answers at
OLLAMA_HOST - Rule engine otherwise
# Cloud — best analysis, slowest and most variable to first token
OPENROUTER_API_KEY=sk-or-v1-...
OPENROUTER_MODEL=stealth/ox-alpha
# Local — fast, needs `ollama serve` running
OLLAMA_HOST=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3.5-4b-32k:latest
# Force the rule engine, for rehearsing the worst case
# COPILOT_PROVIDER=fallback
.env is gitignored. Keep the key out of commits and out of screen shares.
You do not have to edit this file to change models. Once running, the in-app settings page (AI ⚙ in the header) lists every model each provider offers and switches at runtime. See §7.
If you are using Ollama
ollama serve
ollama pull qwen3.5-4b-32k
One gotcha worth knowing: Ollama commonly sets OLLAMA_HOST=0.0.0.0 machine-wide.
That is a bind address, not a destination — you cannot connect to it. The server
normalizes it to 127.0.0.1 automatically, and the settings page shows both the
configured value and the address actually being dialled.
4. Run it
For the demo (recommended)
npm run dev
Starts the API on :8787 and the Vite dev server on :5173, prefixing each process's output. One Ctrl+C stops both.
Open http://localhost:5173.
You should see, within a couple of seconds:
- Header: Telemetry live with a green dot, and a source badge reading
simulated - Header: an AI ⚙ button naming the active provider
- OEE around 87–90% — not 100%
- All five stations green, Alarms: all clear
- Trend charts already populated with history
The line starts pre-warmed: 30 simulated minutes are run before the first frame is served, so the rolling OEE window is full, the anomaly baselines are learned, and the charts have history. You are never presenting a dashboard that just booted.
Single port, no dev server
For a plant-floor box, a clean rehearsal, or handing someone a link:
npm run serve
Builds the front end and serves everything from http://localhost:8787 — one
Node process, one port, no Vite. Use npm run build and npm start separately if
you prefer.
Once web/dist exists, the API process serves it too, so npm run dev will log
serving built front end. That is harmless — but :8787 then shows whatever was
last built, which can be stale. In development always use :5173, which is
served live by Vite.
Other scripts
| Command | What it does |
|---|---|
npm run dev |
API + dev server together (the normal way) |
npm run dev:server |
API only, on :8787 |
npm run dev:web |
Front end only, on :5173 (needs the API running) |
npm run build |
Build the front end to web/dist |
npm start |
Serve API, and web/dist if it has been built |
npm run serve |
build then start |
npm run simcheck |
Verify the simulation model (no browser needed) |
npm run apicheck |
Verify the server API (server must be running) |
5. Verify the install
Two suites. Neither needs a browser, and both are worth running once after install so you know the machine is good.
npm run simcheck
Runs the model headless and asserts what the demo actually claims: signals stay
inside their physical ranges, faults move OEE the right way in a controlled A/B
against an unfaulted line, a packer stoppage propagates upstream as blocking, a
dropped sensor goes stale rather than to zero, setpoint changes are lagged, runs
are reproducible from a seed, and the prediction arrives before the threshold is
crossed. Ends with ALL CHECKS PASSED.
npm run apicheck # in a second terminal, with the server running
Exercises the WebSocket stream, the control API, fault propagation into the
stream, and the copilot in every provider mode — checking answers are grounded in
real readings rather than generic prose. Ends with ALL API CHECKS PASSED.
6. Running the demo
The full run-of-show with timings and wording is in demo-script.md. This is the mechanical sequence.
Ten minutes before
npm run dev, open http://localhost:5173.- Confirm the header shows Telemetry live.
- Pick your copilot and measure it. Open AI ⚙, choose a provider, click Test. Under 4 s to first token is presentable live; 4–12 s means a noticeable pause; above that, keep it for follow-up questions only. Do this on the demo machine, on the demo network — cloud latency has measured anywhere between 2 s and 36 s on consecutive identical calls.
- Press Reset if anyone has been clicking. The line re-warms to ~87% OEE, all clear, in well under a second.
- Leave the clock at 1×. You speed it up during the demo, not before.
- Rehearse once with wifi off so you know what the fallback looks like.
The sequence
| Step | Action | What to watch |
|---|---|---|
| 1 | Orbit the 3D view. Click CNC-02. | Detail charts follow the selection. OEE ~87%. |
| 2 | What-if → drag Oven setpoint 305 → 330 °C | Zone 2 lags: 316 °C at 10 s, settles ~30 s. Burner duty spikes 68→85→74%. Drag back to 305. |
| 3 | What-if → Inject CNC-02 bearing degradation. Set clock 60×. | Bearing vibration begins climbing toward the dashed Warn 3.5 line. |
| 4 | Wait ~10 simulated minutes | A purple Trend card appears: reaches the 4.5 limit in ~40 min of run time, while vibration is still ~2.8. |
| 5 | Click Explain this on the bearing alarm, then the work order chip | The copilot traces vibration → tool wear → rejects → OEE. It is never told which fault you injected. |
| 6 | Clear the fault, click Tool change, clock to 20× | Reject rate falls, OEE recovers. |
| 7 | Copilot selector → Offline rules, ask "Why is OEE down?" | Same diagnosis in ~40 ms, no model, no network. |
Resetting between runs
Reset in the header clears injected faults, learned baselines and client-side history, then re-warms the line. Use it between back-to-back demos rather than restarting the server.
7. Switching models at runtime
AI ⚙ in the header opens the settings page. The dashboard keeps streaming behind it, so nothing is interrupted.
- Provider — Auto / Cloud / Local / Offline rules
- Model — every model each provider offers. OpenRouter's catalogue arrives live with context length and price per million; the Ollama list comes from your local library with parameter size and quantization. Filter, or type an id.
- Test — measures time to first token and grades it
- Generation — temperature, max output tokens, reasoning effort
- Ollama host — shows the configured value and the address actually dialled
Choices persist to .copilot-settings.json (gitignored), so a model picked while
preparing survives a restart. Reset to defaults discards that file and falls
back to .env. Settings never contain the API key.
Note on reasoning models: reasoning tokens count against the output budget on most
providers, so a reasoning model on a small budget can spend the lot thinking and
return nothing. Keep effort low and the budget generous. Ollama thinking
models are sent think: false for the same reason.
8. Troubleshooting
Disconnected in the header, charts empty.
The API died. Restart with npm run dev; the dashboard reconnects on its own with
backoff and the server comes back pre-warmed. No page reload needed.
Port already in use.
Set PORT in .env for the API. For the dev server, change server.port in
web/vite.config.js — and its proxy target if you moved the API.
Copilot returns nothing, or the panel shows a note about an empty answer. Expected behaviour, not a break: it fell back to the rule engine and still answered. Usually a reasoning model exhausting its token budget. Raise max output tokens or lower reasoning effort in the settings page, or switch to Local.
Copilot says Ollama is unreachable.
ollama serve is not running, or the host is wrong. The settings page shows the
address being dialled — check that first. 0.0.0.0 in your environment is normal
and handled.
OEE reads 100% and there are no alarms.
The pre-warm did not run. Check the startup log for pre-warmed 30 simulated minutes. If it is absent, PREWARM_SEC has been overridden in
server/ingest/simulatedSource.js.
Server exits immediately with a long message about MQTT or OPC-UA.
TELEMETRY_SOURCE is set to a stub adapter. Set TELEMETRY_SOURCE=simulated in
.env. The adapters are documented stubs — see architecture.md.
3D view is choppy. Drop the clock to 20×. The model is fine; the render loop is competing with the projector. The scene loads no external assets, so this is never a network issue.
The line is in a strange state. Press Reset.
9. What is where
server/
sim/ line.js (part flow, WIP, blocking) · stations.js (physics)
faults.js (injectable profiles) · kpi.js (OEE)
analytics/ trend.js (least squares) · anomaly.js (frozen baselines)
alarms.js (thresholds, latching, predictions)
ingest/ source.js (the seam) · simulatedSource.js
mqttSource.js, opcuaSource.js (documented stubs)
ai/ copilot.js · context.js · rules.js · settings.js
web/src/
three/ Scene.jsx, Station.jsx, Conveyor.jsx
panels/ KPIs, station strip, charts, alarms, what-if, copilot, settings
scripts/ dev.mjs · simcheck.mjs · apicheck.mjs
docs/ demo-script.md · architecture.md · installation.md · the deck
Connecting real plant data is architecture.md — the ingest seam, both adapter stubs, and the four things that bite when the data is real.