Convention: * CLAUDE.md (root): new "Folder & File Layout (READ BEFORE CREATING NEW FILES)" section with required-name table and explicit legacy-drift list (mgc, vgc, dashboardapi). * .claude/rules/node-architecture.md: file-naming convention + src/editor/ module layout sections; serving recipe for /<nodeName>/editor/:file. Submodule bumps: * generalFunctions: shared output-format picker, redesigned position SVGs, tighter asset wizard, restored curve preview size. * rotatingMachine: pump banner, circular state diagram, mode icon cards, picker integration, CLAUDE.md update. * 10 others: per-node CLAUDE.md "Folder & File Layout" sections — 3 of them (machineGroupControl, valveGroupControl, dashboardAPI) carry inline warnings about their entry-filename drift. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.8 KiB
paths
| paths | |
|---|---|
|
Node Architecture Rules
3-Tier Structure
Every node follows entry → nodeClass → specificClass:
- Entry file (
nodes/<nodeName>/<nodeName>.js): Registers with Node-RED viaRED.nodes.registerType, exposes admin HTTP endpoints. - nodeClass (
nodes/<nodeName>/src/nodeClass.js): Handles Node-RED runtime concerns — message routing, output formatting, tick loops, status updates,RED.*API calls. - specificClass (
nodes/<nodeName>/src/specificClass.js): Pure domain logic — physics, control algorithms, state machines.
Separation Rules
- specificClass must never call
RED.*directly — all Node-RED interaction goes through nodeClass. - specificClass is the source of truth for domain behavior.
- nodeClass is the adapter between Node-RED and domain logic.
- Entry file is minimal — registration and admin endpoints only.
Output Port Convention
- Port 0: Process data (control outputs, state, setpoints)
- Port 1: InfluxDB telemetry payload
- Port 2: Registration/control plumbing (parent-child handshakes)
File-Naming Convention
The folder name is the canonical node name and every per-node file MUST match it exactly (case-sensitive). No abbreviations.
| Path | Required name |
|---|---|
| Folder | nodes/<nodeName>/ |
| Entry file | nodes/<nodeName>/<nodeName>.js |
| Editor HTML | nodes/<nodeName>/<nodeName>.html |
| nodeClass | nodes/<nodeName>/src/nodeClass.js |
| specificClass | nodes/<nodeName>/src/specificClass.js |
| Editor JS modules | nodes/<nodeName>/src/editor/*.js |
machineGroupControl/mgc.js, valveGroupControl/vgc.js, and
dashboardAPI/dashboardapi.js are legacy drift. New nodes MUST use the full
folder name; legacy nodes get renamed when next touched (rename = update entry
file, HTML file, package.json#node-red.nodes, and any test imports in one
commit).
Editor JS Layout — src/editor/
Editor-side JavaScript that exceeds a couple of dozen lines lives in modular
files under nodes/<nodeName>/src/editor/, served by the entry file via:
const path = require('path');
RED.httpAdmin.get(`/${nameOfNode}/editor/:file`, (req, res) => {
const safe = String(req.params.file || '').replace(/[^a-zA-Z0-9._-]/g, '');
if (!safe.endsWith('.js')) return res.status(400).send('// invalid');
res.type('application/javascript');
res.sendFile(path.join(__dirname, 'src', 'editor', safe), (err) => {
if (err && !res.headersSent) res.status(404).send('// editor module not found');
});
});
The HTML file then loads them as plain <script src="/<nodeName>/editor/<file>.js">
tags. Conventional modules:
| File | Purpose |
|---|---|
index.js |
Namespace setup (window.EVOLV.nodes.<nodeName>.editor = …), shared helpers |
oneditprepare.js |
Implementation called from the .html's oneditprepare hook |
oneditsave.js |
Implementation called from the .html's oneditsave hook |
| Feature modules | One per visual concern, e.g. basin-diagram.js, mode-cards.js, timing-donut.js, hover-couple.js |
The .html shrinks to: register defaults, declare HTML template, delegate
oneditprepare/oneditsave to the modules. Inline JS in the .html is fine
for trivial nodes (≤ ~50 lines of editor JS); past that, extract.
Reference implementations: pumpingStation/src/editor/ and
machineGroupControl/src/editor/. rotatingMachine is currently inline and
should be migrated when the editor JS next grows.
Admin Endpoints
GET /<nodeName>/menu.js— Dynamic menu configuration for editorGET /<nodeName>/configData.js— Runtime configuration for editorGET /<nodeName>/editor/:file— (when present) editor JS modules fromsrc/editor/
Submodule Awareness
Most nodes/* directories are git submodules. Keep edits scoped to the target node's directory.