Getting Started
Prerequisites
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 dev and vite build. 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 vue vite vitestnpm install -D @bonsae/nrg node-red vue vite vitestyarn add -D @bonsae/nrg node-red vue vite vitestWhy 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.tstype declarations for its built-in form components (NodeRedInput,NodeRedTypedInput, etc.). These declarations referenceimport("vue").DefineComponentto provide prop autocompletion and type-checking in your.vuetemplates. The Vue Language Server (Volar) needsvueinstalled in your project'snode_modulesto resolve these types. Without it, all component types resolve toanyand you lose autocompletion.pnpm strict isolation — pnpm does not hoist transitive dependencies to the root
node_modules. Even though@bonsae/nrghasvuein its own dependencies, Volar cannot see it because it resolves types from your project root, not from inside@bonsae/nrg's isolated dependency tree. Addingvueas a dev dependency makes it directly visible.
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/core/server.json",
"compilerOptions": {
"rootDir": ".."
},
"include": ["**/*.ts"]
}src/client/tsconfig.json (only needed if you add custom client files)
{
"extends": "@bonsae/nrg/tsconfig/core/client.json",
"compilerOptions": {
"rootDir": ".."
},
"include": ["**/*.ts", "**/*.vue"]
}Shared schemas live in src/shared/schemas/. The rootDir: ".." roots each plane at src/, so these src/server and src/client tsconfigs type-check the src/shared siblings they import.
TIP
The src/client/ directory and its tsconfig.json are optional. NRG auto-generates the client-side code from your server schemas. You only need these if you want to customize the editor behavior or provide custom Vue form components. See Creating a Node 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 collects your node classes into a typed module manifest that NRG uses to register them with Node-RED.
5. Configure ESLint
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). Among other things, nrg surfaces the @bonsae/nrg/schema-server-imports-type-only boundary rule in-editor, which keeps client code from value-importing the server runtime.
6. Add package.json scripts
Wire up the same scripts 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 --build",
"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.