Adding a new pipeline node to megane
SkillDev toolsRegister a new pipeline node type across every surface it must touch (types, catalog, executor, engine dispatch, React component, editor palette, and the optional JS/Python builders). Use whenever you add a node to the visual pipeline, or notice a node is only half-wired. Complements the `add-format` skill (formats vs. nodes) and the prose walkthrough at docs/docs/dev/custom-nodes.md.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Adding a new pipeline node to megane skill
What this skill tells your AI
The instructions your AI receives, as published by megane-labs/megane in .agents/skills/add-node/SKILL.md and read by ahel’s review.
A node type is not a single class — it is a set of coordinated declarations
spread across ~8 files. Miss one and the node either fails to compile, never
appears in the editor, or silently does nothing at runtime. This checklist is the
agent-facing companion to the full walkthrough in
docs/docs/dev/custom-nodes.md; read that page for copy-paste boilerplate and
rationale.
Nodes are a TypeScript-frontend concept only — the Rust core has no notion of
nodes. All of the work below is in src/pipeline/ and src/components/.
When to use this skill
- Adding a new node type to the visual pipeline.
- Reviewing a bug like "the new node compiles but never runs" or "it runs but isn't in the Add Node menu".
- Extending the JS/Python builder API to construct an existing node type.
Compile-time guardrail
Surfaces 1–5 and 7 below are declared as Record<PipelineNodeType, …>, so tsc
refuses to build until every table has an entry for the new type. Run
npm run build:app early and often — the type errors are your to-do list. This is
the project's substitute for a runtime node base class.
Registration checklist
Walk every item. The order roughly follows the data dependency.
1. Type + structural metadata — src/pipeline/types.ts
- Add the string literal to the
PipelineNodeTypeunion. - Add a
NODE_TYPE_LABELSentry (display name). - Add a
NODE_CATEGORYentry (data_load|bond|filter|modify|overlay|viewport). - Add a
NODE_PORTSentry — typedinputs/outputs({ name, dataType, label }). - Define a
XxxParamsinterface (with thetype: "xxx"discriminant), add it to thePipelineNodeParamsunion, and add acase "xxx":todefaultParams(). - Only if the node's input type is resolved from whatever is wired in (like
filter/modify): add aGENERIC_NODE_ACCEPTSentry. Otherwise skip it.
2. Documentation metadata — src/pipeline/catalog.ts
- Add a
NODE_CATALOGentry:description, per-paramparams: ParamDoc[],promptInputs/promptOutputs,inPrompt, andpythonClass(ornull). This feeds the AI system prompt and the autogenerated Node Reference — keep it runtime-dependency-free (types + pure data only).
3. Executor — src/pipeline/executors/<name>.ts
- Export
executeXxx(params, inputs: Map<string, PipelineData[]>) => Map<string, PipelineData>. Keep it a pure function: no Three.js, no DOM, no mutation of the inputs (spread new objects, copy typed arrays). Model it onexecutors/modify.ts/filter.ts.
4. Engine dispatch — src/pipeline/execute.ts
- Import the executor and add a
case "xxx":inside theswitch (data.params.type)inexecutePipeline(). SetedgeOutputs.set(id, outputs)and add a "no input" warning like the neighboring cases.
5. React component — src/components/nodes/<Name>Node.tsx
- Wrap the shared
NodeShell(it draws the header, toggle, delete, error badge, and typed handles fromNODE_PORTS). Render only the param body. Read/write params exclusively viausePipelineStore((s) => s.updateNodeParams)— never mutatedata.params. FollowFilterNode.tsx.
6. Editor registration — src/components/PipelineEditor.tsx
- Add the component to the
nodeTypesmap. - Add the node type to the correct
ADD_NODE_GROUPSgroup so it shows up in the "Add Node" menu.
7. JS builder (optional) — src/pipeline/builder.ts
- If the node should be constructable from the TypeScript
PipelineAPI, add aPipelineNodesubclass:nodeType,_outPorts/_inpPorts(alias → port name), and_toSerializedParams().
8. Python builder (optional) — python/megane/pipeline.py
- Mirror the JS subclass: a
PipelineNodesubclass with_node_type/_out_ports/_inp_portsand params stored onself, plus anisinstance(node, Xxx)branch inPipeline._serialize_node()that copies the params into the node dict. The serializedtypeand param keys must match the TS side exactly or the JSON won't round-trip.
9. Tests (required — Codecov patch ≥ 70 %, CRITICAL RULE #8)
- Executor unit test in
tests/ts/pipeline/executors/<name>.test.ts. -
defaultParams("xxx")shape test. - Component test in
tests/ts/components/nodes/<Name>Node.test.tsx(assertsupdateNodeParamsfires). - If you added builder/Python subclasses: a serialize → deserialize round-trip test.
- Reproduce the gate locally:
npm test -- --coverage.
10. E2E (required for the UI change — CRITICAL RULE #9, local-only)
-
npm run build:wasm && npm run build:app, then run at least--project=pipeline-editorand the relevant modifier/feature project; sweep the neighborhood for side effects. - Re-baseline only genuinely-intended pixel changes (
MEGANE_E2E_UPDATE=1), visually inspect the PNGs, and commit them undertests/e2e/baselines/<project>/. Full runbook:e2e-coverageskill.
11. Docs
- The Node Reference is autogenerated from
catalog.ts— no hand-editing. But if the node introduces a new concept, mention it indocs/docs/guide/pipeline/index.md.
Common omissions caught by this checklist
| Symptom | Missing step |
|---|---|
tsc error "property 'xxx' is missing" | §1 or §2 — a Record<PipelineNodeType, …> table has no entry |
| Node runs but isn't in the Add Node menu | §6 — ADD_NODE_GROUPS |
| Node is in the menu but renders blank / throws | §5 — component not in nodeTypes, or wrong nodeType prop |
| Node appears but does nothing at runtime | §4 — no case in executePipeline() |
Pipeline(...).to_json() omits the node's params | §8 — no isinstance branch in _serialize_node() |
| Loaded JSON drops params / "Unknown node type" | §1 port entry missing (drives VALID_NODE_TYPES) or §7/§8 key mismatch |
Source-of-truth pointers
- Structural metadata (types, ports, params, defaults):
src/pipeline/types.ts - Prose + param docs (AI prompt + Node Reference):
src/pipeline/catalog.ts - Execution:
src/pipeline/executors/,src/pipeline/execute.ts - UI:
src/components/nodes/,src/components/PipelineEditor.tsx - Programmatic builders:
src/pipeline/builder.ts,python/megane/pipeline.py - Prose walkthrough:
docs/docs/dev/custom-nodes.md
Signals
- GitHub stars
- 22
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-node- Source
- github.com/megane-labs/megane