Getting Started
Prerequisites
You do not need a separate Node-RED install — pnpm dev downloads and runs a local Node-RED for you (the version is configurable via the Vite plugin).
Scaffold from Template
The fastest way to start is with the official scaffolding command:
pnpm create @bonsae/nrg my-node-red-nodes
cd my-node-red-nodes
pnpm installThen start the dev server:
pnpm devScaffolded projects expose pnpm dev and pnpm build, which run Vite's dev server and a production build (vite --mode development and vite build --mode production). Open the URL printed by Vite in the terminal and you'll see your custom node in the Node-RED palette.
Manual Setup
If you prefer to add NRG to an existing project:
1. Install dependencies
pnpm add -D @bonsae/nrg node-red@5 vue@^3.5 vite@^6 vitest@^4 typescript@^5.8 eslint@^9 prettier@^3.5npm install -D @bonsae/nrg node-red@5 vue@^3.5 vite@^6 vitest@^4 typescript@^5.8 eslint@^9 prettier@^3.5yarn add -D @bonsae/nrg node-red@5 vue@^3.5 vite@^6 vitest@^4 typescript@^5.8 eslint@^9 prettier@^3.5Why is vue a dev dependency?
@bonsae/nrg already ships Vue as a runtime dependency and serves the Vue browser build to the Node-RED editor automatically — your project does not bundle or deploy Vue itself. However, vue must also be installed in your project as a dev dependency for two reasons:
Editor autocompletion — NRG ships
.d.tsfiles describing its built-in form components (NodeRedInput,NodeRedTypedInput, etc.) so your editor can autocomplete and type-check their props inside.vuefiles. The Vue editor tooling (Volar) can only read those descriptions whenvueis installed in your project; without it, the components fall back toanyand you lose autocompletion.How pnpm installs packages — pnpm keeps packages isolated, so NRG's copy of Vue isn't available at your project root, which is where Volar looks for Vue's type declarations while you edit. Listing
vuein your owndevDependenciesputs those types where the editor can find them. (This is a dev-time type-visibility concern only — it doesn't change what ships at runtime.)
This is only needed during development. The vue package is not included in your published Node-RED node package.
2. Configure Vite
Create a vite.config.ts at the project root:
import { defineConfig } from "vite";
import { nrg } from "@bonsae/nrg/vite";
export default defineConfig({
plugins: [nrg()],
});3. Configure TypeScript
Create tsconfig.json files that extend the shared configs:
tsconfig.json (root)
{
"extends": "@bonsae/nrg/tsconfig/base.json",
"compilerOptions": {
"rootDir": "."
},
"include": ["vite.config.ts"]
}src/server/tsconfig.json
{
"extends": "@bonsae/nrg/tsconfig/lib/server.json",
"compilerOptions": {
"rootDir": ".."
},
"include": ["**/*.ts", "../shared/**/*.ts"]
}src/client/tsconfig.json (only needed if you add custom client files)
{
"extends": "@bonsae/nrg/tsconfig/lib/client.json",
"compilerOptions": {
"rootDir": ".."
},
"include": ["**/*.ts", "**/*.vue"]
}Put your node schemas in src/shared/schemas/ and import them with the @/schemas alias (already set up in NRG's tsconfig, build, and test configs). Server code imports the actual schema values; editor (client) code imports only their TypeScript types. Each src/*/tsconfig.json uses rootDir: ".." to point at src/, so the client can still see the shared src/shared schema types its forms reference.
TIP
The src/client/ directory and its tsconfig.json are optional. NRG auto-generates the client-side code from your schemas. You only need these if you want to customize the editor behavior or provide custom Vue form components. See Custom Vue Forms for details.
4. Create the entry file
Create the server entry point. See the Project Structure page for the full layout, and Creating a Node for a complete walkthrough.
src/server/index.ts
import { defineModule } from "@bonsae/nrg/server";
import MyNode from "./nodes/my-node";
export default defineModule({
nodes: [MyNode],
});defineModule bundles your node classes into a single typed object that NRG reads to register each node with Node-RED.
This entry imports ./nodes/my-node, which imports its schema from src/shared/schemas/ — so create at least one schema + node before you build, or the unresolved import fails. Follow Creating a Node for that minimal schema + class, then continue below.
5. Configure ESLint and Prettier
nrg is a complete, drop-in flat config — the recommended JS/TS/Vue rules, NRG's plane boundaries, and a Prettier reset, all included. Your entire eslint.config.js is one line of config:
import { nrg } from "@bonsae/nrg/eslint";
export default nrg;Need to change a default? It's an array, and later flat-config blocks win, so append your own:
import { nrg } from "@bonsae/nrg/eslint";
export default [
...nrg,
{ rules: { "@typescript-eslint/no-explicit-any": "error" } },
];Then add a lint script (see package.json scripts below). One thing nrg checks: your editor (client) code must use import type when it pulls from server/ or schema files — a plain import would drag your node's server-side runtime into the browser bundle. The companion @bonsae/nrg/schema-server-imports-type-only rule (part of the nrg config, active as soon as you export default nrg) applies the same type-only requirement to schema files that reference your server/ folder.
For formatting, @bonsae/nrg/prettier ships the matching Prettier config. Re-export it from prettier.config.mjs so your formatting matches the framework's conventions:
// prettier.config.mjs
export { default } from "@bonsae/nrg/prettier";It's a plain options object, so you can spread it and override any option:
import nrg from "@bonsae/nrg/prettier";
export default { ...nrg, printWidth: 100 };6. Add package.json scripts
Wire up scripts like these (equivalent to what the scaffold provides) so you can run the short commands:
{
"scripts": {
"dev": "vite dev",
"build": "vite build",
"lint": "eslint .",
"validate": "pnpm validate:tsc && pnpm validate:lint && pnpm validate:format",
"validate:tsc": "tsc -p src/server/tsconfig.json --noEmit && tsc -p src/client/tsconfig.json --noEmit",
"validate:lint": "eslint .",
"validate:format": "prettier --check ."
}
}7. Start developing
The entry above imports ./nodes/my-node, so create at least one node first — otherwise the build fails on the unresolved import. See Creating a Node for a complete walkthrough, then start the dev server:
pnpm devWith the scripts from step 6 in place, pnpm dev runs vite dev just like a scaffolded project — if you skip those scripts, run pnpm vite dev directly.
This launches a local Node-RED instance with your nodes pre-installed. Any change to server or client code triggers an automatic rebuild and a full Node-RED restart; refresh the browser to see it. There's no hot module replacement yet, but your flows are preserved across restarts.