Node-RED is a monorepo with the following structure:
node-red/
├── packages/node_modules/@node-red/ # Core packages
│ ├── editor-client/ # Frontend UI (browser-side)
│ ├── editor-api/ # REST API for editor
│ ├── runtime/ # Flow execution engine
│ ├── registry/ # Node registry management
│ ├── nodes/ # Core nodes (inject, debug, etc.)
│ └── util/ # Shared utilities
├── Gruntfile.js # Build configuration
└── package.json # Main project config
Location: packages/node_modules/@node-red/editor-client/src/
JavaScript Structure (src/js/):
red.js- Main editor initializationmain.js- Application entry pointui/- UI componentsview.js- Main canvas/workspace viewpalette.js- Node palette (left sidebar)sidebar.js- Right sidebar containerworkspaces.js- Flow tabs managementdeploy.js- Deploy button functionalityeditor.js- Node editor dialogcommon/- Reusable UI widgets (tabs, menus, popover, etc.)
Styling (src/sass/):
style.scss- Main stylesheet entryflow.scss- Workspace/canvas stylespalette.scss- Node palette stylessidebar.scss- Sidebar stylesheader.scss- Header/toolbar stylescolors.scss- Color definitionsvariables.scss- SASS variables
HTML Template:
src/index.html- Main HTML template
Main Editor Components:
- Header - Top bar with deploy button, user menu
- Palette - Left sidebar with available nodes
- Workspace - Central canvas for flow editing
- Sidebar - Right panel with info/debug/config tabs
- Footer - Status bar at bottom
CSS Classes:
.red-ui-workspace- Main workspace container.red-ui-palette- Node palette.red-ui-sidebar- Right sidebar.red-ui-header- Top header.red-ui-view- Flow canvas view
Commands:
npm run build- Full build (runs Grunt)npm run dev- Development mode with watchgrunt build- Compiles SASS, concatenates JS
Build Process:
- SASS compilation:
src/sass/→public/red/style.css - JS concatenation:
src/js/→public/red/red.js - Assets copied to
public/
For UI changes, check these files:
- Visual styling:
packages/node_modules/@node-red/editor-client/src/sass/*.scss - Component logic:
packages/node_modules/@node-red/editor-client/src/js/ui/*.js - Main initialization:
packages/node_modules/@node-red/editor-client/src/js/red.js
File naming conventions:
tab-*.js- Sidebar tab implementationsui/common/*.js- Reusable UI widgetsui/editors/*.js- Property editor components
jQuery Usage:
- Node-RED uses jQuery extensively
- Most UI components are jQuery plugins
- DOM selections use
$()not vanilla JS
RED Namespace:
- Global
REDobject contains all editor functionality RED.view- Canvas/workspace methodsRED.palette- Palette managementRED.sidebar- Sidebar tabsRED.nodes- Node registry
Event System:
RED.events.on()/RED.events.emit()for communication- Common events: "workspace:change", "nodes:add", "deploy"
Typical workflow:
- Identify the UI component in
src/js/ui/ - Locate corresponding styles in
src/sass/ - Make changes to both JS and SCSS files
- Run
npm run buildto compile - Refresh browser (changes visible at http://localhost:1880)
After frontend changes:
- Always run
npm run build - No need to restart Node-RED server
- Just refresh the browser
After backend changes:
- Restart Node-RED server
- Use:
kill $(cat node-red.pid) && npm start & && echo $! > node-red.pid
# Find a UI element by class name
grep -r "className" packages/node_modules/@node-red/editor-client/src/
# Find SASS styles
grep -r "selector" packages/node_modules/@node-red/editor-client/src/sass/
# Find JavaScript component
grep -r "componentName" packages/node_modules/@node-red/editor-client/src/js/- Deploy Button:
src/js/ui/deploy.js,src/sass/header.scss - Node Palette:
src/js/ui/palette.js,src/sass/palette.scss - Sidebar Tabs:
src/js/ui/sidebar.js,src/sass/sidebar.scss - Workspace Canvas:
src/js/ui/view.js,src/sass/flow.scss - Node Editor Dialog:
src/js/ui/editor.js,src/sass/editor.scss
Node-RED was designed primarily for desktop use:
- Minimum expected width: 1024px
- Mobile layouts (< 768px) may have overlapping UI elements
- Sidebar can cover workspace on narrow screens
- Touch interactions have limited support
When testing at different resolutions, be aware:
- Sidebar may need to be hidden on mobile
- Palette may overlap workspace
- Some interactions require hover (not touch-friendly)