diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md
index ac08f9c15b..c819921780 100644
--- a/.claude/CLAUDE.md
+++ b/.claude/CLAUDE.md
@@ -180,12 +180,38 @@ Collection config: `nuxt/content.config.ts` (defines the `handbook` collection)
### Product docs
-**Source:** `flowfuse/flowfuse` repo, `docs/` directory — **do not edit in this repo**; cloned automatically at build time by `nuxt/modules/docs-source.ts`.
+`/docs` is assembled from two sources. Which one owns a page decides where to edit it,
+and one of the two is not editable here at all.
+
+| Source | Owns | Edit where |
+|---|---|---|
+| `flowfuse/flowfuse` repo, `docs/` | the product documentation, versioned with the code | that repo, **not here** |
+| `nuxt/content-guides/` | this repo's own guides: the Application Guide, the Node-RED guide, and the Node-RED library under `/docs/node-red/` and `/docs/flowfuse-nodes/` | **here**, in place |
+
+The 38 core-node pages under `/docs/node-red/core-nodes/**` are ordinary guide files in
+that second source, not generator output. Each ends with a
+`::node-red-help{category=... file=... node=... name=...}` directive; the component
+(`nuxt/components/content/NodeRedHelp.vue`) asks `nuxt/server/api/node-red-help.get.ts` for
+that node's built-in help, which fetches the Node-RED project's locale file, selects the
+matching ``
});
- eleventyConfig.addGlobalData("coreNodesArray", () => {
- // Read the JSON file with core nodes
- const coreNodes = JSON.parse(fs.readFileSync(path.join(__dirname, 'src', '_data', 'coreNodes.json'), 'utf-8'));
-
- // Transform coreNodes object into an array
- return Object.entries(coreNodes).map(([key, nodes]) => ({ key, nodes }));
- })
-
- eleventyConfig.addAsyncShortcode("coreNodeDoc", async function (category, node) {
- return await coreNodeDoc(category, node)
- });
-
eleventyConfig.addFilter("filterNodeCategory", function(nodes, category) {
if (category === "all") {
return nodes;
diff --git a/lib/core-node-docs.js b/lib/core-node-docs.js
deleted file mode 100644
index 1ad3ad08e6..0000000000
--- a/lib/core-node-docs.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const EleventyFetch = require("@11ty/eleventy-fetch");
-const xpath = require('xpath');
-const dom = require('@xmldom/xmldom').DOMParser;
-
-module.exports = async function (cat, node) {
- let page = "";
- try {
- const url = `https://raw.githubusercontent.com/node-red/node-red/master/packages/node_modules/%40node-red/nodes/locales/en-US/${cat}/${node.file}.html`
- let data = await EleventyFetch(url, { type: "text" });
-
- const doc = new dom({
- locator: {},
- errorHandler: {
- warning: function (w) { },
- error: function (e) { },
- fatalError: function (e) { console.error(e) }
- }
- // As there's a few nodes that have multiple docs in one file, we wrap it to make it
- // valid XML
- }).parseFromString("" + data.toString() + "", 'text/xml');
-
- return xpath.select(`/scripts/script[starts-with(@data-help-name, "${node.xpath}")]/*`, doc).join(" ")
- } catch (e) {
- console.error(e);
- return null;
- }
-};
diff --git a/nuxt/components/content/CtaImage.vue b/nuxt/components/content/CtaImage.vue
index 727b058b0a..38cd998443 100644
--- a/nuxt/components/content/CtaImage.vue
+++ b/nuxt/components/content/CtaImage.vue
@@ -8,6 +8,17 @@ const props = defineProps<{
src: string
alt: string
cta: 'sign-up' | 'demo' | 'contact' | 'pricing'
+ /**
+ * What the event's `reference` should say, for a page that is not a blog post.
+ *
+ * Blog posts leave this unset and get `Blog: ` from the injected title
+ * below. The Node-RED guides under /docs have no injected title and no post, and
+ * carried their own reference string in a hand-written `onclick="capture(...)"` while
+ * they were Eleventy pages - MDC strips `onclick`, so that tracking went silent the
+ * moment they became content files. This prop is how those pages keep the exact
+ * reference they were already reporting, rather than a new dimension.
+ */
+ reference?: string
}>()
const POSITION = 'inline-image'
@@ -33,7 +44,7 @@ const postTitle = inject | undefined>('blogPostTitle', undefined)
function onClick () {
capture(EVENT, {
- reference: `Blog: ${postTitle?.value || ''}`,
+ reference: props.reference || `Blog: ${postTitle?.value || ''}`,
position: POSITION,
cta_type: props.cta,
})
diff --git a/nuxt/components/content/NodeRedHelp.vue b/nuxt/components/content/NodeRedHelp.vue
new file mode 100644
index 0000000000..cfdfe97c82
--- /dev/null
+++ b/nuxt/components/content/NodeRedHelp.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
\ No newline at end of file
+
diff --git a/src/node-red/database/images/config-connection.png b/nuxt/content-guides/node-red/database/images/config-connection.png
similarity index 100%
rename from src/node-red/database/images/config-connection.png
rename to nuxt/content-guides/node-red/database/images/config-connection.png
diff --git a/src/node-red/database/images/config-database.png b/nuxt/content-guides/node-red/database/images/config-database.png
similarity index 100%
rename from src/node-red/database/images/config-database.png
rename to nuxt/content-guides/node-red/database/images/config-database.png
diff --git a/src/node-red/database/images/data_in_influx.webm b/nuxt/content-guides/node-red/database/images/data_in_influx.webm
similarity index 100%
rename from src/node-red/database/images/data_in_influx.webm
rename to nuxt/content-guides/node-red/database/images/data_in_influx.webm
diff --git a/src/node-red/database/images/dynamodb-data-structure-node-red-flowfuse.png b/nuxt/content-guides/node-red/database/images/dynamodb-data-structure-node-red-flowfuse.png
similarity index 100%
rename from src/node-red/database/images/dynamodb-data-structure-node-red-flowfuse.png
rename to nuxt/content-guides/node-red/database/images/dynamodb-data-structure-node-red-flowfuse.png
diff --git a/src/node-red/database/images/dynamodb-flowfuse-iam-node-red.png b/nuxt/content-guides/node-red/database/images/dynamodb-flowfuse-iam-node-red.png
similarity index 100%
rename from src/node-red/database/images/dynamodb-flowfuse-iam-node-red.png
rename to nuxt/content-guides/node-red/database/images/dynamodb-flowfuse-iam-node-red.png
diff --git a/src/node-red/database/images/flowfuse-dynamodb-aws-setup-node-red.png b/nuxt/content-guides/node-red/database/images/flowfuse-dynamodb-aws-setup-node-red.png
similarity index 100%
rename from src/node-red/database/images/flowfuse-dynamodb-aws-setup-node-red.png
rename to nuxt/content-guides/node-red/database/images/flowfuse-dynamodb-aws-setup-node-red.png
diff --git a/src/node-red/database/images/influxdb-node-red-cta-1.png b/nuxt/content-guides/node-red/database/images/influxdb-node-red-cta-1.png
similarity index 100%
rename from src/node-red/database/images/influxdb-node-red-cta-1.png
rename to nuxt/content-guides/node-red/database/images/influxdb-node-red-cta-1.png
diff --git a/src/node-red/database/images/mysql-node-config.png b/nuxt/content-guides/node-red/database/images/mysql-node-config.png
similarity index 100%
rename from src/node-red/database/images/mysql-node-config.png
rename to nuxt/content-guides/node-red/database/images/mysql-node-config.png
diff --git a/src/node-red/database/images/mysql-with-node-red.png b/nuxt/content-guides/node-red/database/images/mysql-with-node-red.png
similarity index 100%
rename from src/node-red/database/images/mysql-with-node-red.png
rename to nuxt/content-guides/node-red/database/images/mysql-with-node-red.png
diff --git a/src/node-red/database/images/node-red-dynamodb-flow-flowfuse.png b/nuxt/content-guides/node-red/database/images/node-red-dynamodb-flow-flowfuse.png
similarity index 100%
rename from src/node-red/database/images/node-red-dynamodb-flow-flowfuse.png
rename to nuxt/content-guides/node-red/database/images/node-red-dynamodb-flow-flowfuse.png
diff --git a/src/node-red/database/images/node-red-dynamodb-get-item-flowfuse.png b/nuxt/content-guides/node-red/database/images/node-red-dynamodb-get-item-flowfuse.png
similarity index 100%
rename from src/node-red/database/images/node-red-dynamodb-get-item-flowfuse.png
rename to nuxt/content-guides/node-red/database/images/node-red-dynamodb-get-item-flowfuse.png
diff --git a/src/node-red/database/images/node-red-dynamodb-query-flowfuse.png b/nuxt/content-guides/node-red/database/images/node-red-dynamodb-query-flowfuse.png
similarity index 100%
rename from src/node-red/database/images/node-red-dynamodb-query-flowfuse.png
rename to nuxt/content-guides/node-red/database/images/node-red-dynamodb-query-flowfuse.png
diff --git a/src/node-red/database/images/node-red-dynamodb-scan-flowfuse.png b/nuxt/content-guides/node-red/database/images/node-red-dynamodb-scan-flowfuse.png
similarity index 100%
rename from src/node-red/database/images/node-red-dynamodb-scan-flowfuse.png
rename to nuxt/content-guides/node-red/database/images/node-red-dynamodb-scan-flowfuse.png
diff --git a/src/node-red/database/images/node-red-dynamodb.png b/nuxt/content-guides/node-red/database/images/node-red-dynamodb.png
similarity index 100%
rename from src/node-red/database/images/node-red-dynamodb.png
rename to nuxt/content-guides/node-red/database/images/node-red-dynamodb.png
diff --git a/src/node-red/database/images/node-red-influxdb.png b/nuxt/content-guides/node-red/database/images/node-red-influxdb.png
similarity index 100%
rename from src/node-red/database/images/node-red-influxdb.png
rename to nuxt/content-guides/node-red/database/images/node-red-influxdb.png
diff --git a/src/node-red/database/images/postgresql_with_node-red.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_Inventory_management_system.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_Inventory_management_system.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_Inventory_management_system.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_Inventory_management_system.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_delete_data.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_delete_data.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_delete_data.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_delete_data.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_drop_tables.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_drop_tables.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_drop_tables.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_drop_tables.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_form1.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form1.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_form1.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form1.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_form2.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form2.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_form2.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form2.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_form3.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form3.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_form3.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_form3.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_insert_data.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_insert_data.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_insert_data.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_insert_data.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_pgconfig1.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_pgconfig1.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_pgconfig1.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_pgconfig1.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_pgconfig2.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_pgconfig2.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_pgconfig2.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_pgconfig2.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_retrive_data.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_retrive_data.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_retrive_data.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_retrive_data.png
diff --git a/src/node-red/database/images/postgresql_with_node-red_update_data.png b/nuxt/content-guides/node-red/database/images/postgresql_with_node-red_update_data.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_node-red_update_data.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_node-red_update_data.png
diff --git a/src/node-red/database/images/postgresql_with_nodered_create_table.png b/nuxt/content-guides/node-red/database/images/postgresql_with_nodered_create_table.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_nodered_create_table.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_nodered_create_table.png
diff --git a/src/node-red/database/images/postgresql_with_nodred_environment_variable.png b/nuxt/content-guides/node-red/database/images/postgresql_with_nodred_environment_variable.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_nodred_environment_variable.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_nodred_environment_variable.png
diff --git a/src/node-red/database/images/postgresql_with_nodred_environment_variable_ff_editor.png b/nuxt/content-guides/node-red/database/images/postgresql_with_nodred_environment_variable_ff_editor.png
similarity index 100%
rename from src/node-red/database/images/postgresql_with_nodred_environment_variable_ff_editor.png
rename to nuxt/content-guides/node-red/database/images/postgresql_with_nodred_environment_variable_ff_editor.png
diff --git a/src/node-red/database/images/timescaledb-with-node-red-hypertables.png b/nuxt/content-guides/node-red/database/images/timescaledb-with-node-red-hypertables.png
similarity index 100%
rename from src/node-red/database/images/timescaledb-with-node-red-hypertables.png
rename to nuxt/content-guides/node-red/database/images/timescaledb-with-node-red-hypertables.png
diff --git a/src/node-red/database/images/timescaledb-with-node-red.png b/nuxt/content-guides/node-red/database/images/timescaledb-with-node-red.png
similarity index 100%
rename from src/node-red/database/images/timescaledb-with-node-red.png
rename to nuxt/content-guides/node-red/database/images/timescaledb-with-node-red.png
diff --git a/src/node-red/database/images/using-Mongo-with-nr.png b/nuxt/content-guides/node-red/database/images/using-Mongo-with-nr.png
similarity index 100%
rename from src/node-red/database/images/using-Mongo-with-nr.png
rename to nuxt/content-guides/node-red/database/images/using-Mongo-with-nr.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-annotomy-of-mongodb-document.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-annotomy-of-mongodb-document.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-annotomy-of-mongodb-document.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-annotomy-of-mongodb-document.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-change-node-to-delete-data.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-delete-data.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-change-node-to-delete-data.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-delete-data.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-change-node-to-insert-data.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-insert-data.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-change-node-to-insert-data.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-insert-data.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-change-node-to-update-data.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-update-data.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-change-node-to-update-data.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-change-node-to-update-data.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-dashboard-view.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-dashboard-view.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-dashboard-view.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-dashboard-view.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-crm-system-node-red-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-delete-data-form.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-delete-data-form.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-delete-data-form.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-delete-data-form.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-flowfuse-instance-setting.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-flowfuse-instance-setting.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-flowfuse-instance-setting.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-flowfuse-instance-setting.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-friend-id-node.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-friend-id-node.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-friend-id-node.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-friend-id-node.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-insert-data-form.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-insert-data-form.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-insert-data-form.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-insert-data-form.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-node-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-node-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-node-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-deleteone-node-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-node-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-node-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-node-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-drop-node-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-find-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-find-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-find-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-find-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-find-node-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-find-node-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-find-node-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-find-node-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-node-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-node-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-node-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-insertone-node-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-node-connection-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-node-connection-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-node-connection-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-node-connection-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-update-node-configuration.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-update-node-configuration.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-update-node-configuration.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-update-node-configuration.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-mongodb-updateone-flow.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-updateone-flow.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-mongodb-updateone-flow.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-mongodb-updateone-flow.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-table-widget.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-table-widget.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-table-widget.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-table-widget.png
diff --git a/src/node-red/database/images/using-mongodb-with-node-red-update-data-form.png b/nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-update-data-form.png
similarity index 100%
rename from src/node-red/database/images/using-mongodb-with-node-red-update-data-form.png
rename to nuxt/content-guides/node-red/database/images/using-mongodb-with-node-red-update-data-form.png
diff --git a/src/node-red/database/images/using-timescaledb-with-node-red-environment-variables.png b/nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-environment-variables.png
similarity index 100%
rename from src/node-red/database/images/using-timescaledb-with-node-red-environment-variables.png
rename to nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-environment-variables.png
diff --git a/src/node-red/database/images/using-timescaledb-with-node-red-inject-node-1.png b/nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-inject-node-1.png
similarity index 100%
rename from src/node-red/database/images/using-timescaledb-with-node-red-inject-node-1.png
rename to nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-inject-node-1.png
diff --git a/src/node-red/database/images/using-timescaledb-with-node-red-inject-node-2.png b/nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-inject-node-2.png
similarity index 100%
rename from src/node-red/database/images/using-timescaledb-with-node-red-inject-node-2.png
rename to nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-inject-node-2.png
diff --git a/src/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-connection-tab.png b/nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-connection-tab.png
similarity index 100%
rename from src/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-connection-tab.png
rename to nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-connection-tab.png
diff --git a/src/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-security-tab.png b/nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-security-tab.png
similarity index 100%
rename from src/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-security-tab.png
rename to nuxt/content-guides/node-red/database/images/using-timescaledb-with-node-red-postgresql-config-node-security-tab.png
diff --git a/src/node-red/database/influxdb.md b/nuxt/content-guides/node-red/database/influxdb.md
similarity index 89%
rename from src/node-red/database/influxdb.md
rename to nuxt/content-guides/node-red/database/influxdb.md
index cb4fe02795..baa2521730 100644
--- a/src/node-red/database/influxdb.md
+++ b/nuxt/content-guides/node-red/database/influxdb.md
@@ -1,25 +1,22 @@
---
-eleventyNavigation:
- key: InfluxDB
- parent: Database
+title: Using InfluxDB with Node-RED (2026 Updated)
+metaTitle: "Using InfluxDB with Node-RED (2026 Updated)"
+navTitle: InfluxDB
+navOrder: 50
meta:
- title: Using InfluxDB with Node-RED (2026 Updated)
description: Node-RED has great support for InfluxDB. In this guide, we'll explain how to get your data flowing into one of the most popular time-series databases.
keywords: node-red, databases, integration, influxdb, time-series database
-image: /node-red/core-nodes/images/node-red-influxdb.png
+image: /docs/node-red/core-nodes/images/node-red-influxdb.png
---
-# {{ meta.title }}
+# Using InfluxDB with Node-RED (2026 Updated)
InfluxDB is a time series database that is commonly used for storing and analysing IoT data. Node-RED is a visual programming tool that makes it easy to connect different data sources and create flows that automate tasks.
In this documentation, we will show you how to write data to InfluxDB from a Node-RED flow. We will also provide you with a few tips for writing data to InfluxDB effectively.
-
-
-
+::cta-image{src="/docs/node-red/database/images/influxdb-node-red-cta-1.png" alt="Write to InfluxDB from every Node-RED instance you run, all from one place" cta="sign-up" reference="Node-RED: Using InfluxDB with Node-RED"}
+::
## Step 1: Install the InfluxDB Node-RED package
@@ -53,9 +50,11 @@ The fields are the individual pieces of data that you are writing. The tags are
You can import the flow below into Node-RED to see an example of a payload which will write all the required values to create a data point in InfluxDB:
-{% renderFlow %}
+::render-flow
+```json
[{"id":"cb3b0ecc762dbf93","type":"inject","z":"4542482476b9c71d","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"time\":1688718546,\"temperature\":24},{\"device\":\"dQBgXeWLRE\",\"deviceType\":\"Pi4\",\"deviceName\":\"demo-pi-rob\"}]","payloadType":"json","x":450,"y":420,"wires":[["87166c0dafdeea33"]]},{"id":"87166c0dafdeea33","type":"debug","z":"4542482476b9c71d","name":"debug 31","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":600,"y":420,"wires":[]}]
-{% endrenderFlow %}
+```
+::
In this example, the time & temperature fields are hard coded, you will need to overwrite the values stored in ```payload[0].time``` & ```payload[0].temperature``` with real data if you were to connect this flow to a real IOT thermometer.
@@ -83,9 +82,11 @@ This is an example valid payload:
```
You can import a demo, including the demo payload flow using the code below:
-{% renderFlow %}
+::render-flow
+```json
[{"id":"ecbb02face30cbcd","type":"influxdb out","z":"4542482476b9c71d","influxdb":"1c1a5edef41716e3","name":"InfluxDB","measurement":"temperature","precision":"","retentionPolicy":"","database":"database","precisionV18FluxV20":"s","retentionPolicyV18Flux":"","org":"organization","bucket":"my_data","x":360,"y":220,"wires":[]},{"id":"de83c2b49ba249fd","type":"inject","z":"4542482476b9c71d","name":"","props":[{"p":"measurement","v":"temperature","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"time\":1688987984,\"temperature\":24},{\"device\":\"dQBgXeWLRE\",\"deviceType\":\"Pi4\",\"deviceName\":\"demo-pi-rob\"}]","payloadType":"json","x":190,"y":160,"wires":[["aad6353f2f00333e","ecbb02face30cbcd"]]},{"id":"aad6353f2f00333e","type":"debug","z":"4542482476b9c71d","name":"debug 31","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":360,"y":160,"wires":[]},{"id":"1c1a5edef41716e3","type":"influxdb","hostname":"127.0.0.1","port":"8086","protocol":"http","database":"my_data","name":"","usetls":false,"tls":"","influxdbVersion":"2.0","url":"https://localhost","rejectUnauthorized":true}]
-{% endrenderFlow %}
+```
+::
Bear in mind that you will need to edit the server and database details in your influxdb node for this demo to work.
@@ -93,7 +94,7 @@ Bear in mind that you will need to edit the server and database details in your
You should now be ready to test your flow is writing data to InfluxDB correctly. There is no output in Node-RED to confirm you data was written, so you will need to check directly on InfluxDB.
-
+
Great, our data has arrived correctly and is ready to be used.
@@ -103,4 +104,4 @@ Great, our data has arrived correctly and is ready to be used.
1. Set the correct measurement name. The measurement name is the name of the table in InfluxDB where the data will be stored. It is important to choose a meaningful measurement name that will help you to easily identify the data later.
1. Set the correct tags and fields. Tags are used to identify the data points, while fields are used to store the actual data values. It is important to set the correct tags and fields for your data so that you can easily query and analyse it later.
1. Set the correct timestamp. The timestamp is the time at which the data point was recorded. It is important to set the correct timestamp so that you can track the evolution of your data over time.
-1. Use the correct precision. The precision is the number of decimal places that are stored for each data value. It is important to use the correct precision so that your data is easy to use.
\ No newline at end of file
+1. Use the correct precision. The precision is the number of decimal places that are stored for each data value. It is important to use the correct precision so that your data is easy to use.
diff --git a/src/node-red/database/mongodb.md b/nuxt/content-guides/node-red/database/mongodb.md
similarity index 98%
rename from src/node-red/database/mongodb.md
rename to nuxt/content-guides/node-red/database/mongodb.md
index 158fbf5c89..90321575d5 100644
--- a/src/node-red/database/mongodb.md
+++ b/nuxt/content-guides/node-red/database/mongodb.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: MongoDB
- parent: Database
+title: Using MongoDB With Node-RED (2026 Updated)
+metaTitle: "Using MongoDB With Node-RED (2026 Updated)"
+navTitle: MongoDB
+navOrder: 50
meta:
- title: Using MongoDB With Node-RED (2026 Updated)
description: Learn how to seamlessly integrate MongoDB, a NoSQL database, into your Node-RED applications with this step-by-step documentation.
keywords: node-red, databases, integration, mongodb, no-sql database
-image: /node-red/core-nodes/images/using-Mongo-with-nr.png
+image: /docs/node-red/core-nodes/images/using-Mongo-with-nr.png
---
-# {{ meta.title }}
+# Using MongoDB With Node-RED (2026 Updated)
This guide provides implementation procedures for integrating MongoDB with Node-RED. It covers configuration requirements, operational patterns, and a complete implementation example using a customer relationship management system.
@@ -290,4 +290,4 @@ Connect a debug node to the output of any MongoDB4 node to monitor operation res
3. Use inject nodes for retrieval and drop operations
4. Use the forms for create, update, and delete operations
-{data-zoomable}
\ No newline at end of file
+{data-zoomable}
diff --git a/src/node-red/database/mysql.md b/nuxt/content-guides/node-red/database/mysql.md
similarity index 95%
rename from src/node-red/database/mysql.md
rename to nuxt/content-guides/node-red/database/mysql.md
index 569ca8cda1..e37a985ba6 100644
--- a/src/node-red/database/mysql.md
+++ b/nuxt/content-guides/node-red/database/mysql.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: MySQL
- parent: Database
+title: Using MySQL with Node-RED (2026 Updated)
+metaTitle: "Using MySQL with Node-RED (2026 Updated)"
+navTitle: MySQL
+navOrder: 50
meta:
- title: Using MySQL with Node-RED (2026 Updated)
description: Learn how to seamlessly integrate MySQL with Node-RED for efficient data management and application development.
keywords: nodered mysql, node red mysql, node-red-node-mysql, mysql nodered, mysql node red
-image: /node-red/database/images/timescaledb-with-node-red.png
+image: /docs/node-red/database/images/timescaledb-with-node-red.png
---
-# {{ meta.title }}
+# Using MySQL with Node-RED (2026 Updated)
When discussing popular and widely used databases, MySQL inevitably stands out. This is especially evident within the Node-RED community, where the MySQL contrib node has the highest number of downloads among all database contrib nodes. However, popularity often brings its own set of challenges. We've prepared this comprehensive guide to help our Node-RED community members navigate these challenges. It covers all aspects of using MySQL with Node-RED, including an overview of what MySQL is, the differences between PostgreSQL and MySQL, when to choose one over the other, essential MySQL operations, and more.
@@ -31,7 +31,7 @@ When discussing popular and widely used databases, MySQL inevitably stands out.
## Choosing Between PostgreSQL and MySQL
-Deciding between [PostgreSQL](/node-red/database/postgresql/) and MySQL depends on your project's needs and what each database system does best. PostgreSQL is ideal for big projects requiring complex data handling, reliability, and often updated data. It works well in environments where keeping data consistent is crucial. PostgreSQL's advanced features, like materialized views and support for writing procedures in different languages beyond SQL make it great for managing sophisticated data needs.
+Deciding between [PostgreSQL](/docs/node-red/database/postgresql/) and MySQL depends on your project's needs and what each database system does best. PostgreSQL is ideal for big projects requiring complex data handling, reliability, and often updated data. It works well in environments where keeping data consistent is crucial. PostgreSQL's advanced features, like materialized views and support for writing procedures in different languages beyond SQL make it great for managing sophisticated data needs.
On the other hand, MySQL is excellent for projects that prioritize fast data reading and are easy to set up and use. It's commonly used for smaller projects, quick prototypes, or applications where quick deployment is critical. MySQL offers flexibility with different storage options, like InnoDB for transactions and MyISAM for handling lots of reads simultaneously, making it versatile depending on your workload.
@@ -185,9 +185,11 @@ DROP TABLE IF EXISTS weather_data;
Below is the complete flow covering all the operations discussed throughout this blog.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"01aeec8769243693","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":1660,"wires":[["e9ae7f0a3fdbfbc5"]]},{"id":"e9ae7f0a3fdbfbc5","type":"debug","z":"a9e5683585deb91e","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1160,"y":1660,"wires":[]},{"id":"faf229c38d675b2b","type":"inject","z":"a9e5683585deb91e","name":"Create the table","props":[],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","x":600,"y":1660,"wires":[["b407dbb1901749bf"]]},{"id":"b407dbb1901749bf","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"CREATE TABLE IF NOT EXISTS weather_data (\n id INT AUTO_INCREMENT PRIMARY KEY,\n location VARCHAR(100) NOT NULL,\n date DATETIME NOT NULL,\n tem DECIMAL(5, 2) NOT NULL\n);\n","output":"str","x":820,"y":1660,"wires":[["01aeec8769243693"]]},{"id":"cfc26503f0812a88","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":1760,"wires":[["236d40b1edb920d2"]]},{"id":"236d40b1edb920d2","type":"debug","z":"a9e5683585deb91e","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1160,"y":1760,"wires":[]},{"id":"25790e7a3aef22bf","type":"inject","z":"a9e5683585deb91e","name":"Insert the data into the table","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"$random() * 100","payloadType":"jsonata","x":560,"y":1760,"wires":[["7a798b3539da9547"]]},{"id":"7a798b3539da9547","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"INSERT INTO weather_data (location, date, tem)\nVALUES ('New York', CURTIME(), {{ payload }});","output":"str","x":820,"y":1760,"wires":[["cfc26503f0812a88"]]},{"id":"0bbb4d17defe3067","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":1860,"wires":[["ef2de8cb0673de47"]]},{"id":"ef2de8cb0673de47","type":"debug","z":"a9e5683585deb91e","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":1860,"wires":[]},{"id":"027c2c3801bf71a3","type":"inject","z":"a9e5683585deb91e","name":"Retrieve data from table","props":[],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","x":580,"y":1860,"wires":[["079031046156b6a0"]]},{"id":"079031046156b6a0","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"SELECT * FROM weather_data;\n","output":"str","x":820,"y":1860,"wires":[["0bbb4d17defe3067"]]},{"id":"eb38532de73213cf","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":2080,"wires":[["281838d687cea172"]]},{"id":"281838d687cea172","type":"debug","z":"a9e5683585deb91e","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":2080,"wires":[]},{"id":"d4dfbbac635e8a3f","type":"inject","z":"a9e5683585deb91e","name":"Drop the table if it exist","props":[],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","x":580,"y":2080,"wires":[["4442ad0bbc50a256"]]},{"id":"4442ad0bbc50a256","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"DROP TABLE IF EXISTS weather_data;\n","output":"str","x":820,"y":2080,"wires":[["eb38532de73213cf"]]},{"id":"668ed2021704c543","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":1940,"wires":[["666152e3362a25d5"]]},{"id":"666152e3362a25d5","type":"debug","z":"a9e5683585deb91e","name":"debug 5","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":1940,"wires":[]},{"id":"fbcbad8039d05e8e","type":"inject","z":"a9e5683585deb91e","name":"Delete data from the table","props":[],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","x":570,"y":1940,"wires":[["aa929706ed813892"]]},{"id":"aa929706ed813892","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"DELETE FROM weather_data\nWHERE tem > 15\nAND location = 'New York';","output":"str","x":820,"y":1940,"wires":[["668ed2021704c543"]]},{"id":"9c2befca464db660","type":"mysql","z":"a9e5683585deb91e","mydb":"bceed1e54606b872","name":"MySQL","x":980,"y":2020,"wires":[["d28cb3472c5fc357"]]},{"id":"d28cb3472c5fc357","type":"debug","z":"a9e5683585deb91e","name":"debug 6","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":2020,"wires":[]},{"id":"49297922b9784f8e","type":"inject","z":"a9e5683585deb91e","name":"Update data from the table","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"10","payloadType":"num","x":570,"y":2020,"wires":[["bbae98e54824b222"]]},{"id":"bbae98e54824b222","type":"template","z":"a9e5683585deb91e","name":"","field":"topic","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"UPDATE weather_data\nSET tem = {{payload}}\nWHERE id = 3","output":"str","x":820,"y":2020,"wires":[["9c2befca464db660"]]},{"id":"bceed1e54606b872","type":"MySQLdatabase","name":"Mysql config","host":"${HOST}","port":"${PORT}","db":"${DATABASE}","tz":"+5:30","charset":"UTF8"}]
-{% endrenderFlow %}
+```
+::
### Deploying the Flow
@@ -195,4 +197,4 @@ Below is the complete flow covering all the operations discussed throughout this
After deploying the flow, you can test each operation, such as creating, deleting, updating, and executing other queries, by clicking the inject button. For debugging purposes, add debug nodes to the flow.
-Additionally, if you want to explore the integration of other databases with Node-RED, you can refer to our [database section](/node-red/database/) in the Node-RED learning resources, where we cover databases such as PostgreSQL, MongoDB, InfluxDB, DynamoDB, and more.
\ No newline at end of file
+Additionally, if you want to explore the integration of other databases with Node-RED, you can refer to our [database section](/docs/node-red/database/) in the Node-RED learning resources, where we cover databases such as PostgreSQL, MongoDB, InfluxDB, DynamoDB, and more.
diff --git a/src/node-red/database/postgresql.md b/nuxt/content-guides/node-red/database/postgresql.md
similarity index 98%
rename from src/node-red/database/postgresql.md
rename to nuxt/content-guides/node-red/database/postgresql.md
index b618445b2e..4726ec6b6b 100644
--- a/src/node-red/database/postgresql.md
+++ b/nuxt/content-guides/node-red/database/postgresql.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: PostgreSQL
- parent: Database
+title: Using PostgreSQL with Node-RED (2026 Updated)
+metaTitle: "Using PostgreSQL with Node-RED (2026 Updated)"
+navTitle: PostgreSQL
+navOrder: 50
meta:
- title: Using PostgreSQL with Node-RED (2026 Updated)
description: Learn how to seamlessly integrate PostgreSQL with Node-RED for efficient data management and application development.
keywords: node-red, databases, integration, PostgreSQL, SQL database
-image: /node-red/core-nodes/images/postgresql_with_node-red.png
+image: /docs/node-red/core-nodes/images/postgresql_with_node-red.png
---
-# {{ meta.title }}
+# Using PostgreSQL with Node-RED (2026 Updated)
PostgreSQL is a highly reliable open-source relational database known for its extensive features. It supports diverse data types, robust SQL, and ACID compliance, allowing high-performance systems. Over the years, it has demonstrated reliability, security, and compatibility, which makes it a popular choice for businesses worldwide.
diff --git a/src/node-red/database/redis.md b/nuxt/content-guides/node-red/database/redis.md
similarity index 98%
rename from src/node-red/database/redis.md
rename to nuxt/content-guides/node-red/database/redis.md
index 3b27c16948..ef9a24b905 100644
--- a/src/node-red/database/redis.md
+++ b/nuxt/content-guides/node-red/database/redis.md
@@ -1,22 +1,22 @@
---
-eleventyNavigation:
- key: Redis
- parent: Database
+title: Using Redis with Node-RED (2026 Updated)
+metaTitle: "Using Redis with Node-RED (2026 Updated)"
+navTitle: Redis
+navOrder: 50
meta:
- title: Using Redis with Node-RED (2026 Updated)
description: Learn how to integrate Redis with Node-RED for fast data storage, pub/sub messaging, JSON handling, Lua scripting, and advanced Redis operations in Node-RED flows.
keywords: nodered redis, node red redis, node-red-node-redis, redis nodered, redis node red
-certified:
- - "@flowfuse-certified-nodes/redis"
---
-# {{ meta.title }}
+# Using Redis with Node-RED (2026 Updated)
Redis is a powerful in-memory data structure store that can be used as a database, cache, message broker, and streaming engine. When combined with Node-RED, Redis provides a fast and efficient way to store and retrieve data, manage session states, implement pub/sub messaging patterns, and share data across multiple Node-RED instances.
This documentation will walk you through integrating Redis with Node-RED, from basic setup to advanced use cases.
-{% include "components/certified-node-callout.liquid" %}
+::callout{icon="i-lucide-badge-check"}
+**Certified nodes for this technology.** FlowFuse maintains certified nodes for production use covering this technology. [redis](/integrations/?certified=1)
+::
## Getting Started
@@ -366,6 +366,8 @@ For more Redis commands, patterns, and advanced capabilities, refer to the [offi
Below is the complete example that we covered in this document.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"2c33ebeb73062ab3","type":"group","z":"d4f60c79eff5211d","name":"Your First Redis Flow","style":{"label":true},"nodes":["e5f3326ef736cef6","8486e88d8623b42a","d1ebde22d0e224a8","22db25c60af16ab2","fe2be532c53402b3","ebc1e8fc0f1ba2d6","adb95c63d206c633"],"x":514,"y":359,"w":712,"h":162},{"id":"e5f3326ef736cef6","type":"redis-command","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","server":"e370dc92b39a7ba4","command":"SET","name":"","topic":"mykey","params":"[\"Hello from Node-RED\"]","paramsType":"json","payloadType":"json","block":false,"x":810,"y":400,"wires":[["8486e88d8623b42a"]]},{"id":"8486e88d8623b42a","type":"debug","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":970,"y":400,"wires":[]},{"id":"d1ebde22d0e224a8","type":"redis-command","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","server":"e370dc92b39a7ba4","command":"GET","name":"","topic":"","params":"[]","paramsType":"json","payloadType":"json","block":false,"x":1000,"y":480,"wires":[["22db25c60af16ab2"]]},{"id":"22db25c60af16ab2","type":"debug","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1130,"y":480,"wires":[]},{"id":"fe2be532c53402b3","type":"change","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","name":"Set Key for GET","rules":[{"t":"set","p":"topic","pt":"msg","to":"mykey","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":480,"wires":[["d1ebde22d0e224a8"]]},{"id":"ebc1e8fc0f1ba2d6","type":"inject","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":400,"wires":[["e5f3326ef736cef6"]]},{"id":"adb95c63d206c633","type":"inject","z":"d4f60c79eff5211d","g":"2c33ebeb73062ab3","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":480,"wires":[["fe2be532c53402b3"]]},{"id":"e370dc92b39a7ba4","type":"redis-config","name":"Local","options":"{\"host\":\"localhost\",\"port\":6379,\"db\":0}","cluster":false,"optionsType":"json"},{"id":"5e2842a4730589c0","type":"group","z":"d4f60c79eff5211d","name":"Working with JSON Data","style":{"label":true},"nodes":["6acc07a393e5ee26","3255e8a9122253b7","a3b0b4a74133778e","4faba929a84fb358","e5c359b934174c8e","abf011c2e81960c4","22a2b54caae5869d","b9598f313e2a9fd2","d0051f637fd1621a","9e59f275496d722d"],"x":514,"y":539,"w":852,"h":162},{"id":"6acc07a393e5ee26","type":"redis-command","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","server":"e370dc92b39a7ba4","command":"SET","name":"","topic":"","params":"[]","paramsType":"json","payloadType":"json","block":false,"x":1140,"y":580,"wires":[["3255e8a9122253b7"]]},{"id":"3255e8a9122253b7","type":"debug","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1270,"y":580,"wires":[]},{"id":"a3b0b4a74133778e","type":"inject","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":580,"wires":[["d0051f637fd1621a"]]},{"id":"4faba929a84fb358","type":"redis-command","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","server":"e370dc92b39a7ba4","command":"GET","name":"","topic":"","params":"[]","paramsType":"json","payloadType":"json","block":false,"x":1000,"y":660,"wires":[["b9598f313e2a9fd2"]]},{"id":"e5c359b934174c8e","type":"debug","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1270,"y":660,"wires":[]},{"id":"abf011c2e81960c4","type":"change","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"Set Key for GET","rules":[{"t":"set","p":"topic","pt":"msg","to":"sensor:data","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":660,"wires":[["4faba929a84fb358"]]},{"id":"22a2b54caae5869d","type":"inject","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":660,"wires":[["abf011c2e81960c4"]]},{"id":"b9598f313e2a9fd2","type":"json","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"","property":"payload","action":"","pretty":false,"x":1130,"y":660,"wires":[["e5c359b934174c8e"]]},{"id":"d0051f637fd1621a","type":"change","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"Set Key","rules":[{"t":"set","p":"topic","pt":"msg","to":"sensor:data","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"{\t \"temperature\": 22.5,\t \"humidity\": 65,\t \"timestamp\": $now()\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":580,"wires":[["9e59f275496d722d"]]},{"id":"9e59f275496d722d","type":"json","z":"d4f60c79eff5211d","g":"5e2842a4730589c0","name":"","property":"payload","action":"","pretty":false,"x":990,"y":580,"wires":[["6acc07a393e5ee26"]]},{"id":"39de5da95585227f","type":"group","z":"d4f60c79eff5211d","name":"Pub/Sub Messaging","style":{"label":true},"nodes":["7756558fd542d657","bf2dc26107eff967","9856ddb8e7bc28e8","bcd9b22fd67ecf7c","22f0526fab3b589b"],"x":514,"y":719,"w":632,"h":162},{"id":"7756558fd542d657","type":"inject","z":"d4f60c79eff5211d","g":"39de5da95585227f","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":760,"wires":[["9856ddb8e7bc28e8"]]},{"id":"bf2dc26107eff967","type":"redis-out","z":"d4f60c79eff5211d","g":"39de5da95585227f","server":"e370dc92b39a7ba4","command":"publish","name":"","topic":"alerts:temperature","obj":true,"x":1030,"y":760,"wires":[]},{"id":"9856ddb8e7bc28e8","type":"change","z":"d4f60c79eff5211d","g":"39de5da95585227f","name":"Set Alert Message","rules":[{"t":"set","p":"payload","pt":"msg","to":"ALERT: Temperature critical in Zone A: 85°C - Equipment shutdown initiated","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":760,"wires":[["bf2dc26107eff967"]]},{"id":"bcd9b22fd67ecf7c","type":"redis-in","z":"d4f60c79eff5211d","g":"39de5da95585227f","server":"e370dc92b39a7ba4","command":"subscribe","name":"","topic":"alerts:temperature","obj":true,"timeout":0,"x":630,"y":840,"wires":[["22f0526fab3b589b"]]},{"id":"22f0526fab3b589b","type":"debug","z":"d4f60c79eff5211d","g":"39de5da95585227f","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":990,"y":840,"wires":[]},{"id":"adc4b0df6b0e84e3","type":"group","z":"d4f60c79eff5211d","name":"Using Lua Scripts for Atomic Operations","style":{"label":true},"nodes":["ca8a523710138a11","8804755befa1fbc8","0898e80e28b7d276","0b16690b3c2c10df","9a03ebdea51eefdc","c641d8e54620a73a","7c11a5f1c9716527","a07a025db962be50"],"x":514,"y":899,"w":1112,"h":142},{"id":"ca8a523710138a11","type":"inject","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":1000,"wires":[["8804755befa1fbc8"]]},{"id":"8804755befa1fbc8","type":"function","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"Prepare Lua Script Arguments","func":"// msg.payload format: [keys..., args...]\n// First element(s) are the keys, remaining elements are arguments\nmsg.payload = [\n \"inventory:product:SKU-12345\", // KEYS[1]\n 3 // ARGV[1] - quantity requested\n];\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":1000,"wires":[["0898e80e28b7d276"]]},{"id":"0898e80e28b7d276","type":"redis-lua-script","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","server":"e370dc92b39a7ba4","name":"","keyval":"1","func":"local key = KEYS[1]\nlocal requested = tonumber(ARGV[1])\n\nlocal current = tonumber(redis.call('GET', key) or \"0\")\n\nif current >= requested then\n redis.call('DECRBY', key, requested)\n return {1, current - requested}\nelse\n return {0, current}\nend","stored":false,"block":false,"x":1140,"y":1000,"wires":[["0b16690b3c2c10df"]]},{"id":"0b16690b3c2c10df","type":"function","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"Format Lua Script Response","func":"const result = msg.payload;\nconst success = result[0];\nconst remaining = result[1];\n\nif (success === 1) {\n msg.payload = {\n status: \"success\",\n message: `Order processed. Remaining stock: ${remaining}`,\n remaining: remaining\n };\n} else {\n msg.payload = {\n status: \"failed\",\n message: `Insufficient stock. Available: ${remaining}`,\n available: remaining\n };\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1340,"y":1000,"wires":[["9a03ebdea51eefdc"]]},{"id":"9a03ebdea51eefdc","type":"debug","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1530,"y":1000,"wires":[]},{"id":"c641d8e54620a73a","type":"redis-command","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","server":"e370dc92b39a7ba4","command":"SET","name":"","topic":"inventory:product:SKU-12345","params":"[10]","paramsType":"json","payloadType":"json","block":false,"x":880,"y":940,"wires":[["7c11a5f1c9716527"]]},{"id":"7c11a5f1c9716527","type":"debug","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1130,"y":940,"wires":[]},{"id":"a07a025db962be50","type":"inject","z":"d4f60c79eff5211d","g":"adc4b0df6b0e84e3","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":610,"y":940,"wires":[["c641d8e54620a73a"]]},{"id":"01a96fb2044d723f","type":"group","z":"d4f60c79eff5211d","name":"Direct Redis Client Access with redis-instance","style":{"label":true},"nodes":["745f41f352fa2212","a9ec9a8a5a66daa3","e3a5634ef0ebcb78","5192081309e08db9","4f169053bbd7add9","15f0b0462f795828","4a394700c6914961"],"x":514,"y":1059,"w":732,"h":222},{"id":"745f41f352fa2212","type":"redis-instance","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","server":"e370dc92b39a7ba4","name":"","topic":"redis","location":"flow","x":590,"y":1100,"wires":[]},{"id":"a9ec9a8a5a66daa3","type":"inject","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":620,"y":1180,"wires":[["e3a5634ef0ebcb78"]]},{"id":"e3a5634ef0ebcb78","type":"function","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"Batch Store Sensor Readings (Pipeline)","func":"const redis = flow.get('redis');\n\n// Create a pipeline\nconst pipeline = redis.pipeline();\n\n// Add multiple sensor readings in one batch\nconst sensors = [\n { id: 'temp-01', value: 23.5, unit: 'C' },\n { id: 'temp-02', value: 24.1, unit: 'C' },\n { id: 'humidity-01', value: 65, unit: '%' },\n { id: 'pressure-01', value: 1013, unit: 'hPa' }\n];\n\nsensors.forEach(sensor => {\n const key = `sensor:${sensor.id}:latest`;\n const data = JSON.stringify({\n value: sensor.value,\n unit: sensor.unit,\n timestamp: Date.now()\n });\n pipeline.set(key, data, 'EX', 3600); // Expire in 1 hour\n});\n\n// Execute all commands at once\npipeline.exec((err, results) => {\n if (err) {\n node.error(err, msg);\n return;\n }\n\n msg.payload = {\n message: `Stored ${results.length} sensor readings`,\n results: results\n };\n node.send(msg);\n});","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":1180,"wires":[["5192081309e08db9"]]},{"id":"5192081309e08db9","type":"debug","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1140,"y":1180,"wires":[]},{"id":"4f169053bbd7add9","type":"inject","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":620,"y":1240,"wires":[["15f0b0462f795828"]]},{"id":"15f0b0462f795828","type":"function","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"Scan and List Latest Sensor Keys","func":"const redis = flow.get('redis');\n\nasync function scanKeys() {\n const matchPattern = 'sensor:*:latest';\n const allKeys = [];\n let cursor = '0';\n\n try {\n do {\n // Scan with pattern matching\n const result = await redis.scan(\n cursor,\n 'MATCH', matchPattern,\n 'COUNT', 100\n );\n\n cursor = result[0];\n const keys = result[1];\n allKeys.push(...keys);\n\n } while (cursor !== '0');\n\n msg.payload = {\n pattern: matchPattern,\n count: allKeys.length,\n keys: allKeys\n };\n\n node.send(msg);\n\n } catch (err) {\n node.error(err, msg);\n }\n}\n\nscanKeys();","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":860,"y":1240,"wires":[["4a394700c6914961"]]},{"id":"4a394700c6914961","type":"debug","z":"d4f60c79eff5211d","g":"01a96fb2044d723f","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1140,"y":1240,"wires":[]},{"id":"d7c53907f5b90ca5","type":"global-config","env":[],"modules":{"node-red-contrib-redis":"1.4.0"}}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/database/sqlite.md b/nuxt/content-guides/node-red/database/sqlite.md
similarity index 98%
rename from src/node-red/database/sqlite.md
rename to nuxt/content-guides/node-red/database/sqlite.md
index f66ddb2e69..f2991dae83 100644
--- a/src/node-red/database/sqlite.md
+++ b/nuxt/content-guides/node-red/database/sqlite.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: SQLite
- parent: Database
+title: Using SQLite with Node-RED (2026 Updated)
+metaTitle: "Using SQLite with Node-RED (2026 Updated)"
+navTitle: SQLite
+navOrder: 50
meta:
- title: Using SQLite with Node-RED (2026 Updated)
description: Learn how to seamlessly integrate SQLite with Node-RED for efficient data management and application development.
keywords: nodered sqlite, node red sqlite, node-red-node-sqlite, sqlite nodered, sqlite node red
---
-# {{ meta.title }}
+# Using SQLite with Node-RED (2026 Updated)
SQLite is a lightweight, self-contained database that does not require a server. It is ideal for quick setups, small applications, and IoT devices, as it stores data directly in files and is easy to manage.
@@ -230,6 +230,8 @@ DELETE FROM devices WHERE device_id = $id;
Below is the complete flow created throughout this guide. You can import it into Node-RED and experiment with it.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"7397d3636bf9eec9","type":"group","z":"9cf82b68bb89e8ce","name":"Create Table ( fixed statement )","style":{"label":true},"nodes":["843c6bddd1fa88dd","c7134f3054775ed9","462a0643f5f85a85"],"x":1034,"y":4459,"w":732,"h":82},{"id":"843c6bddd1fa88dd","type":"inject","z":"9cf82b68bb89e8ce","g":"7397d3636bf9eec9","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":4500,"wires":[["c7134f3054775ed9"]]},{"id":"c7134f3054775ed9","type":"sqlite","z":"9cf82b68bb89e8ce","g":"7397d3636bf9eec9","mydb":"c91139d411507971","sqlquery":"fixed","sql":"CREATE TABLE IF NOT EXISTS devices (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n device_id TEXT NOT NULL UNIQUE,\n name TEXT,\n status TEXT,\n location TEXT,\n last_seen DATETIME DEFAULT CURRENT_TIMESTAMP\n);\n","name":"Create Table","x":1490,"y":4500,"wires":[["462a0643f5f85a85"]]},{"id":"462a0643f5f85a85","type":"debug","z":"9cf82b68bb89e8ce","g":"7397d3636bf9eec9","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1660,"y":4500,"wires":[]},{"id":"c91139d411507971","type":"sqlitedb","db":"/tmp/sqlite","mode":"RWC"},{"id":"191f069422d0f9b4","type":"group","z":"9cf82b68bb89e8ce","name":"Read Records","style":{"label":true},"nodes":["f145276495e6a7bd","b6e61ecb0379b93b","02c7723103391825"],"x":1034,"y":4559,"w":732,"h":82},{"id":"f145276495e6a7bd","type":"inject","z":"9cf82b68bb89e8ce","g":"191f069422d0f9b4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":4600,"wires":[["b6e61ecb0379b93b"]]},{"id":"b6e61ecb0379b93b","type":"sqlite","z":"9cf82b68bb89e8ce","g":"191f069422d0f9b4","mydb":"c91139d411507971","sqlquery":"fixed","sql":"SELECT * FROM devices;\n","name":"Read","x":1470,"y":4600,"wires":[["02c7723103391825"]]},{"id":"02c7723103391825","type":"debug","z":"9cf82b68bb89e8ce","g":"191f069422d0f9b4","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1660,"y":4600,"wires":[]},{"id":"c9bf8c21a73cf4f1","type":"group","z":"9cf82b68bb89e8ce","name":"Batch without response","style":{"label":true},"nodes":["d8d2fd8ff4da64fe","7d7556aa27fa6ca8","d15a64daed322158","ea5920b64362e412"],"x":1034,"y":4659,"w":732,"h":82},{"id":"d8d2fd8ff4da64fe","type":"inject","z":"9cf82b68bb89e8ce","g":"c9bf8c21a73cf4f1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":4700,"wires":[["ea5920b64362e412"]]},{"id":"7d7556aa27fa6ca8","type":"sqlite","z":"9cf82b68bb89e8ce","g":"c9bf8c21a73cf4f1","mydb":"c91139d411507971","sqlquery":"batch","sql":"INSERT INTO devices (device_id, name, status, location)\nVALUES ($id, $name, $status, $location);","name":"Insert","x":1470,"y":4700,"wires":[["d15a64daed322158"]]},{"id":"d15a64daed322158","type":"debug","z":"9cf82b68bb89e8ce","g":"c9bf8c21a73cf4f1","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1660,"y":4700,"wires":[]},{"id":"ea5920b64362e412","type":"function","z":"9cf82b68bb89e8ce","g":"c9bf8c21a73cf4f1","name":"Batch Insert","func":"// Sample 10 devices\nconst devices = [\n { id: 'DEV002', name: 'Pressure Sensor', status: 'offline', location: 'Factory Floor 2' },\n { id: 'DEV003', name: 'Humidity Sensor', status: 'online', location: 'Warehouse 1' },\n { id: 'DEV004', name: 'Vibration Sensor', status: 'online', location: 'Factory Floor 3' },\n { id: 'DEV005', name: 'Flow Sensor', status: 'offline', location: 'Plant 1' },\n { id: 'DEV006', name: 'Level Sensor', status: 'online', location: 'Tank 1' },\n { id: 'DEV007', name: 'Pressure Gauge', status: 'online', location: 'Plant 2' },\n { id: 'DEV008', name: 'Temperature Sensor 2', status: 'offline', location: 'Warehouse 2' },\n { id: 'DEV009', name: 'Humidity Sensor 2', status: 'online', location: 'Plant 3' },\n { id: 'DEV010', name: 'Flow Meter', status: 'online', location: 'Factory Floor 4' }\n];\n\n// Generate batch SQL\nconst batchSQL = devices.map(d =>\n `INSERT INTO devices (device_id, name, status, location) VALUES \n ('${d.id}', '${d.name}', '${d.status}', '${d.location}');`\n).join('\\n');\n\nmsg.topic = batchSQL;\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1310,"y":4700,"wires":[["7d7556aa27fa6ca8"]]},{"id":"e199d35406609471","type":"group","z":"9cf82b68bb89e8ce","name":"Update Record ( via prepared statement with array )","style":{"label":true},"nodes":["9688278c29895ab0","ea71fbc3ef5cc8bd","9208e6ef30218e35","1ad5c81d925a0310"],"x":1034,"y":4759,"w":732,"h":82},{"id":"9688278c29895ab0","type":"inject","z":"9cf82b68bb89e8ce","g":"e199d35406609471","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":4800,"wires":[["9208e6ef30218e35"]]},{"id":"ea71fbc3ef5cc8bd","type":"sqlite","z":"9cf82b68bb89e8ce","g":"e199d35406609471","mydb":"c91139d411507971","sqlquery":"prepared","sql":"UPDATE devices SET status = $1 WHERE device_id = $2;","name":"Update","x":1480,"y":4800,"wires":[["1ad5c81d925a0310"]]},{"id":"9208e6ef30218e35","type":"change","z":"9cf82b68bb89e8ce","g":"e199d35406609471","name":"Set Params","rules":[{"t":"set","p":"params","pt":"msg","to":"[\"offline\", \"DEV002\"]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1310,"y":4800,"wires":[["ea71fbc3ef5cc8bd"]]},{"id":"1ad5c81d925a0310","type":"debug","z":"9cf82b68bb89e8ce","g":"e199d35406609471","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1660,"y":4800,"wires":[]},{"id":"67085d9fa9b7b5dd","type":"group","z":"9cf82b68bb89e8ce","name":"Delete Record ( via prepared statement with object )","style":{"label":true},"nodes":["c551a497bf776c15","1767cd99e3b03bd2","b3570250013c8703","9ec536a39e055ffe"],"x":1034,"y":4859,"w":732,"h":82},{"id":"c551a497bf776c15","type":"inject","z":"9cf82b68bb89e8ce","g":"67085d9fa9b7b5dd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1140,"y":4900,"wires":[["b3570250013c8703"]]},{"id":"1767cd99e3b03bd2","type":"sqlite","z":"9cf82b68bb89e8ce","g":"67085d9fa9b7b5dd","mydb":"c91139d411507971","sqlquery":"prepared","sql":"DELETE FROM devices WHERE device_id = $device_id;","name":"Delete","x":1470,"y":4900,"wires":[["9ec536a39e055ffe"]]},{"id":"b3570250013c8703","type":"change","z":"9cf82b68bb89e8ce","g":"67085d9fa9b7b5dd","name":"Set Params","rules":[{"t":"set","p":"params","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"params.$device_id","pt":"msg","to":"DEV006","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1310,"y":4900,"wires":[["1767cd99e3b03bd2"]]},{"id":"9ec536a39e055ffe","type":"debug","z":"9cf82b68bb89e8ce","g":"67085d9fa9b7b5dd","name":"debug 5","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1660,"y":4900,"wires":[]},{"id":"4c464964391e1c1c","type":"global-config","env":[],"modules":{"node-red-node-sqlite":"1.1.1"}}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/database/timescaledb.md b/nuxt/content-guides/node-red/database/timescaledb.md
similarity index 97%
rename from src/node-red/database/timescaledb.md
rename to nuxt/content-guides/node-red/database/timescaledb.md
index aff38d57c4..c7623204c6 100644
--- a/src/node-red/database/timescaledb.md
+++ b/nuxt/content-guides/node-red/database/timescaledb.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: TimescaleDB
- parent: Database
+title: Using TimescaleDB with Node-RED (2026 Updated)
+metaTitle: "Using TimescaleDB with Node-RED (2026 Updated)"
+navTitle: TimescaleDB
+navOrder: 50
meta:
- title: Using TimescaleDB with Node-RED (2026 Updated)
description: Learn how to integrate TimescaleDB with Node-RED for storing and managing time-series data efficiently.
keywords: node-red timescaledb, nodered postgresql, nodered time-series database
-image: /node-red/database/images/timescaledb-with-node-red.png
+image: /docs/node-red/database/images/timescaledb-with-node-red.png
---
-# {{ meta.title }}
+# Using TimescaleDB with Node-RED (2026 Updated)
In the context of IoT and IIoT applications, time series databases are essential for storing data based on timestamps. While InfluxDB has been a popular choice for a long time, another time series database, TimescaleDB, is gaining popularity. This guide will cover how to use TimescaleDB with Node-RED, how TimescaleDB works, and the queries needed when building IoT applications.
@@ -87,9 +87,11 @@ SELECT create_hypertable('sensor_data', 'time');
2. Drag an Inject node onto the canvas, which we will use to trigger the operation.
3. Connect the Inject node's output to the input of the PostgreSQL node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"d766709f13c8410b","type":"inject","z":"7748186d67ad0a58","name":"Create hypertable","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":140,"wires":[["a977cb646de2a30b"]]},{"id":"a977cb646de2a30b","type":"postgresql","z":"7748186d67ad0a58","name":"PostgreSQL","query":"CREATE TABLE sensor_data (\n time TIMESTAMPTZ NOT NULL,\n location TEXT,\n temperature DOUBLE PRECISION\n);\n\nSELECT create_hypertable('sensor_data', 'time');\n","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":490,"y":140,"wires":[["c843732f2088f83e"]]},{"id":"c843732f2088f83e","type":"debug","z":"7748186d67ad0a58","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":140,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Inserting Data into the Table
@@ -119,9 +121,11 @@ VALUES (
5. Drag a Debug node onto the canvas.
6. Connect the output of the Inject nodes to the input of the PostgreSQL node and the output of PostgreSQL to the input of the Debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"c42dfdaa44a02eda","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"INSERT INTO sensor_data (time, location, temperature)\nVALUES (now(), '{{msg.payload.location}}', '{{msg.payload.temperature}}');\n","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":490,"y":540,"wires":[["f88822fc9fdf90dc"]]},{"id":"f88822fc9fdf90dc","type":"debug","z":"7748186d67ad0a58","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":700,"y":540,"wires":[]},{"id":"b3b5fc6ad830145e","type":"inject","z":"7748186d67ad0a58","name":"Sensor placed in the New York","props":[{"p":"payload.location","v":"New York","vt":"str"},{"p":"payload.temperature","v":"$floor(($random() * 21) + 30)","vt":"jsonata"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":230,"y":580,"wires":[["c42dfdaa44a02eda"]]},{"id":"2d07d8d73ed43f37","type":"inject","z":"7748186d67ad0a58","name":"Sensor placed in the Chicago","props":[{"p":"payload.location","v":"Chicago","vt":"str"},{"p":"payload.temperature","v":"$floor(($random() * 21) + 30)","vt":"jsonata"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":230,"y":520,"wires":[["c42dfdaa44a02eda"]]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Updating data to the table
@@ -140,9 +144,11 @@ UPDATE sensor_data
3. Drag a Debug node onto the canvas.
4. Connect the output of the Inject node to the input of the PostgreSQL node and the output of the PostgreSQL node to the input of the Debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"702b9169ff00396c","type":"inject","z":"7748186d67ad0a58","name":"Updating data based on condition","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":1120,"wires":[["81dcb2d851bb9316"]]},{"id":"81dcb2d851bb9316","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"-- Update temperature data in the sensor_data table\nUPDATE sensor_data\n SET temperature = temperature + 0.1\n WHERE time >= '2024-05-29T11:50:25.859Z' -- Starting timestamp for the update\n AND time < '2024-05-29T12:17:43.305Z'; -- Ending timestamp for the update\n","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":530,"y":1120,"wires":[["29e28595a9f5a0df"]]},{"id":"29e28595a9f5a0df","type":"debug","z":"7748186d67ad0a58","name":"debug 14","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":1120,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Deleting data to the table
@@ -157,9 +163,11 @@ WHERE temperature < 35 -- Delete rows where the temperature is less than 35 degr
3. Drag a Debug node onto the canvas.
4. Connect the output of the Inject node to the input of the PostgreSQL node and the output of the PostgreSQL node to the input of the Debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"702b9169ff00396c","type":"inject","z":"7748186d67ad0a58","name":"Delete data based on condition","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":1120,"wires":[["81dcb2d851bb9316"]]},{"id":"81dcb2d851bb9316","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"-- Delete rows from the sensor_data table where the temperature is below 35 degrees Celsius or humidity is below 60%\nDELETE FROM sensor_data\nWHERE temperature < 35 -- Delete rows where the temperature is less than 35 degrees Celsius","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":530,"y":1120,"wires":[["29e28595a9f5a0df"]]},{"id":"29e28595a9f5a0df","type":"debug","z":"7748186d67ad0a58","name":"debug 14","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":1120,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Retrieving all data from the table
@@ -173,9 +181,11 @@ SELECT * FROM sensor_data;
3. Drag a Debug node onto the canvas.
4. Connect the output of the Inject node to the input of the PostgreSQL node and the output of the PostgreSQL node to the input of the Debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"d551e15f7013e970","type":"inject","z":"7748186d67ad0a58","name":"Retrieve all data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":660,"wires":[["858063c8e7d90f50"]]},{"id":"858063c8e7d90f50","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"SELECT * FROM sensor_data;","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":550,"y":660,"wires":[["79156835d5ad4c4d"]]},{"id":"79156835d5ad4c4d","type":"debug","z":"7748186d67ad0a58","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":660,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Retrieve Recent Data
@@ -195,9 +205,11 @@ LIMIT 100; -- Limit the results to 100 rows
3. Drag a Debug node onto the canvas.
4. Connect the output of the Inject node to the input of the PostgreSQL node and the output of the PostgreSQL node to the input of the Debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"9436c79e9d9e3593","type":"inject","z":"7748186d67ad0a58","name":"Retrieve last 100 data ordered by time","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":720,"wires":[["6d26117dd61d0ecc"]]},{"id":"6d26117dd61d0ecc","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"SELECT * FROM sensor_data ORDER BY time DESC LIMIT 100;","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":550,"y":720,"wires":[["092a08307ae6d63c"]]},{"id":"092a08307ae6d63c","type":"debug","z":"7748186d67ad0a58","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":720,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Retrieve Data Based on Time Range
@@ -216,9 +228,11 @@ WHERE time > NOW() - INTERVAL '400 SECONDS';
3. Drag a Debug node onto the canvas.
4. Connect the output of the inject node to the input of the PostgreSQL node, and connect the output of the PostgreSQL node to the input of the debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"60e111b1f6e09613","type":"inject","z":"7748186d67ad0a58","name":"Retrieve data based on time range","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":880,"wires":[["0b1ec338dbb164f9"]]},{"id":"0b1ec338dbb164f9","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"-- Aggregate data into specific time buckets\nSELECT time_bucket('15 minutes', time) AS fifteen_min, -- Create time buckets of 15 minutes\n location, -- Location of the sensor\n MAX(temperature) AS max_temp -- Calculate the maximum temperature within each time bucket\nFROM sensor_data -- Select data from the conditions table\nWHERE time > NOW() - INTERVAL '3 hours' -- Filter data to include only the last 3 hours\nGROUP BY fifteen_min, location -- Group data by time buckets and location\nORDER BY fifteen_min DESC, max_temp DESC; -- Order the results by time bucket in descending order, and then by maximum temperature in descending order\n","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":550,"y":880,"wires":[["f6f6c4fa651ee351"]]},{"id":"f6f6c4fa651ee351","type":"debug","z":"7748186d67ad0a58","name":"debug 13","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":880,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Aggregating data into specific time bucket
@@ -241,9 +255,11 @@ ORDER BY fifteen_min DESC, max_temp DESC; -- Order the results by time bucket in
3. Drag the Debug node onto the canvas.
4. Connect the output of the inject node to the input of the PostgreSQL node, and connect the output of the PostgreSQL node to the input of the debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"60e111b1f6e09613","type":"inject","z":"7748186d67ad0a58","name":"Aggregating data into specific time bucket","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":880,"wires":[["0b1ec338dbb164f9"]]},{"id":"0b1ec338dbb164f9","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"-- Aggregate data into specific time buckets\nSELECT time_bucket('15 minutes', time) AS fifteen_min, -- Create time buckets of 15 minutes\n location, -- Location of the sensor\n MAX(temperature) AS max_temp -- Calculate the maximum temperature within each time bucket\nFROM sensor_data -- Select data from the conditions table\nWHERE time > NOW() - INTERVAL '3 hours' -- Filter data to include only the last 3 hours\nGROUP BY fifteen_min, location -- Group data by time buckets and location\nORDER BY fifteen_min DESC, max_temp DESC; -- Order the results by time bucket in descending order, and then by maximum temperature in descending order\n","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":550,"y":880,"wires":[["f6f6c4fa651ee351"]]},{"id":"f6f6c4fa651ee351","type":"debug","z":"7748186d67ad0a58","name":"debug 13","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":880,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
### Dropping the table
@@ -257,12 +273,14 @@ DROP TABLE IF EXISTS sensor_data;
3. Drag the Debug node onto the canvas.
4. Connect the output of the inject node to the input of the PostgreSQL node, and connect the output of the PostgreSQL node to the input of the debug node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"5275332fecd1c715","type":"inject","z":"7748186d67ad0a58","name":"Drop table","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":960,"wires":[["382c26de90712487"]]},{"id":"382c26de90712487","type":"postgresql","z":"7748186d67ad0a58","name":"","query":"DROP TABLE IF EXISTS sensor_data;","postgreSQLConfig":"ea1f8e3d9db95245","split":false,"rowsPerMsg":1,"outputs":1,"x":450,"y":960,"wires":[["d7eb0c9020c968c5"]]},{"id":"d7eb0c9020c968c5","type":"debug","z":"7748186d67ad0a58","name":"debug 12","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":720,"y":960,"wires":[]},{"id":"ea1f8e3d9db95245","type":"postgreSQLConfig","name":"TimescaleDB Configurations","host":"${HOST}","hostFieldType":"str","port":"${PORT}","portFieldType":"num","database":"${DATABASE}","databaseFieldType":"str","ssl":"false","sslFieldType":"bool","applicationName":"","applicationNameType":"str","max":"10","maxFieldType":"num","idle":"1000","idleFieldType":"num","connectionTimeout":"10000","connectionTimeoutFieldType":"num","user":"${USERNAME}","userFieldType":"str","password":"${PASSWORD}","passwordFieldType":"str"}]
-{% endrenderFlow %}
+```
+::
## Deploying the Flow
1. To test the imported flows, you need to deploy them. To do that, click on the deploy button located in the top right corner.
-After deploying the flow, you can test each operation such as creating, deleting, updating, and other queries by clicking on the inject button. Upon successful operation, you will be able to see the results in the debug panel of the sidebar. If you want to learn any additional information about PostgreSQL, you can refer to the [Using PostgreSQL with Node-RED](/node-red/database/postgresql/) where you will also find the section which shows the messages received after a successful operation by the PostgresWQL node.
\ No newline at end of file
+After deploying the flow, you can test each operation such as creating, deleting, updating, and other queries by clicking on the inject button. Upon successful operation, you will be able to see the results in the debug panel of the sidebar. If you want to learn any additional information about PostgreSQL, you can refer to the [Using PostgreSQL with Node-RED](/docs/node-red/database/postgresql/) where you will also find the section which shows the messages received after a successful operation by the PostgresWQL node.
diff --git a/nuxt/content-guides/node-red/getting-started/README.md b/nuxt/content-guides/node-red/getting-started/README.md
new file mode 100644
index 0000000000..7e94a94d6f
--- /dev/null
+++ b/nuxt/content-guides/node-red/getting-started/README.md
@@ -0,0 +1,23 @@
+---
+title: Getting Started with Node-RED
+metaTitle: "Getting Started with Node-RED"
+navTitle: Getting started
+navOrder: 2
+meta:
+ description: Learn the basics of Node-RED, a powerful tool for IoT integration and workflow automation.
+ keywords: node-red, node-red basics, node-red foundation, node-red editor
+---
+
+# Getting Started with Node-RED
+
+This section provides an overview of Node-RED, a robust visual tool designed for integrating IoT devices and automating workflows without needing extensive programming knowledge.
+
+- [Getting Started with the Node-RED Editor](/docs/node-red/getting-started/editor/): Learn about the powerful features of Node-RED Editor.
+- [Node-RED Port (localhost:1880)](/docs/node-red/getting-started/node-red-port/): Learn how to configure Node-RED ports, change default settings, secure your installation, and set up remote access with FlowFuse.
+- [How to Update Node-RED](/docs/node-red/getting-started/update-node-red/): Learn how to update Node-RED across different installation methods including npm, Raspberry Pi, Docker, and FlowFuse
+- [Node-RED Library – A Curated and Actively Maintained List of Nodes](/docs/node-red/getting-started/library/): Browse the Node-RED Library for community-built nodes and integrations. FlowFuse's curated catalog offers tested, documented, enterprise-ready solutions with professional support for critical deployments.
+- [Installing Node-RED on Android](/docs/node-red/getting-started/node-red-android/): Learn how to install and run Node-RED on Android devices using Termux
+- [Understanding Node-RED Messages](/docs/node-red/getting-started/node-red-messages/): A comprehensive guide to working with Node-RED messages, ensuring error-free flows and optimized data handling.
+- [Strings in Node-RED: Convert String to Number, Split, Concatenate, Trim, and More](/docs/node-red/getting-started/string/): Learn essential string operations in Node-RED including converting between strings and numbers, splitting and concatenating text, parsing JSON, extracting substrings, trimming whitespace, and more. Step-by-step guide with practical examples.
+- [Node-RED Programming](/docs/node-red/getting-started/programming/): Master Node-RED programming fundamentals including flows, nodes, messages, conditional logic, and data manipulation. Learn essential concepts for building sophisticated visual programming solutions.
+- [Working with Dates and Times in Node-RED](/docs/node-red/getting-started/date-and-time/): Learn how to handle dates and times in Node-RED without coding. Master timestamps, formatting, timezones, calculations, and time-based automation with visual nodes.
diff --git a/src/node-red/getting-started/date-and-time.md b/nuxt/content-guides/node-red/getting-started/date-and-time.md
similarity index 98%
rename from src/node-red/getting-started/date-and-time.md
rename to nuxt/content-guides/node-red/getting-started/date-and-time.md
index 26f2a6ed0f..31958da125 100644
--- a/src/node-red/getting-started/date-and-time.md
+++ b/nuxt/content-guides/node-red/getting-started/date-and-time.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: Date & Time
- order: 7
- parent: Getting Started
+title: Working with Dates and Times in Node-RED
+metaTitle: "Working with Dates and Times in Node-RED"
+navTitle: Date & Time
+navOrder: 7
meta:
- title: Working with Dates and Times in Node-RED
- description: Learn how to handle dates and times in Node-RED without coding. Master timestamps, formatting, timezones, calculations, and time-based automation with visual nodes.
+ description: Learn how to handle dates and times in Node-RED without coding. Master timestamps, formatting, timezones, calculations, and time-based automation with visual nodes.
keywords: Node-RED, dates, times, timestamps, JSONata, Moment.js, Date/Time Formatter, timezones, date formatting, time calculations, inject node, change node, human-readable dates, relative time, time-based automation, date math, date difference, ISO 8601, flow automation, Node-RED tutorial, date manipulation, scheduling, event logging, time conversion, time adjustment, visual programming
---
-# {{meta.title}}
+# Working with Dates and Times in Node-RED
Working with dates and times comes up constantly in Node-RED. Whether you're logging events, scheduling tasks, checking business hours, displaying the current time, or pulling historical data, it all relies on handling timestamps correctly. The best part is that you can manage all of this using visual nodes, without writing any code.
@@ -48,9 +47,11 @@ In the inject/change node, select **JSONata expression** from the payload type d
This JSONata approach works identically in both nodes, use whichever fits your flow better.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"9341cec1a1f9e50e","type":"group","z":"d7101f3a4d45deed","name":"Getting the Current Time in Node-RED","style":{"label":true},"nodes":["89cb30afb7fec451","51937bef067f5257","547ec4b9d6a389c9"],"x":108,"y":73,"w":804,"h":694},{"id":"89cb30afb7fec451","type":"group","z":"d7101f3a4d45deed","g":"9341cec1a1f9e50e","name":"Using Change node ( JSONata )","style":{"label":true},"nodes":["b5bdfd1b2a3b9c27","444d17c32b8bd1c1","276e0fcf607c944d","07fbc83f895b7aa4","ac8e5e28a896f52c","8d4143fb8361c469","aff528c64b9568ad"],"x":134,"y":539,"w":752,"h":202},{"id":"b5bdfd1b2a3b9c27","type":"inject","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"Inject","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":230,"y":640,"wires":[["444d17c32b8bd1c1","276e0fcf607c944d","07fbc83f895b7aa4"]]},{"id":"444d17c32b8bd1c1","type":"change","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"milliseconds since epoch","rules":[{"t":"set","p":"payload","pt":"msg","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":580,"wires":[["ac8e5e28a896f52c"]]},{"id":"276e0fcf607c944d","type":"change","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"YYYY-MM-DDTHH:mm:ss.sssZ","rules":[{"t":"set","p":"payload","pt":"msg","to":"$now()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":640,"wires":[["8d4143fb8361c469"]]},{"id":"07fbc83f895b7aa4","type":"change","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"JavaScript Date object","rules":[{"t":"set","p":"payload","pt":"msg","to":"$moment()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":700,"wires":[["aff528c64b9568ad"]]},{"id":"ac8e5e28a896f52c","type":"debug","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":580,"wires":[]},{"id":"8d4143fb8361c469","type":"debug","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":640,"wires":[]},{"id":"aff528c64b9568ad","type":"debug","z":"d7101f3a4d45deed","g":"89cb30afb7fec451","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":700,"wires":[]},{"id":"51937bef067f5257","type":"group","z":"d7101f3a4d45deed","g":"9341cec1a1f9e50e","name":"Using Change node ( Timestamp option )","style":{"label":true},"nodes":["375d143d48695d37","72fcba815fa5cfdd","4e50e0a2e436b658","d41aa61b456bd3a1","f5bec9511bc8f77f","9d3fb7b89adafa8d","7e60fb224e4ff747"],"x":134,"y":319,"w":752,"h":202},{"id":"375d143d48695d37","type":"inject","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"Inject","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":230,"y":420,"wires":[["72fcba815fa5cfdd","4e50e0a2e436b658","d41aa61b456bd3a1"]]},{"id":"72fcba815fa5cfdd","type":"change","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"milliseconds since epoch","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":360,"wires":[["f5bec9511bc8f77f"]]},{"id":"4e50e0a2e436b658","type":"change","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"YYYY-MM-DDTHH:mm:ss.sssZ","rules":[{"t":"set","p":"payload","pt":"msg","to":"iso","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":420,"wires":[["9d3fb7b89adafa8d"]]},{"id":"d41aa61b456bd3a1","type":"change","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"JavaScript Date object","rules":[{"t":"set","p":"payload","pt":"msg","to":"object","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":480,"wires":[["7e60fb224e4ff747"]]},{"id":"f5bec9511bc8f77f","type":"debug","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":360,"wires":[]},{"id":"9d3fb7b89adafa8d","type":"debug","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":420,"wires":[]},{"id":"7e60fb224e4ff747","type":"debug","z":"d7101f3a4d45deed","g":"51937bef067f5257","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":480,"wires":[]},{"id":"547ec4b9d6a389c9","type":"group","z":"d7101f3a4d45deed","g":"9341cec1a1f9e50e","name":"Using Inject Nodes ( Timestamp Option )","style":{"label":true},"nodes":["499ab581537f5598","b9bd4fdc2f424cbf","b969db92319355f3","ccc969cd1ed85eda","ab178e4e3109f9b0","cdb0cfd879846420"],"x":134,"y":99,"w":752,"h":202},{"id":"499ab581537f5598","type":"inject","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"milliseconds since epoch","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":310,"y":140,"wires":[["b9bd4fdc2f424cbf"]]},{"id":"b9bd4fdc2f424cbf","type":"debug","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":140,"wires":[]},{"id":"b969db92319355f3","type":"inject","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"YYYY-MM-DDTHH:mm:ss.sssZ","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"iso","payloadType":"date","x":340,"y":200,"wires":[["ccc969cd1ed85eda"]]},{"id":"ccc969cd1ed85eda","type":"debug","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":200,"wires":[]},{"id":"ab178e4e3109f9b0","type":"inject","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"JavaScript Date object","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"object","payloadType":"date","x":300,"y":260,"wires":[["cdb0cfd879846420"]]},{"id":"cdb0cfd879846420","type":"debug","z":"d7101f3a4d45deed","g":"547ec4b9d6a389c9","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":260,"wires":[]}]
-{% endrenderFlow %}
+```
+::
> For more advanced date/time operations and formatting, see the [JSONata documentation](https://docs.jsonata.org/date-time-functions).
@@ -172,9 +173,11 @@ JSONata uses square brackets, but the codes are different from the **Date/Time F
- `$fromMillis(payload, '[M]/[D]/[Y]')` → 12/11/2024
- `$fromMillis(payload, '[h]:[m01] [P]')` → 3:45 PM
-{% renderFlow %}
+::render-flow
+```json
[{"id":"1e8a1110d36d3f33","type":"group","z":"d7101f3a4d45deed","name":"Formatting Dates for Display","style":{"label":true},"nodes":["f019c2f5ed9d8104","1699577150167eb5"],"x":108,"y":793,"w":804,"h":414},{"id":"f019c2f5ed9d8104","type":"group","z":"d7101f3a4d45deed","g":"1e8a1110d36d3f33","name":"The Moment Nodes","style":{"label":true},"nodes":["bd06565765141868","898b23fa51f95edf","f734d9e8979b20b2","f3a3a5a9974816d3","2de95300ee070276","d5f3d8aeaaeffa7d","b713b196b48c62d3"],"x":134,"y":819,"w":752,"h":202},{"id":"bd06565765141868","type":"moment","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"MMMM D, YYYY","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"MMMM D, YYYY","locale":"en-US","output":"payload","outputType":"msg","outTz":"Africa/Abidjan","x":460,"y":860,"wires":[["898b23fa51f95edf"]]},{"id":"898b23fa51f95edf","type":"debug","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":860,"wires":[]},{"id":"f734d9e8979b20b2","type":"inject","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":920,"wires":[["f3a3a5a9974816d3","d5f3d8aeaaeffa7d","bd06565765141868"]]},{"id":"f3a3a5a9974816d3","type":"moment","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"MMMM D, YYYY [at] h:mm A","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"MMMM D, YYYY [at] h:mm A","locale":"en-US","output":"payload","outputType":"msg","outTz":"Africa/Abidjan","x":510,"y":920,"wires":[["2de95300ee070276"]]},{"id":"2de95300ee070276","type":"debug","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":920,"wires":[]},{"id":"d5f3d8aeaaeffa7d","type":"moment","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"fromNow","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"fromNow","locale":"en-US","output":"payload","outputType":"msg","outTz":"Africa/Abidjan","x":430,"y":980,"wires":[["b713b196b48c62d3"]]},{"id":"b713b196b48c62d3","type":"debug","z":"d7101f3a4d45deed","g":"f019c2f5ed9d8104","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":980,"wires":[]},{"id":"1699577150167eb5","type":"group","z":"d7101f3a4d45deed","g":"1e8a1110d36d3f33","name":"JSONata Formatting","style":{"label":true},"nodes":["678f13a9fad9c397","cf810cbd301fddb0","9443cb33ea42e25b","255b135032862816","2d3b9aee8b0ebe5b"],"x":134,"y":1039,"w":752,"h":142},{"id":"678f13a9fad9c397","type":"inject","z":"d7101f3a4d45deed","g":"1699577150167eb5","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":1120,"wires":[["cf810cbd301fddb0","2d3b9aee8b0ebe5b"]]},{"id":"cf810cbd301fddb0","type":"change","z":"d7101f3a4d45deed","g":"1699577150167eb5","name":"$fromMillis(payload, '[M]/[D]/[Y]')","rules":[{"t":"set","p":"payload","pt":"msg","to":"$fromMillis(payload, '[M]/[D]/[Y]')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":1080,"wires":[["9443cb33ea42e25b"]]},{"id":"9443cb33ea42e25b","type":"debug","z":"d7101f3a4d45deed","g":"1699577150167eb5","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1080,"wires":[]},{"id":"255b135032862816","type":"debug","z":"d7101f3a4d45deed","g":"1699577150167eb5","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1140,"wires":[]},{"id":"2d3b9aee8b0ebe5b","type":"change","z":"d7101f3a4d45deed","g":"1699577150167eb5","name":"$fromMillis(payload, '[h]:[m01] [P]')","rules":[{"t":"set","p":"payload","pt":"msg","to":"$fromMillis(payload, '[h]:[m01] [P]')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":1140,"wires":[["255b135032862816"]]},{"id":"5e97a86213b906bf","type":"global-config","env":[],"modules":{"node-red-contrib-moment":"5.0.0"}}]
-{% endrenderFlow %}
+```
+::
## Handling Time Zones
@@ -226,9 +229,11 @@ $fromMillis(payload, '[M]/[D]/[Y] [h]:[m01] [P]', '-0500')
The offset is a string like `-0500` (5 hours behind UTC). This works, but you have to know the offset and manage daylight saving time yourself. The **Date/Time Formatter** node handles all of that automatically.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"894fb9d3ddfa14d7","type":"group","z":"d7101f3a4d45deed","name":"Handling Time Zones","style":{"label":true},"nodes":["4d735b1f71f79189","0c31bb975d166128"],"x":108,"y":1233,"w":804,"h":474},{"id":"4d735b1f71f79189","type":"group","z":"d7101f3a4d45deed","g":"894fb9d3ddfa14d7","name":"Converting to a Different Timezone Using Moment nodes","style":{"label":true},"nodes":["995cf0548ac66af1","963db1d838c1a34d","faefd25e268f68e9","9259ebfd137a16b0","32f2b829e7a6de84","6a4a272401d45e61","48bf3927e175904c"],"x":134,"y":1259,"w":752,"h":202},{"id":"995cf0548ac66af1","type":"inject","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":1360,"wires":[["963db1d838c1a34d","6a4a272401d45e61","48bf3927e175904c"]]},{"id":"963db1d838c1a34d","type":"moment","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"America/New_York","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"MMMM D, YYYY h:mm A z","locale":"en-US","output":"payload","outputType":"msg","outTz":"America/New_York","x":470,"y":1300,"wires":[["faefd25e268f68e9"]]},{"id":"faefd25e268f68e9","type":"debug","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1300,"wires":[]},{"id":"9259ebfd137a16b0","type":"debug","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1360,"wires":[]},{"id":"32f2b829e7a6de84","type":"debug","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1420,"wires":[]},{"id":"6a4a272401d45e61","type":"moment","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"Europe/London","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"MMMM D, YYYY h:mm A z","locale":"en-US","output":"payload","outputType":"msg","outTz":"Europe/London","x":460,"y":1360,"wires":[["9259ebfd137a16b0"]]},{"id":"48bf3927e175904c","type":"moment","z":"d7101f3a4d45deed","g":"4d735b1f71f79189","name":"Asia/Tokyo","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":0,"adjType":"days","adjDir":"add","format":"MMMM D, YYYY h:mm A z","locale":"en-US","output":"payload","outputType":"msg","outTz":"Asia/Tokyo","x":440,"y":1420,"wires":[["32f2b829e7a6de84"]]},{"id":"0c31bb975d166128","type":"group","z":"d7101f3a4d45deed","g":"894fb9d3ddfa14d7","name":"Converting to a Different Timezone Using JSONata","style":{"label":true},"nodes":["ee7822f24a2792cb","0a006c9e87656cfc","31122b7227db8ce7","c62c7e7b3b450e85","6dfde983c76894c3","74e37a7cc2080238","f0c786e6db30ffad"],"x":134,"y":1479,"w":752,"h":202},{"id":"ee7822f24a2792cb","type":"inject","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":1580,"wires":[["6dfde983c76894c3","74e37a7cc2080238","f0c786e6db30ffad"]]},{"id":"0a006c9e87656cfc","type":"debug","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1520,"wires":[]},{"id":"31122b7227db8ce7","type":"debug","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1580,"wires":[]},{"id":"c62c7e7b3b450e85","type":"debug","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":1640,"wires":[]},{"id":"6dfde983c76894c3","type":"change","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"America/New_York ( Winter )","rules":[{"t":"set","p":"payload","pt":"msg","to":"$fromMillis(payload, '[M]/[D]/[Y] [h]:[m01] [P]', '-0500')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":1520,"wires":[["0a006c9e87656cfc"]]},{"id":"74e37a7cc2080238","type":"change","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"Europe/London ( Winter )","rules":[{"t":"set","p":"payload","pt":"msg","to":"$fromMillis(payload, '[M]/[D]/[Y] [h]:[m01] [P]', '+0000')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":1580,"wires":[["31122b7227db8ce7"]]},{"id":"f0c786e6db30ffad","type":"change","z":"d7101f3a4d45deed","g":"0c31bb975d166128","name":"Asia/Tokyo ( Winter )","rules":[{"t":"set","p":"payload","pt":"msg","to":"$fromMillis(payload, '[M]/[D]/[Y] [h]:[m01] [P]', '+0900')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":1640,"wires":[["c62c7e7b3b450e85"]]},{"id":"dcb2806bdd099173","type":"global-config","env":[],"modules":{"node-red-contrib-moment":"5.0.0"}}]
-{% endrenderFlow %}
+```
+::
## Doing Math with Dates
@@ -312,6 +317,8 @@ This example calculates the difference between a timestamp seven days ago and th
Hit the **Inject** button. The **Debug** tab will show the number of days difference (**7**).
-{% renderFlow %}
+::render-flow
+```json
[{"id":"48b48dea5aef0701","type":"group","z":"d7101f3a4d45deed","name":"Doing Math with Dates","style":{"label":true},"nodes":["a2137766a67faf67","bb370162520e95d7"],"x":108,"y":1733,"w":964,"h":254},{"id":"a2137766a67faf67","type":"group","z":"d7101f3a4d45deed","g":"48b48dea5aef0701","name":"Using Moment nodes","style":{"label":true},"nodes":["aa71711160b1b545","f76e05557f807562","bfd33b878fefe852"],"x":134,"y":1759,"w":912,"h":82},{"id":"aa71711160b1b545","type":"inject","z":"d7101f3a4d45deed","g":"a2137766a67faf67","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":1800,"wires":[["f76e05557f807562"]]},{"id":"f76e05557f807562","type":"moment","z":"d7101f3a4d45deed","g":"a2137766a67faf67","name":"+ 1 days","topic":"","input":"payload","inputType":"msg","inTz":"Africa/Abidjan","adjAmount":"1","adjType":"days","adjDir":"add","format":"YYYY-MM-DD","locale":"en-US","output":"payload","outputType":"msg","outTz":"Africa/Abidjan","x":430,"y":1800,"wires":[["bfd33b878fefe852"]]},{"id":"bfd33b878fefe852","type":"debug","z":"d7101f3a4d45deed","g":"a2137766a67faf67","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":940,"y":1800,"wires":[]},{"id":"bb370162520e95d7","type":"group","z":"d7101f3a4d45deed","g":"48b48dea5aef0701","name":"Using JSONata","style":{"label":true},"nodes":["551b26f1bfda2d88","4881ffafeb5da64c","82c0370128a1f80d","29f632a5c68ecc55"],"x":134,"y":1879,"w":912,"h":82},{"id":"551b26f1bfda2d88","type":"inject","z":"d7101f3a4d45deed","g":"bb370162520e95d7","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":1920,"wires":[["82c0370128a1f80d"]]},{"id":"4881ffafeb5da64c","type":"debug","z":"d7101f3a4d45deed","g":"bb370162520e95d7","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"days_difference","targetType":"msg","statusVal":"","statusType":"auto","x":940,"y":1920,"wires":[]},{"id":"82c0370128a1f80d","type":"change","z":"d7101f3a4d45deed","g":"bb370162520e95d7","name":"Set Start and End Time","rules":[{"t":"move","p":"payload","pt":"msg","to":"end_time","tot":"msg"},{"t":"set","p":"start_time","pt":"msg","to":"msg.end_time - (7 * 86400000)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":1920,"wires":[["29f632a5c68ecc55"]]},{"id":"29f632a5c68ecc55","type":"change","z":"d7101f3a4d45deed","g":"bb370162520e95d7","name":"Difference in Days","rules":[{"t":"set","p":"days_difference","pt":"msg","to":"(msg.end_time - msg.start_time) / 86400000","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1920,"wires":[["4881ffafeb5da64c"]]},{"id":"ccc081e4ccaba879","type":"global-config","env":[],"modules":{"node-red-contrib-moment":"5.0.0"}}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/getting-started/editor/index.md b/nuxt/content-guides/node-red/getting-started/editor/README.md
similarity index 82%
rename from src/node-red/getting-started/editor/index.md
rename to nuxt/content-guides/node-red/getting-started/editor/README.md
index 27862cacb3..e5d2be814f 100644
--- a/src/node-red/getting-started/editor/index.md
+++ b/nuxt/content-guides/node-red/getting-started/editor/README.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: Editor
- order: 1
- parent: Getting Started
+title: Getting Started with the Node-RED Editor
+metaTitle: "Getting Started with the Node-RED Editor"
+navTitle: Editor
+navOrder: 1
meta:
- title: Getting Started with the Node-RED Editor
- description: Learn about the powerful features of Node-RED Editor.
+ description: Learn about the powerful features of Node-RED Editor.
keywords: node red editor, node-red editor, nodered flow, node-red flows, nodered workspace
---
-# {{meta.title}}
+# Getting Started with the Node-RED Editor
The Node-RED Editor is one of the most essential components of Node-RED. As the main focus of Node-RED is to enable visual programming, the editor provides a graphical interface that allows users to create, configure, and manage flows easily.
diff --git a/src/node-red/getting-started/editor/header.md b/nuxt/content-guides/node-red/getting-started/editor/header.md
similarity index 97%
rename from src/node-red/getting-started/editor/header.md
rename to nuxt/content-guides/node-red/getting-started/editor/header.md
index 0a0301f9e7..bfab10e44f 100644
--- a/src/node-red/getting-started/editor/header.md
+++ b/nuxt/content-guides/node-red/getting-started/editor/header.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: Header
- parent: Editor
+title: Node-RED Editor Header component
+metaTitle: "Node-RED Editor Header component"
+navTitle: Header
+navOrder: 50
meta:
- title: Node-RED Editor Header component
- description: Explore the features available in the Node-RED Editor header component, essential for navigation and configuration.
+ description: Explore the features available in the Node-RED Editor header component, essential for navigation and configuration.
keywords: node-red, node-red editor
---
-# {{meta.title}}
+# Node-RED Editor Header component
The Node-RED editor header is a central component that facilitates navigation to Node-RED main settings, provides a deploy button for executing flows, and access to the user profile.
@@ -160,7 +160,7 @@ Clicking on this option will open the sidebars config tab that will allow you to
{data-zoomable}
-This option allows you to manage the [flow](/node-red/terminology/#flow) tabs.
+This option allows you to manage the [flow](/docs/node-red/terminology/#flow) tabs.
- **Add**: Adds a new flow tab.
- **Edit**: Edits the current flow tab.
@@ -170,7 +170,7 @@ This option allows you to manage the [flow](/node-red/terminology/#flow) tabs.
{data-zoomable}
-This option allows you to create the [subflow](/node-red/terminology/#subflow).
+This option allows you to create the [subflow](/docs/node-red/terminology/#subflow).
- **Create Subflow**: Creates a new subflow tab.
- **Selection to Subflow**: Converts the selected nodes into a subflow.
diff --git a/src/node-red/getting-started/editor/images/adding-nodes-to-group.webm b/nuxt/content-guides/node-red/getting-started/editor/images/adding-nodes-to-group.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/adding-nodes-to-group.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/adding-nodes-to-group.webm
diff --git a/src/node-red/getting-started/editor/images/creating-group.webm b/nuxt/content-guides/node-red/getting-started/editor/images/creating-group.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/creating-group.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/creating-group.webm
diff --git a/src/node-red/getting-started/editor/images/deleting-wires.webm b/nuxt/content-guides/node-red/getting-started/editor/images/deleting-wires.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/deleting-wires.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/deleting-wires.webm
diff --git a/src/node-red/getting-started/editor/images/deploy-button-active.png b/nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-active.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/deploy-button-active.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-active.png
diff --git a/src/node-red/getting-started/editor/images/deploy-button-inactive.png b/nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-inactive.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/deploy-button-inactive.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-inactive.png
diff --git a/src/node-red/getting-started/editor/images/deploy-button-options.png b/nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-options.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/deploy-button-options.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/deploy-button-options.png
diff --git a/src/node-red/getting-started/editor/images/detaching-nodes-while-keeping-wires.webm b/nuxt/content-guides/node-red/getting-started/editor/images/detaching-nodes-while-keeping-wires.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/detaching-nodes-while-keeping-wires.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/detaching-nodes-while-keeping-wires.webm
diff --git a/src/node-red/getting-started/editor/images/editor-flow-tabs.png b/nuxt/content-guides/node-red/getting-started/editor/images/editor-flow-tabs.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/editor-flow-tabs.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/editor-flow-tabs.png
diff --git a/src/node-red/getting-started/editor/images/editor-workspace.png b/nuxt/content-guides/node-red/getting-started/editor/images/editor-workspace.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/editor-workspace.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/editor-workspace.png
diff --git a/src/node-red/getting-started/editor/images/environment-variables-options.png b/nuxt/content-guides/node-red/getting-started/editor/images/environment-variables-options.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/environment-variables-options.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/environment-variables-options.png
diff --git a/src/node-red/getting-started/editor/images/group-description.png b/nuxt/content-guides/node-red/getting-started/editor/images/group-description.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/group-description.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/group-description.png
diff --git a/src/node-red/getting-started/editor/images/group-level-env.png b/nuxt/content-guides/node-red/getting-started/editor/images/group-level-env.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/group-level-env.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/group-level-env.png
diff --git a/src/node-red/getting-started/editor/images/group-merging-groups.webm b/nuxt/content-guides/node-red/getting-started/editor/images/group-merging-groups.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/group-merging-groups.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/group-merging-groups.webm
diff --git a/src/node-red/getting-started/editor/images/group-properties-edit.png b/nuxt/content-guides/node-red/getting-started/editor/images/group-properties-edit.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/group-properties-edit.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/group-properties-edit.png
diff --git a/src/node-red/getting-started/editor/images/group-properties.png b/nuxt/content-guides/node-red/getting-started/editor/images/group-properties.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/group-properties.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/group-properties.png
diff --git a/src/node-red/getting-started/editor/images/group.png b/nuxt/content-guides/node-red/getting-started/editor/images/group.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/group.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/group.png
diff --git a/src/node-red/getting-started/editor/images/header-flowfuse-instance.png b/nuxt/content-guides/node-red/getting-started/editor/images/header-flowfuse-instance.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/header-flowfuse-instance.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/header-flowfuse-instance.png
diff --git a/src/node-red/getting-started/editor/images/header.png b/nuxt/content-guides/node-red/getting-started/editor/images/header.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/header.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/header.png
diff --git a/src/node-red/getting-started/editor/images/lasso-tool.webm b/nuxt/content-guides/node-red/getting-started/editor/images/lasso-tool.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/lasso-tool.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/lasso-tool.webm
diff --git a/src/node-red/getting-started/editor/images/main-menu-arrange-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-arrange-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-arrange-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-arrange-option.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-configuration-nodes.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-configuration-nodes.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-configuration-nodes.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-configuration-nodes.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-edit-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-edit-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-edit-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-edit-option.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-export-local.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export-local.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-export-local.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export-local.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-export-team.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export-team.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-export-team.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export-team.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-export.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-export.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-export.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-flows.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-flows.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-flows.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-flows.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-groups.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-groups.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-groups.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-groups.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-import.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-import.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-import.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-import.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-search-flow-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-search-flow-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-search-flow-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-search-flow-option.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-search-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-search-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-search-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-search-tab.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-settings.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-settings.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-settings.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-settings.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-subflows.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-subflows.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-subflows.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-subflows.png
diff --git a/src/node-red/getting-started/editor/images/main-menu-view-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/main-menu-view-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/main-menu-view-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/main-menu-view-option.png
diff --git a/src/node-red/getting-started/editor/images/moving-multiple-wires.webm b/nuxt/content-guides/node-red/getting-started/editor/images/moving-multiple-wires.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/moving-multiple-wires.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/moving-multiple-wires.webm
diff --git a/src/node-red/getting-started/editor/images/moving-wire.webm b/nuxt/content-guides/node-red/getting-started/editor/images/moving-wire.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/moving-wire.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/moving-wire.webm
diff --git a/src/node-red/getting-started/editor/images/mqtt-in-node-status.png b/nuxt/content-guides/node-red/getting-started/editor/images/mqtt-in-node-status.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/mqtt-in-node-status.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/mqtt-in-node-status.png
diff --git a/src/node-red/getting-started/editor/images/node-add-config-node.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-add-config-node.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-add-config-node.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-add-config-node.png
diff --git a/src/node-red/getting-started/editor/images/node-appearance-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-appearance-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-appearance-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-appearance-tab.png
diff --git a/src/node-red/getting-started/editor/images/node-buttons.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-buttons.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-buttons.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-buttons.png
diff --git a/src/node-red/getting-started/editor/images/node-description-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-description-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-description-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-description-tab.png
diff --git a/src/node-red/getting-started/editor/images/node-edit-properties-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-edit-properties-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-edit-properties-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-edit-properties-tab.png
diff --git a/src/node-red/getting-started/editor/images/node-enable-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-enable-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-enable-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-enable-option.png
diff --git a/src/node-red/getting-started/editor/images/node-help.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-help.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-help.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-help.png
diff --git a/src/node-red/getting-started/editor/images/node-indicating-error.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-error.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-indicating-error.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-error.png
diff --git a/src/node-red/getting-started/editor/images/node-indicating-how-many-nodes-using-config-node.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-how-many-nodes-using-config-node.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-indicating-how-many-nodes-using-config-node.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-how-many-nodes-using-config-node.png
diff --git a/src/node-red/getting-started/editor/images/node-indicating-undeployed-changes.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-undeployed-changes.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-indicating-undeployed-changes.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-indicating-undeployed-changes.png
diff --git a/src/node-red/getting-started/editor/images/node-input-ouput-port.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-input-ouput-port.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-input-ouput-port.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-input-ouput-port.png
diff --git a/src/node-red/getting-started/editor/images/node-quick-add-dialog.webm b/nuxt/content-guides/node-red/getting-started/editor/images/node-quick-add-dialog.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-quick-add-dialog.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-quick-add-dialog.webm
diff --git a/src/node-red/getting-started/editor/images/node-red-editor-palette.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-editor-palette.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-editor-palette.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-editor-palette.png
diff --git a/src/node-red/getting-started/editor/images/node-red-editor-window.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-editor-window.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-editor-window.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-editor-window.png
diff --git a/src/node-red/getting-started/editor/images/node-red-export-local-library.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-export-local-library.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-export-local-library.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-export-local-library.png
diff --git a/src/node-red/getting-started/editor/images/node-red-node.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-node.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-node.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-node.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-category.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-category.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-category.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-category.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-collapse-expand.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-collapse-expand.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-collapse-expand.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-collapse-expand.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-export-scope.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-export-scope.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-export-scope.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-export-scope.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-json.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-json.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-json.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-json.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-search.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-search.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-search.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-search.png
diff --git a/src/node-red/getting-started/editor/images/node-red-palette-toggle.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-toggle.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-palette-toggle.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-palette-toggle.png
diff --git a/src/node-red/getting-started/editor/images/node-red-pallete-manger-nodes-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-pallete-manger-nodes-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-pallete-manger-nodes-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-pallete-manger-nodes-option.png
diff --git a/src/node-red/getting-started/editor/images/node-red-sidebar.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-red-sidebar.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-red-sidebar.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-red-sidebar.png
diff --git a/src/node-red/getting-started/editor/images/node-wire.png b/nuxt/content-guides/node-red/getting-started/editor/images/node-wire.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/node-wire.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/node-wire.png
diff --git a/src/node-red/getting-started/editor/images/pallete-manger-filter-and-sort-options.png b/nuxt/content-guides/node-red/getting-started/editor/images/pallete-manger-filter-and-sort-options.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/pallete-manger-filter-and-sort-options.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/pallete-manger-filter-and-sort-options.png
diff --git a/src/node-red/getting-started/editor/images/removing-node-from-group.webm b/nuxt/content-guides/node-red/getting-started/editor/images/removing-node-from-group.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/removing-node-from-group.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/removing-node-from-group.webm
diff --git a/src/node-red/getting-started/editor/images/removing-nodes-from-group.webm b/nuxt/content-guides/node-red/getting-started/editor/images/removing-nodes-from-group.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/removing-nodes-from-group.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/removing-nodes-from-group.webm
diff --git a/src/node-red/getting-started/editor/images/removing-nodes-while-keeping-wires.webm b/nuxt/content-guides/node-red/getting-started/editor/images/removing-nodes-while-keeping-wires.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/removing-nodes-while-keeping-wires.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/removing-nodes-while-keeping-wires.webm
diff --git a/src/node-red/getting-started/editor/images/selecting-connected-nodes.webm b/nuxt/content-guides/node-red/getting-started/editor/images/selecting-connected-nodes.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/selecting-connected-nodes.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/selecting-connected-nodes.webm
diff --git a/src/node-red/getting-started/editor/images/selecting-downward-connected-nodes.webm b/nuxt/content-guides/node-red/getting-started/editor/images/selecting-downward-connected-nodes.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/selecting-downward-connected-nodes.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/selecting-downward-connected-nodes.webm
diff --git a/src/node-red/getting-started/editor/images/selecting-flows.webm b/nuxt/content-guides/node-red/getting-started/editor/images/selecting-flows.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/selecting-flows.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/selecting-flows.webm
diff --git a/src/node-red/getting-started/editor/images/selecting-upward-connected-nodes.webm b/nuxt/content-guides/node-red/getting-started/editor/images/selecting-upward-connected-nodes.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/selecting-upward-connected-nodes.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/selecting-upward-connected-nodes.webm
diff --git a/src/node-red/getting-started/editor/images/slicing-wires.webm b/nuxt/content-guides/node-red/getting-started/editor/images/slicing-wires.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/slicing-wires.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/slicing-wires.webm
diff --git a/src/node-red/getting-started/editor/images/subflow-appearance-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-appearance-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-appearance-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-appearance-tab.png
diff --git a/src/node-red/getting-started/editor/images/subflow-converting-nodes-to-subflow.webm b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-converting-nodes-to-subflow.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-converting-nodes-to-subflow.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-converting-nodes-to-subflow.webm
diff --git a/src/node-red/getting-started/editor/images/subflow-custom-properties.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-custom-properties.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-custom-properties.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-custom-properties.png
diff --git a/src/node-red/getting-started/editor/images/subflow-delete-option.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-delete-option.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-delete-option.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-delete-option.png
diff --git a/src/node-red/getting-started/editor/images/subflow-editing-properties.webm b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-editing-properties.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-editing-properties.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-editing-properties.webm
diff --git a/src/node-red/getting-started/editor/images/subflow-input-output.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-input-output.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-input-output.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-input-output.png
diff --git a/src/node-red/getting-started/editor/images/subflow-module-tab.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-module-tab.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-module-tab.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-module-tab.png
diff --git a/src/node-red/getting-started/editor/images/subflow-node.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-node.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-node.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-node.png
diff --git a/src/node-red/getting-started/editor/images/subflow-property-description.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-property-description.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-property-description.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-property-description.png
diff --git a/src/node-red/getting-started/editor/images/subflow-status-node.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-status-node.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-status-node.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-status-node.png
diff --git a/src/node-red/getting-started/editor/images/subflow-ui-preview.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-ui-preview.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-ui-preview.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-ui-preview.png
diff --git a/src/node-red/getting-started/editor/images/subflow-window.png b/nuxt/content-guides/node-red/getting-started/editor/images/subflow-window.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/subflow-window.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/subflow-window.png
diff --git a/src/node-red/getting-started/editor/images/wiring-nodes-together.webm b/nuxt/content-guides/node-red/getting-started/editor/images/wiring-nodes-together.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/wiring-nodes-together.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/wiring-nodes-together.webm
diff --git a/src/node-red/getting-started/editor/images/workspace-add-flow.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-add-flow.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-add-flow.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-add-flow.png
diff --git a/src/node-red/getting-started/editor/images/workspace-delete-flow-dialog.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-delete-flow-dialog.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-delete-flow-dialog.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-delete-flow-dialog.png
diff --git a/src/node-red/getting-started/editor/images/workspace-delete-flow.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-delete-flow.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-delete-flow.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-delete-flow.png
diff --git a/src/node-red/getting-started/editor/images/workspace-disable-enable-flow.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-disable-enable-flow.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-disable-enable-flow.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-disable-enable-flow.png
diff --git a/src/node-red/getting-started/editor/images/workspace-enable-disable-flow.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-enable-disable-flow.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-enable-disable-flow.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-enable-disable-flow.png
diff --git a/src/node-red/getting-started/editor/images/workspace-flow-edit.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-flow-edit.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-flow-edit.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-flow-edit.png
diff --git a/src/node-red/getting-started/editor/images/workspace-navigator-tool.webm b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-navigator-tool.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-navigator-tool.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-navigator-tool.webm
diff --git a/src/node-red/getting-started/editor/images/workspace-reordering-flow.webm b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-reordering-flow.webm
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-reordering-flow.webm
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-reordering-flow.webm
diff --git a/src/node-red/getting-started/editor/images/workspace-search-tool.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-search-tool.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-search-tool.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-search-tool.png
diff --git a/src/node-red/getting-started/editor/images/workspace-view-tool.png b/nuxt/content-guides/node-red/getting-started/editor/images/workspace-view-tool.png
similarity index 100%
rename from src/node-red/getting-started/editor/images/workspace-view-tool.png
rename to nuxt/content-guides/node-red/getting-started/editor/images/workspace-view-tool.png
diff --git a/src/node-red/getting-started/editor/palette.md b/nuxt/content-guides/node-red/getting-started/editor/palette.md
similarity index 91%
rename from src/node-red/getting-started/editor/palette.md
rename to nuxt/content-guides/node-red/getting-started/editor/palette.md
index e3983cd54f..56c40bb7b4 100644
--- a/src/node-red/getting-started/editor/palette.md
+++ b/nuxt/content-guides/node-red/getting-started/editor/palette.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: Palette
- parent: Editor
+title: Node-RED Editor Palette
+metaTitle: "Node-RED Editor Palette"
+navTitle: Palette
+navOrder: 50
meta:
- title: Node-RED Editor Palette
description: Explore the features available in the Node-RED Editor palette, essential for navigation and configuration.
keywords: node-red, node-red editor
---
-# {{meta.title}}
+# Node-RED Editor Palette
The Palette is the left sidebar that contains all available nodes, including core nodes and third-party nodes that are installed.
@@ -40,4 +40,4 @@ Clicking on the down arrow icon will expand all categories back as default.
{data-zoomable}
-Clicking this button hides the palette sidebar. To show it again, click on the button once more.
\ No newline at end of file
+Clicking this button hides the palette sidebar. To show it again, click on the button once more.
diff --git a/src/node-red/getting-started/editor/sidebar.md b/nuxt/content-guides/node-red/getting-started/editor/sidebar.md
similarity index 98%
rename from src/node-red/getting-started/editor/sidebar.md
rename to nuxt/content-guides/node-red/getting-started/editor/sidebar.md
index e28746cd33..b2b83c1165 100644
--- a/src/node-red/getting-started/editor/sidebar.md
+++ b/nuxt/content-guides/node-red/getting-started/editor/sidebar.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: Sidebar
- parent: Editor
+title: Node-RED Editor Sidebar component
+metaTitle: "Node-RED Editor Sidebar component"
+navTitle: Sidebar
+navOrder: 50
meta:
- title: Node-RED Editor Sidebar component
description: Explore the features available in the Node-RED Editor sidebar component.
keywords: node-red, node-red editor, sidebar
---
-# {{meta.title}}
+# Node-RED Editor Sidebar component
The sidebar is located on the right side of your Node-RED Editor. It contains a collection of different tools that make Node-RED easier to use, such as managing nodes, configuration, context storage, and more.
@@ -160,4 +160,4 @@ To resize the sidebar, hover the mouse over the sidebar's border until the curso
To switch between panels, click the expand icon in the top-right corner. This will open a menu with all the available panels.
-Alternatively, you can click on the small boxes with different icons at the top.
\ No newline at end of file
+Alternatively, you can click on the small boxes with different icons at the top.
diff --git a/src/node-red/getting-started/editor/workspace.md b/nuxt/content-guides/node-red/getting-started/editor/workspace.md
similarity index 89%
rename from src/node-red/getting-started/editor/workspace.md
rename to nuxt/content-guides/node-red/getting-started/editor/workspace.md
index ba6a0c58d8..958c15f26f 100644
--- a/src/node-red/getting-started/editor/workspace.md
+++ b/nuxt/content-guides/node-red/getting-started/editor/workspace.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: Workspace
- parent: Editor
+title: Node-RED Editor Workspace
+metaTitle: "Node-RED Editor Workspace"
+navTitle: Workspace
+navOrder: 50
meta:
- title: Node-RED Editor Workspace
description: Explore the features available in the Node-RED Editor workspace component
keywords: node-red, node-red editor, workspace
---
-# {{meta.title}}
+# Node-RED Editor Workspace
The workspace is the main area in the editor where you build application flows by dropping nodes from the palette.
@@ -20,7 +20,7 @@ The workspace is the main area in the editor where you build application flows b
The workspace provides view tools at the footer in the right corner. This includes zoom in (`Ctrl` + `+`) and zoom out (`Ctrl` + `-`) buttons to control the view of the workspace and reset the zoom level to its default.
-
+
Additionally, it provides a view navigator that allows you to see a scaled-down view of the entire workspace. In this view, you can also see the currently visible area of the workspace in the editor. To jump to a specific workspace area, click on that area in the view navigator.
@@ -74,7 +74,7 @@ Alternatively, right-click on the flow tab and select "Disable/Enable" from the
### Reordering Flows
-
+
Flows can be reordered by clicking and dragging the flow tab to the desired position. More options for the flow tab menu can be accessed by clicking on the top-right dropdown arrow icon.
@@ -98,7 +98,7 @@ It will create the subflow window like a flow tab for you.
### Editing a Subflow
-
+
To open the subflow edit dialog, double-click on the subflow node, then click on the "edit template properties". You can give the name for that subflow, add the description by clicking on the top-right
@@ -130,7 +130,7 @@ To delete the subflow, click on the "delete subflow" button at the top of the su
### Converting Nodes into a Subflow
-
+
If you have nodes on the workspace and you want to create a subflow of them, you can select them by pressing the left mouse key and drawing a rectangle around them. Then click on subflow -> selection to subflow in the main menu.
@@ -184,7 +184,7 @@ Nodes can be added from the [Node-RED palette](./palette.md) by dragging them on
Node-RED Editor provides a quick and easy way to add nodes via the palette:
-
+
- Press `Ctrl` or `Command` and click on the workspace.
- Select the desired node from the dialog, which contains all available nodes from the main node palette.
@@ -253,7 +253,7 @@ The "wires" refer to the connections that link nodes together to define the flow
### Wiring Nodes Together
-
+
To connect the nodes using the wires, left-click on the node's output port and drag the wire to the destination input port. Additionally, if you press the `Ctrl`/`Command` and mouse left key on the input or output port you will not need to hold the left mouse key or any other button to drag the wire. To connect it to the destination port, press the left mouse key on destination port. If the `Ctrl`/`Command` key remains pressed after connecting to the destination port, and if that port's node has an output port, a new wire will be dragged.
@@ -261,23 +261,23 @@ The wires can be connected from the input port to the output port, not from the
### Deleting Wires
-
+
To delete wires, click the left mouse button to select the first wire. To select multiple wires, press and hold the `Ctrl\Command` key while clicking each wire with the left mouse button. If you use only the left mouse button, you can select only one wire at a time. After selecting the wires, press the 'delete' or 'backspace' key to delete them.
### Moving Wires
-
+
To disconnect the wire from the port, select the wire by clicking on it. Then press and hold the `Shift` key while the left mouse key is pressed on the port. When the mouse is dragged you'll see the wire disconnects from the port and can be connected to another port.
-
+
If a port has multiple wires connected to it, if none of them are selected when the button is pressed with the Shift key held, all of the wires will move.
### Slicing Wires
-
+
Wires can also be removed by slicing through them. You can do this by holding the `Alt`/`Option` key and then drawing the line for slicing by holding the left mouse key.
@@ -285,13 +285,13 @@ Wires can also be removed by slicing through them. You can do this by holding th
#### Keeping Wire While Deleting Node
-
+
To do that, press and hold the `Ctrl`/`Command` key, select the node by clicking the left mouse key, and then press the "delete" or "backspace" button.
#### Detaching Node from Wires
-
+
To use this option, you have to set the [keyboard shortcut](./header.md#keyboard-shortcuts) for the "detach-selected-nodes" action.
@@ -303,7 +303,7 @@ In Node-RED, groups can be created for better organization, containing a single
### Creating a Flow Group
-
+
To create a flow group, select nodes (by holding the Ctrl key or drawing a rectangle around them). Navigate to `Groups -> Group selection` in the main menu or press `Ctrl + Shift + G`.
@@ -329,25 +329,25 @@ To add a description to the group, double-click on it. Select the third option f
### Adding Nodes to a Group
-
+
To add nodes to an existing group, drag and drop them into the group. This can be done one node at a time. Groups can also be nested within each other in the same manner.
### Removing Nodes from a Group
-
+
To remove nodes from a group, select the nodes and navigate to `Groups -> Remove selection` in the main menu. Similarly, remove a group from another group. Alternatively, click on a node, hold the 'Alt' key, and drag it outside of the group.
### Merging Groups
-
+
To merge multiple groups into a single group, select the groups. Go to `Main Menu -> Groups -> Merge selection`.
### Ungrouping Selected Nodes
-
+
To ungroup nodes from a group, select the nodes. Go to `Main Menu -> Groups -> Ungroup selection`.
@@ -359,30 +359,30 @@ A node can be selected or deselected by clicking on it. To select multiple nodes
### Lasso Tool
-
+
Node-RED provides a lasso tool to make selection faster. To use the lasso tool, press the left mouse key and drag the cursor, then you can select multiple nodes by drawing a rectangle around them.
### Selecting Connected Nodes
-
+
To select all connected nodes to a specific node, press the `Shift` button and click on the middle of that node.
### Selecting All Upstream Nodes
-
+
To select all of the connected nodes that are before that specific node, press the `Shift` button and while holding it click on the left part of that node.
### Selecting All Downstream Nodes
-
+
To select all of the connected nodes that are after that specific node, press the `Shift` button and while holding it click on the right part of that node.
### Selecting Flows
-
+
To select the flow tabs, press the `Ctrl/Command` key and while holding it click on the flow tab you want to select. Now you can then delete, export, or copy them collectively.
diff --git a/src/node-red/getting-started/images/adding-breakpoints.webm b/nuxt/content-guides/node-red/getting-started/images/adding-breakpoints.webm
similarity index 100%
rename from src/node-red/getting-started/images/adding-breakpoints.webm
rename to nuxt/content-guides/node-red/getting-started/images/adding-breakpoints.webm
diff --git a/src/node-red/getting-started/images/breakpoint-debugging.webm b/nuxt/content-guides/node-red/getting-started/images/breakpoint-debugging.webm
similarity index 100%
rename from src/node-red/getting-started/images/breakpoint-debugging.webm
rename to nuxt/content-guides/node-red/getting-started/images/breakpoint-debugging.webm
diff --git a/src/node-red/getting-started/images/breakpoints-section.png b/nuxt/content-guides/node-red/getting-started/images/breakpoints-section.png
similarity index 100%
rename from src/node-red/getting-started/images/breakpoints-section.png
rename to nuxt/content-guides/node-red/getting-started/images/breakpoints-section.png
diff --git a/src/node-red/getting-started/images/debugger-controls.png b/nuxt/content-guides/node-red/getting-started/images/debugger-controls.png
similarity index 100%
rename from src/node-red/getting-started/images/debugger-controls.png
rename to nuxt/content-guides/node-red/getting-started/images/debugger-controls.png
diff --git a/src/node-red/getting-started/images/disable-enable-button.png b/nuxt/content-guides/node-red/getting-started/images/disable-enable-button.png
similarity index 100%
rename from src/node-red/getting-started/images/disable-enable-button.png
rename to nuxt/content-guides/node-red/getting-started/images/disable-enable-button.png
diff --git a/src/node-red/getting-started/images/disabling-breakpoints.webm b/nuxt/content-guides/node-red/getting-started/images/disabling-breakpoints.webm
similarity index 100%
rename from src/node-red/getting-started/images/disabling-breakpoints.webm
rename to nuxt/content-guides/node-red/getting-started/images/disabling-breakpoints.webm
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-change-node.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-change-node.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-change-node.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-change-node.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-calculating-avg.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-calculating-avg.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-calculating-avg.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-calculating-avg.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-combining-node.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-combining-node.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-combining-node.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-join-node-combining-node.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-sort-node.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-sort-node.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-sort-node.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-sort-node.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-switch-node.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-switch-node.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-switch-node.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-data-with-node-red-switch-node.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-switch-node.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-switch-node.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-switch-node.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-switch-node.png
diff --git a/src/node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png b/nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png
similarity index 100%
rename from src/node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png
rename to nuxt/content-guides/node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png
diff --git a/src/node-red/getting-started/images/if-else-with-node-red.png b/nuxt/content-guides/node-red/getting-started/images/if-else-with-node-red.png
similarity index 100%
rename from src/node-red/getting-started/images/if-else-with-node-red.png
rename to nuxt/content-guides/node-red/getting-started/images/if-else-with-node-red.png
diff --git a/src/node-red/getting-started/images/message-section.png b/nuxt/content-guides/node-red/getting-started/images/message-section.png
similarity index 100%
rename from src/node-red/getting-started/images/message-section.png
rename to nuxt/content-guides/node-red/getting-started/images/message-section.png
diff --git a/src/node-red/getting-started/images/mistake-1-solution.webm b/nuxt/content-guides/node-red/getting-started/images/mistake-1-solution.webm
similarity index 100%
rename from src/node-red/getting-started/images/mistake-1-solution.webm
rename to nuxt/content-guides/node-red/getting-started/images/mistake-1-solution.webm
diff --git a/src/node-red/getting-started/images/mistake1.webm b/nuxt/content-guides/node-red/getting-started/images/mistake1.webm
similarity index 100%
rename from src/node-red/getting-started/images/mistake1.webm
rename to nuxt/content-guides/node-red/getting-started/images/mistake1.webm
diff --git a/src/node-red/getting-started/images/node-red-data-types.webm b/nuxt/content-guides/node-red/getting-started/images/node-red-data-types.webm
similarity index 100%
rename from src/node-red/getting-started/images/node-red-data-types.webm
rename to nuxt/content-guides/node-red/getting-started/images/node-red-data-types.webm
diff --git a/src/node-red/getting-started/images/node-red-instance-update.png b/nuxt/content-guides/node-red/getting-started/images/node-red-instance-update.png
similarity index 100%
rename from src/node-red/getting-started/images/node-red-instance-update.png
rename to nuxt/content-guides/node-red/getting-started/images/node-red-instance-update.png
diff --git a/src/node-red/getting-started/images/node-red-message-passing.webm b/nuxt/content-guides/node-red/getting-started/images/node-red-message-passing.webm
similarity index 100%
rename from src/node-red/getting-started/images/node-red-message-passing.webm
rename to nuxt/content-guides/node-red/getting-started/images/node-red-message-passing.webm
diff --git a/src/node-red/getting-started/images/proceeding-further-execution.webm b/nuxt/content-guides/node-red/getting-started/images/proceeding-further-execution.webm
similarity index 100%
rename from src/node-red/getting-started/images/proceeding-further-execution.webm
rename to nuxt/content-guides/node-red/getting-started/images/proceeding-further-execution.webm
diff --git a/src/node-red/getting-started/images/removing-breakpoints.webm b/nuxt/content-guides/node-red/getting-started/images/removing-breakpoints.webm
similarity index 100%
rename from src/node-red/getting-started/images/removing-breakpoints.webm
rename to nuxt/content-guides/node-red/getting-started/images/removing-breakpoints.webm
diff --git a/src/node-red/getting-started/images/schedule-update.png b/nuxt/content-guides/node-red/getting-started/images/schedule-update.png
similarity index 100%
rename from src/node-red/getting-started/images/schedule-update.png
rename to nuxt/content-guides/node-red/getting-started/images/schedule-update.png
diff --git a/src/node-red/getting-started/images/update-node-red-cta-1.png b/nuxt/content-guides/node-red/getting-started/images/update-node-red-cta-1.png
similarity index 100%
rename from src/node-red/getting-started/images/update-node-red-cta-1.png
rename to nuxt/content-guides/node-red/getting-started/images/update-node-red-cta-1.png
diff --git a/src/node-red/getting-started/library/index.md b/nuxt/content-guides/node-red/getting-started/library/README.md
similarity index 83%
rename from src/node-red/getting-started/library/index.md
rename to nuxt/content-guides/node-red/getting-started/library/README.md
index 2189eb298a..68e0f4fe04 100644
--- a/src/node-red/getting-started/library/index.md
+++ b/nuxt/content-guides/node-red/getting-started/library/README.md
@@ -1,13 +1,11 @@
---
+title: Node-RED Library – A Curated and Actively Maintained List of Nodes
metaTitle: "Node-RED Library: Curated List of Nodes"
-eleventyNavigation:
- key: Node-RED Library
- parent: Getting Started
- order: 3
+navTitle: Node-RED Library
+navOrder: 3
meta:
- title: Node-RED Library – A Curated and Actively Maintained List of Nodes
- description: Browse the Node-RED Library for community-built nodes and integrations. FlowFuse's curated catalog offers tested, documented, enterprise-ready solutions with professional support for critical deployments.
- keywords: node-red library, node-red nodes, node-red integrations, community nodes, node-red packages, custom nodes, node-red flows
+ description: Browse the Node-RED Library for community-built nodes and integrations. FlowFuse's curated catalog offers tested, documented, enterprise-ready solutions with professional support for critical deployments.
+ keywords: node-red library, node-red nodes, node-red integrations, community nodes, node-red packages, custom nodes, node-red flows
---
# Node-RED Library
@@ -47,7 +45,7 @@ To install nodes through the Node-RED editor:
5. Search for the required node
6. Click **Install** next to the package
-
+
Installed nodes appear in your palette immediately and are ready for use in your flows.
diff --git a/src/node-red/getting-started/library/images/installing-node-red-node.webm b/nuxt/content-guides/node-red/getting-started/library/images/installing-node-red-node.webm
similarity index 100%
rename from src/node-red/getting-started/library/images/installing-node-red-node.webm
rename to nuxt/content-guides/node-red/getting-started/library/images/installing-node-red-node.webm
diff --git a/src/node-red/getting-started/node-red-android.md b/nuxt/content-guides/node-red/getting-started/node-red-android.md
similarity index 96%
rename from src/node-red/getting-started/node-red-android.md
rename to nuxt/content-guides/node-red/getting-started/node-red-android.md
index a1e90b5bfb..f6920142ac 100644
--- a/src/node-red/getting-started/node-red-android.md
+++ b/nuxt/content-guides/node-red/getting-started/node-red-android.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: Node-RED On Android
- order: 4
- parent: Getting Started
+title: Installing Node-RED on Android
+metaTitle: "Installing Node-RED on Android"
+navTitle: Node-RED On Android
+navOrder: 4
meta:
- title: Installing Node-RED on Android
description: Learn how to install and run Node-RED on Android devices using Termux
keywords: node-red android, termux, android installation, mobile node-red
---
-# {{ meta.title }}
+# Installing Node-RED on Android
You can run Node-RED on Android devices using Termux, a terminal emulator and Linux environment app. This guide walks you through the installation process and helps you get Node-RED running on your Android phone or tablet.
diff --git a/src/node-red/getting-started/node-red-messages.md b/nuxt/content-guides/node-red/getting-started/node-red-messages.md
similarity index 95%
rename from src/node-red/getting-started/node-red-messages.md
rename to nuxt/content-guides/node-red/getting-started/node-red-messages.md
index 9eab49a2de..1bc7377930 100644
--- a/src/node-red/getting-started/node-red-messages.md
+++ b/nuxt/content-guides/node-red/getting-started/node-red-messages.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: Working with Messages
- order: 5
- parent: Getting Started
+title: Understanding Node-RED Messages
+metaTitle: "Understanding Node-RED Messages"
+navTitle: Working with Messages
+navOrder: 5
meta:
- title: Understanding Node-RED Messages
description: A comprehensive guide to working with Node-RED messages, ensuring error-free flows and optimized data handling.
keywords: msg.payload node red, node red message structure, node-red messages, node red msg.payload, msg.payload, node red msg.payload array
---
-# {{ meta.title }}
+# Understanding Node-RED Messages
Node-RED operates by passing messages between nodes to create dynamic IoT, automation, and data-processing workflows. Each message transports data that nodes read, modify, process, or analyze. Understanding message structure and handling is essential for building reliable flows. Poor message management can cause subtle bugs like data overwrites, infinite loops, or system crashes.
@@ -19,7 +18,7 @@ This guide explores Node-RED message mechanics, common pitfalls, and best practi
Messages in Node-RED are data packets that flow between nodes in your workflow. Node-RED follows an event-driven architecture where nodes act as both event emitters and listeners, with messages serving as the communication medium between them.
-
+
_Node-RED message passing visualization_
Messages carry the data that powers your workflows, sensor readings, user inputs, API responses, and more. Fundamentally, Node-RED messages are JavaScript objects, providing a flexible structure for managing and transferring data throughout your flows.
@@ -69,7 +68,7 @@ Message property values can be any JavaScript-supported data type:
- [Buffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
- Other complex data types
-
+
_Various data types supported by Node-RED_
## How to Clone Messages and Properties
@@ -245,7 +244,7 @@ Steps:
3. Set the action to "Always convert to JavaScript Object" and click Done.
4. Connect the JSON node between the source node (sending the JSON string) and the destination node (requiring the parsed object).
-The JSON node automatically converts incoming JSON strings into JavaScript objects. For more details, see the [JSON node documentation](/node-red/core-nodes/json/).
+The JSON node automatically converts incoming JSON strings into JavaScript objects. For more details, see the [JSON node documentation](/docs/node-red/core-nodes/parsers/json/).
## Common Mistakes to Avoid
@@ -271,10 +270,10 @@ return msg;
This commonly occurs when an Inject node sends `msg.payload` as a string or number, then a Change node attempts to add properties to it.
-
+
_Incorrect: Adding properties to a non-object type_
-
+
_Correct: Initialize as object before adding properties_
### 2. Overwriting the Entire Message Object
@@ -324,4 +323,4 @@ msg.payload = msg.payload * 2;
return msg; // Flow continues
```
-By mastering Node-RED message handling and avoiding common mistakes, you can build robust, efficient workflows. Understanding JSON conversion, message cloning, and proper property management ensures smooth data flow between nodes and maintainable, error-free applications.
\ No newline at end of file
+By mastering Node-RED message handling and avoiding common mistakes, you can build robust, efficient workflows. Understanding JSON conversion, message cloning, and proper property management ensures smooth data flow between nodes and maintainable, error-free applications.
diff --git a/src/node-red/getting-started/node-red-port.md b/nuxt/content-guides/node-red/getting-started/node-red-port.md
similarity index 96%
rename from src/node-red/getting-started/node-red-port.md
rename to nuxt/content-guides/node-red/getting-started/node-red-port.md
index d42a2394ab..9787a510ea 100644
--- a/src/node-red/getting-started/node-red-port.md
+++ b/nuxt/content-guides/node-red/getting-started/node-red-port.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: Port Configuration
- order: 2
- parent: Getting Started
+title: Node-RED Port (localhost:1880)
+metaTitle: "Node-RED Port (localhost:1880)"
+navTitle: Port Configuration
+navOrder: 2
meta:
- title: Node-RED Port (localhost:1880)
description: Learn how to configure Node-RED ports, change default settings, secure your installation, and set up remote access with FlowFuse.
keywords: Node-RED port, port 1880, change Node-RED port, Node-RED security, remote access, FlowFuse, port configuration
---
-# {{ meta.title }}
+# Node-RED Port (localhost:1880)
Node-RED runs on **port 1880** by default. This is the network port where Node-RED listens for connections. When you start Node-RED, you access the editor by opening `http://localhost:1880` in your browser. All your HTTP endpoints and the Node-RED interface are served through this port.
diff --git a/nuxt/content-guides/node-red/getting-started/programming/README.md b/nuxt/content-guides/node-red/getting-started/programming/README.md
new file mode 100644
index 0000000000..6b4fe635c8
--- /dev/null
+++ b/nuxt/content-guides/node-red/getting-started/programming/README.md
@@ -0,0 +1,22 @@
+---
+title: Node-RED Programming
+metaTitle: "Node-RED Programming"
+navTitle: Programming
+navOrder: 8
+meta:
+ description: Master Node-RED programming fundamentals including flows, nodes, messages, conditional logic, and data manipulation. Learn essential concepts for building sophisticated visual programming solutions.
+ keywords: Node-RED programming, visual programming, Node-RED flows, Node-RED nodes, message passing, conditional logic, data manipulation, flow-based programming, Node-RED tutorial, IoT programming
+---
+
+# Node-RED Programming
+
+Learn the core programming concepts you'll use every day in Node-RED. This section covers the fundamental building blocks that will help you create more sophisticated and reliable flows.
+
+## What's Covered
+
+Programming in Node-RED means working with flows, nodes, and messages. Even though you're working visually, you'll still need to understand key programming concepts like conditional logic, loops, and data manipulation. This section teaches you how to implement these concepts using Node-RED's visual approach.
+
+- [How to Debug Node-RED Flows Using Debugger](/docs/node-red/getting-started/programming/debugging-flows/): Debug Node-RED flows using the Debugger. Learn to set breakpoints, step through execution, and inspect messages for efficient troubleshooting.
+- [How to Filter, Map, Sort, and Reduce Data in Node-RED](/docs/node-red/getting-started/programming/data-tranformation/): Learn how to perform data transformation in Node-RED with a low-code approach.
+- [How to implement loops in Node-RED flows](/docs/node-red/getting-started/programming/loop/): Learn how to implement while, for, and for...of loops in Node-RED with core and custom nodes for efficient data processing and automation.
+- [How to Use If-Else Logic in Node-RED](/docs/node-red/getting-started/programming/if-else/): Learn how to implement If-Else logic in Node-RED with our step-by-step guide. Use Function and Switch nodes for dynamic, conditional flows.
diff --git a/src/node-red/getting-started/programming/data-tranformation.md b/nuxt/content-guides/node-red/getting-started/programming/data-tranformation.md
similarity index 97%
rename from src/node-red/getting-started/programming/data-tranformation.md
rename to nuxt/content-guides/node-red/getting-started/programming/data-tranformation.md
index 8ef74b5a7d..3e16217393 100644
--- a/src/node-red/getting-started/programming/data-tranformation.md
+++ b/nuxt/content-guides/node-red/getting-started/programming/data-tranformation.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: Data Tranformation
- parent: Programming
+title: How to Filter, Map, Sort, and Reduce Data in Node-RED
+metaTitle: "How to Filter, Map, Sort, and Reduce Data in Node-RED"
+navTitle: Data Tranformation
+navOrder: 50
meta:
- title: How to Filter, Map, Sort, and Reduce Data in Node-RED
- description: Learn how to perform data transformation in Node-RED with a low-code approach.
+ description: Learn how to perform data transformation in Node-RED with a low-code approach.
keywords: how to filter data in node-red, how to map array in node-red, how to map data in node-red, how to sort data in node-red, how to reduce data in node-red, data transformation in node-red
-image: /node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png
+image: /docs/node-red/getting-started/images/filtering-mapping-sorting-reducing-with-node-red.png
---
-# {{meta.title}}
+# How to Filter, Map, Sort, and Reduce Data in Node-RED
Data transformation is at the heart of most Node-RED applications, whether you're processing IoT sensor readings, cleaning API responses, or preparing data for visualization. While you could write JavaScript functions to handle these operations, Node-RED's visual, low-code approach offers a more maintainable and accessible alternative that anyone on your team can understand and modify.
@@ -92,9 +92,11 @@ Filter, map, sort, and reduce are essential functions in data processing because
However, you've noticed that the temperature data is in Kelvin, but you need it in Celsius. Additionally, the data is not correctly ordered by timestamp, and you only need the data of June 17th. Finally, you want to calculate the average temperature for that day. Users who are not familiar with Node-RED basics can use a JavaScript function node to achieve this, as shown below:
-{% renderFlow %}
+::render-flow
+```json
[{"id":"306d455509a3747e","type":"inject","z":"977143edb097b685","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15},{\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15},{\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15},{\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15},{\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15}]","payloadType":"json","x":260,"y":200,"wires":[["c58e1653fe5511eb"]]},{"id":"c58e1653fe5511eb","type":"function","z":"977143edb097b685","name":"Filtering, mapping, reducing and sorting data with traditional coding","func":"let sensorData = msg.payload;\n\nconst filteredData = sensorData\n .filter(item => item.timestamp.startsWith(\"2024-06-17\"))\n .map(item => ({\n timestamp: item.timestamp,\n temperature: item.temperature - 273.15\n }));\n\nfilteredData.sort((a, b) => (a.timestamp > b.timestamp) ? 1 : ((b.timestamp > a.timestamp) ? -1 : 0));\n\nconst totalTemperature = filteredData.reduce((acc, entry) => acc + entry.temperature, 0);\nconst averageTemperature = totalTemperature / filteredData.length;\n\nmsg.payload = {\n sensorData: filteredData,\n averageTemperature: averageTemperature\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":200,"wires":[["827c7d2009eeb046"]]},{"id":"827c7d2009eeb046","type":"debug","z":"977143edb097b685","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1060,"y":200,"wires":[]}]
-{% endrenderFlow %}
+```
+::
Using function nodes isn't wrong, but it adds complexity to your applications, for more information refer to the [Drawbacks of using Fuction nodes](/blog/2023/03/why-should-you-use-node-red-function-nodes/#_5-benefits-of-avoiding-function-nodes) Article. Since not everyone on the team may be familiar with JavaScript, it can limit who can solve business problems. To keep the application flow simple, using a low-code approach to perform these operations is crucial.
@@ -113,9 +115,11 @@ Mapping often refers to the process of applying a function to each item in a lis
{data-zoomable}
-{% renderFlow %}
+::render-flow
+```json
[{"id":"306d455509a3747e","type":"inject","z":"977143edb097b685","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[ {\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15}, {\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15}, {\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15}, {\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15}, {\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15}, {\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15}, {\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15}, {\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15}, {\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15}, {\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15}, {\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15} ]","payloadType":"json","x":500,"y":540,"wires":[["9d9c0688468e1aae"]]},{"id":"9d9c0688468e1aae","type":"split","z":"977143edb097b685","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":860,"y":540,"wires":[["785125a70fbdc554"]]},{"id":"785125a70fbdc554","type":"change","z":"977143edb097b685","name":"Converting the temperature data from kelvin to celsius","rules":[{"t":"set","p":"payload.temperature","pt":"msg","to":"payload.temperature - 273.15","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":540,"wires":[["9cd6e05b88ec26fd"]]},{"id":"9cd6e05b88ec26fd","type":"join","z":"977143edb097b685","name":"Creating new array by combining message sequence","mode":"auto","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1820,"y":540,"wires":[["244660d81bf5e5b2"]]},{"id":"244660d81bf5e5b2","type":"debug","z":"977143edb097b685","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2140,"y":540,"wires":[]}]
-{% endrenderFlow %}
+```
+::
## Filtering
@@ -127,9 +131,11 @@ Filtering is the process of selecting specific items from an array to create a n
{data-zoomable}
-{% renderFlow %}
+::render-flow
+```json
[{"id":"4e76a2328451b4c3","type":"inject","z":"977143edb097b685","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15},{\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15},{\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15},{\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15},{\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15}]","payloadType":"json","x":380,"y":480,"wires":[["f4e07a31f505a50c"]]},{"id":"f4e07a31f505a50c","type":"split","z":"977143edb097b685","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":680,"y":480,"wires":[["fcd6a0a1497203a9"]]},{"id":"bed1a7d861fa9e3d","type":"join","z":"977143edb097b685","name":"Creating new array by combining message sequence","mode":"auto","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"0","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":1940,"y":480,"wires":[["2449811ec79bc220"]]},{"id":"2449811ec79bc220","type":"debug","z":"977143edb097b685","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2240,"y":480,"wires":[]},{"id":"7797594a508cfb46","type":"switch","z":"977143edb097b685","name":"Routing message sequence based on condition","property":"payload.timestamp","propertyType":"msg","rules":[{"t":"cont","v":"2024-06-17","vt":"str"}],"checkall":"true","repair":true,"outputs":1,"x":1520,"y":480,"wires":[["bed1a7d861fa9e3d"]]},{"id":"fcd6a0a1497203a9","type":"change","z":"977143edb097b685","name":"Converting the temperature data from kelvin to celsius","rules":[{"t":"set","p":"payload.temperature","pt":"msg","to":"payload.temperature - 273.15","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1100,"y":480,"wires":[["7797594a508cfb46"]]}]
-{% endrenderFlow %}
+```
+::
## Sorting
@@ -141,9 +147,11 @@ To perform sorting, we have to use the Node-RED Sort Node.
{data-zoomable}
-{% renderFlow %}
+::render-flow
+```json
[{"id":"8b66990baca45f2d","type":"inject","z":"977143edb097b685","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15},{\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15},{\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15},{\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15},{\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15}]","payloadType":"json","x":400,"y":540,"wires":[["f0d48b57cbd10fdd"]]},{"id":"f0d48b57cbd10fdd","type":"split","z":"977143edb097b685","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":740,"y":540,"wires":[["fdc21a267f7583e7"]]},{"id":"fdc21a267f7583e7","type":"change","z":"977143edb097b685","name":"Correcting the temperature property","rules":[{"t":"set","p":"payload.temperature","pt":"msg","to":"payload.temperature - 273.15","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1080,"y":540,"wires":[["7d4ce2d4e21cd914"]]},{"id":"c273215c8c9cebee","type":"join","z":"977143edb097b685","name":"Creating new array by combining message sequence","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":1860,"y":540,"wires":[["c423efbd0581367a"]]},{"id":"e70d15ced7405755","type":"debug","z":"977143edb097b685","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2480,"y":540,"wires":[]},{"id":"7d4ce2d4e21cd914","type":"switch","z":"977143edb097b685","name":"Routing message sequence based on condition","property":"payload.timestamp","propertyType":"msg","rules":[{"t":"cont","v":"2024-06-17","vt":"str"}],"checkall":"true","repair":true,"outputs":1,"x":1440,"y":540,"wires":[["c273215c8c9cebee"]]},{"id":"c423efbd0581367a","type":"sort","z":"977143edb097b685","name":"Sorting data based on timestamp","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"timestamp","msgKeyType":"jsonata","seqKey":"payload.timestamp","seqKeyType":"jsonata","x":2240,"y":540,"wires":[["e70d15ced7405755"]]}]
-{% endrenderFlow %}
+```
+::
## Reducing
@@ -157,6 +165,8 @@ Reducing refers to the process of combining elements of a data structure (such a
In this configuration, the Join node is set to reduce sequence mode. The initial value of the accumulator ($A) is initialized to 0. As each message is processed, the current temperature (payload.temperature) is added to $A. Once all messages have been processed, the accumulated sum $A is divided by the total number of messages ($N) to compute the average temperature.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"5ff0902202c21e85","type":"inject","z":"977143edb097b685","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15},{\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15},{\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15},{\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15},{\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15}]","payloadType":"json","x":580,"y":620,"wires":[["993ffc096c3e8089"]]},{"id":"993ffc096c3e8089","type":"split","z":"977143edb097b685","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":900,"y":620,"wires":[["3bbb68c2dc2a0f5c"]]},{"id":"3bbb68c2dc2a0f5c","type":"change","z":"977143edb097b685","name":"Correcting the temperature property","rules":[{"t":"set","p":"payload.temperature","pt":"msg","to":"payload.temperature - 273.15","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1280,"y":620,"wires":[["580210c585730f97"]]},{"id":"01e7066b3ff012e7","type":"join","z":"977143edb097b685","name":"Creating new array by combining message sequence","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":2060,"y":620,"wires":[["27cc5d5e90f7facd","6116c1efc3f7f682"]]},{"id":"580210c585730f97","type":"switch","z":"977143edb097b685","name":"Routing message sequence based on condition","property":"payload.timestamp","propertyType":"msg","rules":[{"t":"cont","v":"2024-06-17","vt":"str"}],"checkall":"true","repair":true,"outputs":1,"x":1640,"y":620,"wires":[["01e7066b3ff012e7"]]},{"id":"27cc5d5e90f7facd","type":"sort","z":"977143edb097b685","name":"Sorting data based on timestamp","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"timestamp","msgKeyType":"jsonata","seqKey":"payload.timestamp","seqKeyType":"jsonata","x":2440,"y":620,"wires":[["f1f93a7b4575daf1"]]},{"id":"362ec9c482688cf6","type":"debug","z":"977143edb097b685","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":3140,"y":740,"wires":[]},{"id":"b9f2f83a330140ca","type":"join","z":"977143edb097b685","name":"Calculating the the average of temperature","mode":"reduce","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"$A+ payload.temperature","reduceInit":"0","reduceInitType":"num","reduceFixup":"$A/$N","x":2890,"y":740,"wires":[["362ec9c482688cf6"]]},{"id":"f1f93a7b4575daf1","type":"debug","z":"977143edb097b685","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2720,"y":620,"wires":[]},{"id":"6116c1efc3f7f682","type":"split","z":"977143edb097b685","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":2460,"y":740,"wires":[["b9f2f83a330140ca"]]}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/getting-started/programming/debugging-flows.md b/nuxt/content-guides/node-red/getting-started/programming/debugging-flows.md
similarity index 90%
rename from src/node-red/getting-started/programming/debugging-flows.md
rename to nuxt/content-guides/node-red/getting-started/programming/debugging-flows.md
index da2f030725..fa70f4aeaa 100644
--- a/src/node-red/getting-started/programming/debugging-flows.md
+++ b/nuxt/content-guides/node-red/getting-started/programming/debugging-flows.md
@@ -1,16 +1,16 @@
---
-eleventyNavigation:
- key: Debugging
- parent: Programming
+title: How to Debug Node-RED Flows Using Debugger
+metaTitle: "How to Debug Node-RED Flows Using Debugger"
+navTitle: Debugging
+navOrder: 50
meta:
- title: How to Debug Node-RED Flows Using Debugger
description: Debug Node-RED flows using the Debugger. Learn to set breakpoints, step through execution, and inspect messages for efficient troubleshooting.
keywords: node-red-debugger, node red debug, nodered debug, node-red debug, how to debug nodered flows, how to debug node-red flows
---
-# {{meta.title}}
+# How to Debug Node-RED Flows Using Debugger
-When it comes to debugging application flows in Node-RED, the tool most Node-RED developers often reach for is the [Debug](/node-red/core-nodes/debug/) node. It provides a simple way to output message payloads or other data to the debug sidebar, helping you gain insights into how your flow is working. But what if you needed more control and visibility over the flow’s execution? What if you wanted to step through each node in detail, inspect variables, or pause the flow at specific points to understand what’s happening?
+When it comes to debugging application flows in Node-RED, the tool most Node-RED developers often reach for is the [Debug](/docs/node-red/core-nodes/common/debug/) node. It provides a simple way to output message payloads or other data to the debug sidebar, helping you gain insights into how your flow is working. But what if you needed more control and visibility over the flow’s execution? What if you wanted to step through each node in detail, inspect variables, or pause the flow at specific points to understand what’s happening?
In these cases, using the **Node-RED Debugger** becomes invaluable. The debugger allows you to trace the execution of your flows interactively, set breakpoints, and gain deeper insights beyond what the Debug node offers. This Documentation will show you how to effectively use the Node-RED Debugger to pinpoint issues and fine-tune your applications.
@@ -57,9 +57,11 @@ To illustrate how to use the Node-RED Debugger effectively, let’s consider a f
3. Create a new array from the filtered results.
4. Split the array and calculate the average temperature.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"3c012808d6b397e2","type":"group","z":"9cf82b68bb89e8ce","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["5ff0902202c21e85","993ffc096c3e8089","3bbb68c2dc2a0f5c","580210c585730f97","362ec9c482688cf6","b9f2f83a330140ca","6116c1efc3f7f682","01e7066b3ff012e7"],"x":394,"y":1899,"w":532,"h":642},{"id":"5ff0902202c21e85","type":"inject","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Inject the sample data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"timestamp\":\"2024-06-17T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-17T11:00:00Z\",\"temperature\":299.15},{\"timestamp\":\"2024-06-17T10:30:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-17T10:15:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-17T10:45:00Z\",\"temperature\":303.15},{\"timestamp\":\"2024-06-18T09:00:00Z\",\"temperature\":297.15},{\"timestamp\":\"2024-06-18T10:00:00Z\",\"temperature\":300.15},{\"timestamp\":\"2024-06-18T11:00:00Z\",\"temperature\":301.15},{\"timestamp\":\"2024-06-18T12:00:00Z\",\"temperature\":302.15},{\"timestamp\":\"2024-06-19T10:00:00Z\",\"temperature\":298.15},{\"timestamp\":\"2024-06-19T11:00:00Z\",\"temperature\":299.15}]","payloadType":"json","x":540,"y":1940,"wires":[["993ffc096c3e8089"]]},{"id":"993ffc096c3e8089","type":"split","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":640,"y":2020,"wires":[["3bbb68c2dc2a0f5c"]]},{"id":"3bbb68c2dc2a0f5c","type":"change","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Kelvin to celcius","rules":[{"t":"set","p":"payload.temperature","pt":"msg","to":"payload.temperature - 273.15","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":2100,"wires":[["580210c585730f97"]]},{"id":"580210c585730f97","type":"switch","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Routing message sequence based on condition","property":"payload.timestamp","propertyType":"msg","rules":[{"t":"cont","v":"2024-06-17","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":660,"y":2180,"wires":[["01e7066b3ff012e7"]]},{"id":"362ec9c482688cf6","type":"debug","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":2500,"wires":[]},{"id":"b9f2f83a330140ca","type":"join","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Calculating the the average of temperature","mode":"reduce","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":true,"accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"$A+ payload.temperature","reduceInit":"0","reduceInitType":"num","reduceFixup":"$A/$N","x":690,"y":2400,"wires":[["362ec9c482688cf6"]]},{"id":"6116c1efc3f7f682","type":"split","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Splits a message into a sequence of messages.","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":700,"y":2340,"wires":[["b9f2f83a330140ca"]]},{"id":"01e7066b3ff012e7","type":"join","z":"9cf82b68bb89e8ce","g":"3c012808d6b397e2","name":"Creating new array by combining message sequence","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":true,"accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":700,"y":2260,"wires":[["6116c1efc3f7f682"]]}]
-{% endrenderFlow %}
+```
+::
However, clicking the **Inject** node once does not produce the expected results; instead, it requires clicking again to get the output. This indicates that there might be a timing issue or a logic flaw in the flow that prevents it from processing correctly on the first click. Let's debug the flow with a debugger now.
@@ -87,7 +89,7 @@ At the top of the Debugger tab, you will find controls to stop the runtime manua
Now, let's diagnose the flow. We’ll manually pause the runtime, then step through each part of the flow using the debugger controls, observing the changes at each step.
-
+
_Video showing the execution of flow while debugger enabled and how to proceed to subsequent execution_
Follow these steps:
@@ -103,13 +105,13 @@ Manually stepping through the flow is useful for understanding how the flow oper
## Adding Breakpoints for Debugging Flows
-Now that we've pinpointed the problem to be somewhere between the[Switch](/node-red/core-nodes/switch/) node and the [Join](/node-red/core-nodes/join/) node, it’s time to leverage breakpoints for a more efficient debugging experience. These breakpoints allow you to pause the flow automatically allowing you to inspect messages and context without having to step through each node manually. This is especially useful for larger or more intricate flows.
+Now that we've pinpointed the problem to be somewhere between the[Switch](/docs/node-red/core-nodes/function/switch/) node and the [Join](/docs/node-red/core-nodes/sequence/join/) node, it’s time to leverage breakpoints for a more efficient debugging experience. These breakpoints allow you to pause the flow automatically allowing you to inspect messages and context without having to step through each node manually. This is especially useful for larger or more intricate flows.
First, let’s discuss where exactly we should add breakpoints. Our previous debugging shows that all 11 messages are correctly reaching the input of the Switch node. However, we need to check how many messages pass through the Switch node's condition and whether they contain the required part object for the Join node to create a single value (array).
To do this, we should add breakpoints at the output of the Switch node to monitor how many messages pass through, as well as at the input and output of the Join node. This will help us determine how many messages are reaching the input of the Join node and whether they contain the part object necessary for the Join node to automatically convert them into an array of those objects.
-
+
_Video showing how to add breakpoints_
To add a breakpoint:
@@ -121,7 +123,7 @@ To add a breakpoint:
### Debugging: Pinpointing the Exact Problem and Solving the Issue in the Flow
-
+
_Video showing the execution of the flow with added breakpoints, indicating the number of each input/output being sent and received for debugging._
Start by clicking the inject node to trigger execution, which will pause at the output of the switch node. Check the blue rectangle to see how many messages have passed through; it shows only a few, not 11, indicating that only those messages met the condition. As you proceed, you will see those messages also reaching the input of the join node correctly.
@@ -136,7 +138,7 @@ Now that you’ve learned how to add breakpoints and pinpoint problems, lets loo
### Disabling Breakpoints
-
+
_Video showing two ways of disabling breakpoints_
To disable a breakpoint without removing it:
@@ -149,7 +151,7 @@ To disable a breakpoint without removing it:
### Removing Breakpoints
-
+
_Video showing two ways of removing breakpoints_
To remove a breakpoint:
diff --git a/src/node-red/getting-started/programming/if-else.md b/nuxt/content-guides/node-red/getting-started/programming/if-else.md
similarity index 93%
rename from src/node-red/getting-started/programming/if-else.md
rename to nuxt/content-guides/node-red/getting-started/programming/if-else.md
index 46a809beed..289e2227d5 100644
--- a/src/node-red/getting-started/programming/if-else.md
+++ b/nuxt/content-guides/node-red/getting-started/programming/if-else.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: If-Else
- parent: Programming
+title: How to Use If-Else Logic in Node-RED
+metaTitle: "How to Use If-Else Logic in Node-RED"
+navTitle: If-Else
+navOrder: 50
meta:
- title: How to Use If-Else Logic in Node-RED
- description: Learn how to implement If-Else logic in Node-RED with our step-by-step guide. Use Function and Switch nodes for dynamic, conditional flows.
+ description: Learn how to implement If-Else logic in Node-RED with our step-by-step guide. Use Function and Switch nodes for dynamic, conditional flows.
keywords: node red if else, nodered switch, node-red conditional flow, node red function if else, node red if then else example, node red switch example, node red switch node example, node red function multiple outputs example, node red function example,node red function if, node red if, node red if node, node red if then
-image: /node-red/getting-started/images/if-else-with-node-red.png
+image: /docs/node-red/getting-started/images/if-else-with-node-red.png
---
-# {{meta.title}}
+# How to Use If-Else Logic in Node-RED
Human decision-making is often guided by a series of "if this, then that" choices, whether it's deciding what to wear based on the weather or determining the quickest route to work depending on traffic. This kind of logic is equally crucial in systems, especially those built in Node-RED. Just as we make decisions based on various factors, systems must evaluate conditions and choose the appropriate course of action.
@@ -36,7 +36,7 @@ To implement If-Else logic in Node-RED, you can use the Switch node, which align
### Using Switch Node
-The [Switch](/node-red/core-nodes/switch/) node in Node-RED is used for routing messages based on specific conditions, offering a straightforward, low-code approach to implementing conditional logic in your flows. The Switch node allows you to set up rules using a visual interface, making it ideal for users who prefer a more intuitive method for handling conditions. However, it’s important to note that the Switch node represents a different, independent concept known as the "[switch statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)." While it serves a similar purpose to If-Else logic by building conditional flows, it operates under its own programming paradigm.
+The [Switch](/docs/node-red/core-nodes/function/switch/) node in Node-RED is used for routing messages based on specific conditions, offering a straightforward, low-code approach to implementing conditional logic in your flows. The Switch node allows you to set up rules using a visual interface, making it ideal for users who prefer a more intuitive method for handling conditions. However, it’s important to note that the Switch node represents a different, independent concept known as the "[switch statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)." While it serves a similar purpose to If-Else logic by building conditional flows, it operates under its own programming paradigm.
To demonstrate the Switch node, we'll set up a flow to make decisions based on the temperature value. We will route messages through different outputs based on temperature thresholds.
@@ -73,13 +73,15 @@ graph TD
```
_Node-RED flow using the Switch node to route messages based on temperature thresholds._
-{% renderFlow %}
+::render-flow
+```json
[{"id":"b90722a28f81c014","type":"group","z":"9cf82b68bb89e8ce","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["dd0d3432c348e1f2","21bd53568877f3b5","5277e184faad375a","7fbf37916236a960","aac1f46169e431ab","3eb24a6129d8fa8e","36e51d42d34c9587"],"x":194,"y":1219,"w":892,"h":322},{"id":"dd0d3432c348e1f2","type":"debug","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"high temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":1260,"wires":[]},{"id":"21bd53568877f3b5","type":"inject","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"Temperature","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random()*100","payloadType":"jsonata","x":310,"y":1380,"wires":[["5277e184faad375a"]]},{"id":"5277e184faad375a","type":"switch","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"30","vt":"num"},{"t":"lte","v":"30","vt":"num"},{"t":"lte","v":"20","vt":"num"},{"t":"lte","v":"10","vt":"num"}],"checkall":"true","repair":false,"outputs":4,"x":530,"y":1380,"wires":[["dd0d3432c348e1f2"],["7fbf37916236a960"],["7fbf37916236a960"],["3eb24a6129d8fa8e"]]},{"id":"7fbf37916236a960","type":"switch","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"20","vt":"num"},{"t":"gt","v":"10","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":670,"y":1380,"wires":[["aac1f46169e431ab"],["36e51d42d34c9587"]]},{"id":"aac1f46169e431ab","type":"debug","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"for medium temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":930,"y":1340,"wires":[]},{"id":"3eb24a6129d8fa8e","type":"debug","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"for very low temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":1500,"wires":[]},{"id":"36e51d42d34c9587","type":"debug","z":"9cf82b68bb89e8ce","g":"b90722a28f81c014","name":"for low temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":1420,"wires":[]}]
-{% endrenderFlow %}
+```
+::
### Using Function Node
-The [Function](/node-red/core-nodes/function/) node allows for more complex logic by writing JavaScript. It's suitable when you need more control, or multiple values must be checked together.
+The [Function](/docs/node-red/core-nodes/function/function/) node allows for more complex logic by writing JavaScript. It's suitable when you need more control, or multiple values must be checked together.
For demonstration purposes, let's use the temperature example where we determine whether to turn the air conditioner on or off based on the temperature:
@@ -100,7 +102,7 @@ Before moving further, let's pause and understand what’s happening in the code
In Node-RED, `msg.payload` is used to carry data through the flow. Initially, it holds the temperature value injected by the Inject node. The Function node then processes this value using If-Else logic. If the temperature exceeds 30°C, `msg.payload` is set to `"Turn on the air conditioner"`, indicating that the air conditioner should be turned on. If the temperature is 30°C or lower, `msg.payload` is set to `"No action required"`, signaling that the air conditioner should remain off. This updated `msg.payload` is then passed on to the next node, ensuring the system responds appropriately based on the temperature input.
-Many people need clarification on the messaging system in Node-RED. For a deeper understanding of how messaging works in Node-RED, I recommend going through this document: [Node-RED Messaging Guide](/node-red/getting-started/node-red-messages/).
+Many people need clarification on the messaging system in Node-RED. For a deeper understanding of how messaging works in Node-RED, I recommend going through this document: [Node-RED Messaging Guide](/docs/node-red/getting-started/node-red-messages/).
3. Next, drag the Debug node onto the canvas and connect it to the output of the Function node. This will allow you to see the results of your conditional logic in the Node-RED debug window.
4. Deploy the flow by clicking the "Deploy" button in the top-right corner of the Node-RED editor.
@@ -115,9 +117,11 @@ flowchart TD
D --> E[End]
```
-{% renderFlow %}
+::render-flow
+```json
[{"id":"51ffa77e55eb7f63","type":"group","z":"9cf82b68bb89e8ce","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["19fa09374c1be7c4","ff41ef215d860c1a","773175cbe8014372"],"x":154,"y":2059,"w":672,"h":82},{"id":"19fa09374c1be7c4","type":"inject","z":"9cf82b68bb89e8ce","g":"51ffa77e55eb7f63","name":"Temperature","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random()*100","payloadType":"jsonata","x":270,"y":2100,"wires":[["ff41ef215d860c1a"]]},{"id":"ff41ef215d860c1a","type":"function","z":"9cf82b68bb89e8ce","g":"51ffa77e55eb7f63","name":"Temperature Threshold Check","func":"let Temperature = msg.payload;\n if (Temperature > 30) {\n msg.payload = \"Turn on the air conditioner\";\n } else {\n msg.payload = \"No action required\";\n }\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":2100,"wires":[["773175cbe8014372"]]},{"id":"773175cbe8014372","type":"debug","z":"9cf82b68bb89e8ce","g":"51ffa77e55eb7f63","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":2100,"wires":[]}]
-{% endrenderFlow %}
+```
+::
_Node-RED flow using the Function node to implement simple If-Else logic for temperature control._
@@ -182,9 +186,11 @@ flowchart TD
```
_Node-RED flow using the Function node with multiple outputs for handling various conditions like temperature and humidity._
-{% renderFlow %}
+::render-flow
+```json
[{"id":"301a31b0972b0b20","type":"group","z":"9cf82b68bb89e8ce","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["dbd085ed607e41de","31d2e8f0c871143d","b169bf385ca85f6c","aa7ab6452f4a7791","cc3e6e2c70643f6f","800508e428d74f5f"],"x":114,"y":719,"w":832,"h":202},{"id":"dbd085ed607e41de","type":"inject","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Temperature && Humidity","props":[{"p":"payload.temperature","v":"$random() * 100","vt":"jsonata"},{"p":"payload.humidity","v":"$random() * 100","vt":"jsonata"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":820,"wires":[["31d2e8f0c871143d"]]},{"id":"31d2e8f0c871143d","type":"function","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Temp/Humidity Decision Engine","func":"let Temperature = msg.payload.temperature;\nlet Humidity = msg.payload.humidity;\n\n// Initialize output array\nlet outputs = [null, null, null, null];\n\nif (Temperature > 30 && Humidity < 40) {\n // High temperature and low humidity\n outputs[0] = { payload: \"High temperature and low humidity: Turn on the air conditioner and use a humidifier\" };\n} else if (Temperature > 30 && Humidity >= 40) {\n // High temperature and high humidity\n outputs[1] = { payload: \"High temperature and high humidity: Turn on the air conditioner\" };\n} else if (Temperature < 15 && Humidity < 40) {\n // Low temperature and low humidity\n outputs[2] = { payload: \"Low temperature and low humidity: Turn on the heater and use a humidifier\" };\n} else if (Temperature < 15 && Humidity >= 40) {\n // Low temperature and high humidity\n outputs[3] = { payload: \"Low temperature and high humidity: Turn on the heater\" };\n}\n\nreturn outputs;","outputs":4,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":820,"wires":[["b169bf385ca85f6c"],["aa7ab6452f4a7791"],["cc3e6e2c70643f6f"],["800508e428d74f5f"]]},{"id":"b169bf385ca85f6c","type":"debug","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Output 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":760,"wires":[]},{"id":"aa7ab6452f4a7791","type":"debug","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Output 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":800,"wires":[]},{"id":"cc3e6e2c70643f6f","type":"debug","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Output 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":840,"wires":[]},{"id":"800508e428d74f5f","type":"debug","z":"9cf82b68bb89e8ce","g":"301a31b0972b0b20","name":"Output 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":880,"wires":[]}]
-{% endrenderFlow %}
+```
+::
## Choosing Between the Function Node and Switch Node
@@ -194,4 +200,4 @@ The Function node excels in scenarios where complex logic and detailed message p
In contrast, the Switch node is designed for simpler, value-based routing. It is ideal for straightforward scenarios where you need to route messages based on a single value with multiple possible outputs. This node enables you to create rules based on specific values or conditions without the need for complex logic or extensive message modifications. If your routing logic involves basic comparisons and does not require advanced processing or calculations, the Switch node provides a more streamlined and intuitive approach.
-In summary, choose the Function node for intricate decision-making and detailed message processing, while the Switch node is better suited for scenarios where simple value-based routing is sufficient.
\ No newline at end of file
+In summary, choose the Function node for intricate decision-making and detailed message processing, while the Switch node is better suited for scenarios where simple value-based routing is sufficient.
diff --git a/src/node-red/getting-started/programming/loop.md b/nuxt/content-guides/node-red/getting-started/programming/loop.md
similarity index 96%
rename from src/node-red/getting-started/programming/loop.md
rename to nuxt/content-guides/node-red/getting-started/programming/loop.md
index e92552f5e9..837b2fc8bf 100644
--- a/src/node-red/getting-started/programming/loop.md
+++ b/nuxt/content-guides/node-red/getting-started/programming/loop.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: Loop
- parent: Programming
+title: How to implement loops in Node-RED flows
+metaTitle: "How to implement loops in Node-RED flows"
+navTitle: Loop
+navOrder: 50
meta:
- title: How to implement loops in Node-RED flows
description: Learn how to implement while, for, and for...of loops in Node-RED with core and custom nodes for efficient data processing and automation.
keywords: node red loop, nodered loop, node red for loop, node-red loop, nodered for of, node-red while loop, node-red do while loop
---
-# {{meta.title}}
+# How to implement loops in Node-RED flows
Handling repetitive tasks is a common challenge in automation and data processing. Whether you need to iterate over large datasets, perform calculations, or execute operations based on conditions multiple times, using loops can significantly enhance efficiency and scalability.
@@ -61,9 +61,11 @@ graph TD
F --> G["Debug Node Display Current String"]
```
-{% renderFlow %}
+::render-flow
+```json
[{"id":"e90dc2e50e40896c","type":"group","z":"a3aa840957f658c6","name":"While Loop","style":{"label":true},"nodes":["cf6ebf02d00eaca6","696d89aa4050cd13","0e2d9f0447cf6226","bb6074cdf4398cb6","e19304ab31199315","c467509c666ee400","06bb08e3f0d7888a"],"x":34,"y":139,"w":1092,"h":242},{"id":"cf6ebf02d00eaca6","type":"switch","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"Does the msg.i contains Z","property":"i","propertyType":"msg","rules":[{"t":"cont","v":"Z","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":590,"y":240,"wires":[["c467509c666ee400"],["0e2d9f0447cf6226","06bb08e3f0d7888a"]]},{"id":"696d89aa4050cd13","type":"debug","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"End","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1030,"y":180,"wires":[]},{"id":"0e2d9f0447cf6226","type":"debug","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"Output \"i\"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"i","targetType":"msg","statusVal":"","statusType":"auto","x":900,"y":260,"wires":[]},{"id":"bb6074cdf4398cb6","type":"inject","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"Start","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"[\"hello\",\"run\",\"why\"]","payloadType":"json","x":130,"y":240,"wires":[["e19304ab31199315"]]},{"id":"e19304ab31199315","type":"change","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"initilized i with empty string","rules":[{"t":"set","p":"i","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":240,"wires":[["cf6ebf02d00eaca6"]]},{"id":"c467509c666ee400","type":"change","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"if not Set payload to \"completed\"","rules":[{"t":"set","p":"payload","pt":"msg","to":"Completed","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":180,"wires":[["696d89aa4050cd13"]]},{"id":"06bb08e3f0d7888a","type":"function","z":"a3aa840957f658c6","g":"e90dc2e50e40896c","name":"Append Random Letter","func":"// add ASCII char from 32 to 126\nmsg.i += String.fromCharCode(Math.random()*26 + 65);\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":340,"wires":[["cf6ebf02d00eaca6"]]}]
-{% endrenderFlow %}
+```
+::
#### For Loop
@@ -94,13 +96,15 @@ graph TD
G --> H["Debug Node Display Completion Message"]
```
-{% renderFlow %}
+::render-flow
+```json
[{"id":"3b546e0612673478","type":"group","z":"a3aa840957f658c6","name":"ForLoop","style":{"label":true},"nodes":["8ee16c1d06fca9fe","64a4a7329631d7ce","e67a34285a7e6979","e2074cf01ed451fd","811cedbe7cb89415","8bbccc2d10c36bfe","826d819a06810184","e7ebf7f66cda1370"],"x":14,"y":159,"w":1292,"h":242},{"id":"8ee16c1d06fca9fe","type":"switch","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"if msg.i == msg.payload.length","property":"i","propertyType":"msg","rules":[{"t":"eq","v":"payload.length","vt":"msg"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":550,"y":280,"wires":[["8bbccc2d10c36bfe"],["e7ebf7f66cda1370","826d819a06810184"]]},{"id":"64a4a7329631d7ce","type":"debug","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"End","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1210,"y":200,"wires":[]},{"id":"e67a34285a7e6979","type":"debug","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"Output \"i\"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1080,"y":340,"wires":[]},{"id":"e2074cf01ed451fd","type":"inject","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"Start","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"[\"hello\",\"run\",\"why\"]","payloadType":"json","x":110,"y":280,"wires":[["811cedbe7cb89415"]]},{"id":"811cedbe7cb89415","type":"change","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"initilized i with 0","rules":[{"t":"set","p":"i","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":280,"wires":[["8ee16c1d06fca9fe"]]},{"id":"8bbccc2d10c36bfe","type":"change","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"If 'i' equals array length, set payload to \"completed\".","rules":[{"t":"set","p":"payload","pt":"msg","to":"Completed","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":200,"wires":[["64a4a7329631d7ce"]]},{"id":"826d819a06810184","type":"change","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"Access array element with i","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[msg.i]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":340,"wires":[["e67a34285a7e6979"]]},{"id":"e7ebf7f66cda1370","type":"change","z":"a3aa840957f658c6","g":"3b546e0612673478","name":"increment i by 1","rules":[{"t":"set","p":"i","pt":"msg","to":"i+1","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":360,"wires":[["8ee16c1d06fca9fe"]]}]
-{% endrenderFlow %}
+```
+::
#### For...of / ForEach Loop
-In traditional programming, `for...of` and `forEach` loops are commonly used to iterate through arrays or object properties, allowing for individual element processing. Since Node-RED doesn’t include these specific constructs, you can replicate their functionality by using a combination of nodes, particularly the **[Split](/node-red/core-nodes/split/)** and **[Join](/node-red/core-nodes/join/)** nodes.
+In traditional programming, `for...of` and `forEach` loops are commonly used to iterate through arrays or object properties, allowing for individual element processing. Since Node-RED doesn’t include these specific constructs, you can replicate their functionality by using a combination of nodes, particularly the **[Split](/docs/node-red/core-nodes/sequence/split/)** and **[Join](/docs/node-red/core-nodes/sequence/join/)** nodes.
Here’s how you can replicate this functionality in Node-RED:
@@ -111,7 +115,7 @@ Here’s how you can replicate this functionality in Node-RED:
When you click the **Inject** button, the **Split** node will process each element of the array individually, and the **Debug** node will display each one in the debug window.
-To explore how you can map, sort, filter, and reduce data using this approach, check out our guide: [How to Filter, Map, Sort, and Reduce Data in Node-RED](/node-red/getting-started/programming/data-tranformation/).
+To explore how you can map, sort, filter, and reduce data using this approach, check out our guide: [How to Filter, Map, Sort, and Reduce Data in Node-RED](/docs/node-red/getting-started/programming/data-tranformation/).
```mermaid
graph TD
@@ -123,13 +127,15 @@ graph TD
C["Debug Node\nDisplays each element"]
```
-{% renderFlow %}
+::render-flow
+```json
[{"id":"2e67b2739f364a71","type":"group","z":"a3aa840957f658c6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["2add2705d262010d","40333c736844a0c1","3337ba024a363a15","2f7d2aab12b3b4e9"],"x":254,"y":219,"w":532,"h":162},{"id":"2add2705d262010d","type":"inject","z":"a3aa840957f658c6","g":"2e67b2739f364a71","name":"Array","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[\"foo\",\"bar\",\"foobar\"]","payloadType":"json","x":350,"y":340,"wires":[["40333c736844a0c1"]]},{"id":"40333c736844a0c1","type":"split","z":"a3aa840957f658c6","g":"2e67b2739f364a71","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":530,"y":320,"wires":[["3337ba024a363a15"]]},{"id":"3337ba024a363a15","type":"debug","z":"a3aa840957f658c6","g":"2e67b2739f364a71","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":320,"wires":[]},{"id":"2f7d2aab12b3b4e9","type":"inject","z":"a3aa840957f658c6","g":"2e67b2739f364a71","name":"Object","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"first\":\"Hello World\",\"second\":8,\"third\":true}","payloadType":"json","x":350,"y":260,"wires":[["40333c736844a0c1"]]}]
-{% endrenderFlow %}
+```
+::
#### Implementing Loops with the Function Node
-Implementing loops with the **[Function](/node-red/core-nodes/function/)** node is straightforward if you're familiar with JavaScript, as it allows you to write custom code. However, a common issue is figuring out how to send a message on each iteration without ending the loop after the first iteration. In this section, we’ll show you how to implement loops in the `Function` node correctly, ensuring that each iteration is processed and sent out properly without prematurely breaking the loop.
+Implementing loops with the **[Function](/docs/node-red/core-nodes/function/function/)** node is straightforward if you're familiar with JavaScript, as it allows you to write custom code. However, a common issue is figuring out how to send a message on each iteration without ending the loop after the first iteration. In this section, we’ll show you how to implement loops in the `Function` node correctly, ensuring that each iteration is processed and sent out properly without prematurely breaking the loop.
For demonstration purposes, we will implement a `for` loop.
@@ -149,9 +155,11 @@ When you deploy the flow and click the **Inject** button, each item in the array
By using `node.send()` inside the loop, you ensure that each iteration produces a separate message, and the Function node can handle multiple messages efficiently. For more information on on this, refer to [Documentation on Sending messages asynchronously](https://nodered.org/docs/user-guide/writing-functions#sending-messages-asynchronously).
-{% renderFlow %}
+::render-flow
+```json
[{"id":"50be2bac3b058be5","type":"group","z":"a3aa840957f658c6","name":"","style":{"label":true},"nodes":["97c288f32955c6ab","7a8404c44ac0749b","0d7b9cb51669ad9b"],"x":414,"y":499,"w":612,"h":82},{"id":"97c288f32955c6ab","type":"inject","z":"a3aa840957f658c6","g":"50be2bac3b058be5","name":"Array","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[1, \"hello\", \"%\", true]","payloadType":"json","x":510,"y":540,"wires":[["7a8404c44ac0749b"]]},{"id":"7a8404c44ac0749b","type":"function","z":"a3aa840957f658c6","g":"50be2bac3b058be5","name":"For Loop","func":"for (let i = 0; i < msg.payload.length; i++) {\n // Create a new message for each item\n let newMsg = { ...msg }; // Copy the original msg object\n newMsg.payload = msg.payload[i]; // Set payload to the current item\n node.send(newMsg)\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":540,"wires":[["0d7b9cb51669ad9b"]]},{"id":"0d7b9cb51669ad9b","type":"debug","z":"a3aa840957f658c6","g":"50be2bac3b058be5","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":540,"wires":[]}]
-{% endrenderFlow %}
+```
+::
### Implementing Loops in Node-RED with Custom node
@@ -177,9 +185,11 @@ Throughtout this section we will show you how you can implement loops in Node-RE
6. Drag a **Debug** node onto the canvas and connect its input to the output of the **Function** node. This will print the current `msg.payload` after each iteration.
7. Drag another **Debug** node onto the canvas and connect its input to the first output of the **Loop** node. This will print when the loop exits, indicating that the condition has been met.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"7ef4d41cf74f75c3","type":"group","z":"a3aa840957f658c6","name":"While Loop","style":{"label":true},"nodes":["3ba931b1.fb48d6","2d297dfa.6e660a","5aef28e.0f9e7d8","90c49008.053a58","9a725668.330148","e88b0e8c.d39858","9c48f336.471ea","66144af4.d1ec9c","75c6b326.e934d4","77ac6763.8e54b8","99b265b4.e2d3c8"],"x":174,"y":139,"w":672,"h":322},{"id":"3ba931b1.fb48d6","type":"loop","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","kind":"cond","count":"10","initial":"1","step":"1","condition":"msg.payload.includes(\"Z\") != true","conditionType":"js","when":"after","enumeration":"enum","enumerationType":"msg","limit":"","loopPayload":"loop-keep","finalPayload":"final-last","x":500,"y":280,"wires":[["5aef28e.0f9e7d8"],["e88b0e8c.d39858"]]},{"id":"2d297dfa.6e660a","type":"inject","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":270,"y":280,"wires":[["3ba931b1.fb48d6"]]},{"id":"5aef28e.0f9e7d8","type":"debug","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"loop","targetType":"msg","statusVal":"","statusType":"auto","x":720,"y":280,"wires":[]},{"id":"90c49008.053a58","type":"comment","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"Example: Conditional loop","info":"","x":310,"y":180,"wires":[]},{"id":"9a725668.330148","type":"comment","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"Show final status","info":"","x":740,"y":240,"wires":[]},{"id":"e88b0e8c.d39858","type":"function","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","func":"// add ASCII char from 32 to 126\nmsg.payload += String.fromCharCode(Math.random()*26 + 65);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":380,"wires":[["66144af4.d1ec9c","9c48f336.471ea"]]},{"id":"9c48f336.471ea","type":"debug","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":380,"wires":[]},{"id":"66144af4.d1ec9c","type":"delay","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"","pauseType":"delay","timeout":"0.5","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":530,"y":355,"wires":[["3ba931b1.fb48d6"]]},{"id":"75c6b326.e934d4","type":"comment","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"Show string","info":"","x":730,"y":420,"wires":[]},{"id":"77ac6763.8e54b8","type":"comment","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"Add char to string","info":"","x":370,"y":420,"wires":[]},{"id":"99b265b4.e2d3c8","type":"comment","z":"a3aa840957f658c6","g":"7ef4d41cf74f75c3","name":"Repeat until string doesn't finish with \"Z\"","info":"","x":480,"y":240,"wires":[]}]
-{% endrenderFlow %}
+```
+::
#### For Loop
@@ -190,9 +200,11 @@ Throughtout this section we will show you how you can implement loops in Node-RE
5. Then, drag another **Change** node onto the canvas. Configure this node to set `msg.payload` to `msg.payload[msg.loop.value]`, which extracts the current array element using the loop’s counter (`msg.loop.value`). The **Loop** node generates properties like `value`, which is the counter we are incrementing.
6. Finally, drag a **Debug** node onto the canvas and connect it to the output of the previous **Change** node to print the current array element in each iteration.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"ac4bfead30be7380","type":"group","z":"a3aa840957f658c6","name":"For Loop","style":{"label":true},"nodes":["2ffc3d07.23e6fa","6e1118b1.449db8","ea852667d724cfb1","880a2501f7d153ba","bd58a956.c036b","60a8f138.0909a","44f1a29403157bba"],"x":74,"y":199,"w":1132,"h":202},{"id":"2ffc3d07.23e6fa","type":"inject","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[\"foo\",\"bar\",\"foobar\"]","payloadType":"json","x":210,"y":260,"wires":[["880a2501f7d153ba"]]},{"id":"6e1118b1.449db8","type":"loop","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"","kind":"fcnt","count":"","initial":"0","step":"1","condition":"","conditionType":"js","when":"before","enumeration":"enum","enumerationType":"msg","limit":"","loopPayload":"loop-orig","finalPayload":"final-last","x":710,"y":260,"wires":[["44f1a29403157bba"],["bd58a956.c036b"]]},{"id":"ea852667d724cfb1","type":"change","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"Access array element with loop counter","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[msg.loop.value]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":840,"y":360,"wires":[["60a8f138.0909a"]]},{"id":"880a2501f7d153ba","type":"change","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"Set Pass Count","rules":[{"t":"set","p":"count","pt":"msg","to":"payload.length","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":260,"wires":[["6e1118b1.449db8"]]},{"id":"bd58a956.c036b","type":"change","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"Repeat","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":360,"wires":[["6e1118b1.449db8","ea852667d724cfb1"]]},{"id":"60a8f138.0909a","type":"debug","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1090,"y":360,"wires":[]},{"id":"44f1a29403157bba","type":"debug","z":"a3aa840957f658c6","g":"ac4bfead30be7380","name":"End Loop","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1000,"y":240,"wires":[]}]
-{% endrenderFlow %}
+```
+::
#### For...of / ForEach Loop
@@ -203,6 +215,8 @@ Throughtout this section we will show you how you can implement loops in Node-RE
With the **Enumeration** kind, you can iterate through different types of data such as arrays, strings, objects, and more, making this loop versatile for handling various data structures.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"65d854c9098393e8","type":"group","z":"a3aa840957f658c6","name":"For of/ for each","style":{"label":true},"nodes":["38630ff1.21721","f009e0e9.24576","cf52b6dd.5febb8","33031c0e.1b115c","b28b06f1.38eb48","6e593ff2.dc94c"],"x":334,"y":219,"w":722,"h":222},{"id":"38630ff1.21721","type":"inject","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"Object","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"first\":\"Hello World\",\"second\":8,\"third\":true}","payloadType":"json","x":430,"y":260,"wires":[["f009e0e9.24576"]]},{"id":"f009e0e9.24576","type":"loop","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"","kind":"enum","count":"","initial":"","step":"","condition":"","conditionType":"js","when":"before","enumeration":"payload","enumerationType":"msg","limit":"","loopPayload":"loop-val","finalPayload":"final-orig","x":740,"y":300,"wires":[["cf52b6dd.5febb8"],["33031c0e.1b115c","6e593ff2.dc94c"]]},{"id":"cf52b6dd.5febb8","type":"debug","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"Loop End","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"loop","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":280,"wires":[]},{"id":"33031c0e.1b115c","type":"change","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"Repeat","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":400,"wires":[["f009e0e9.24576"]]},{"id":"b28b06f1.38eb48","type":"inject","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"Array","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[\"foo\",\"bar\",\"foobar\"]","payloadType":"json","x":430,"y":320,"wires":[["f009e0e9.24576"]]},{"id":"6e593ff2.dc94c","type":"debug","z":"a3aa840957f658c6","g":"65d854c9098393e8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":400,"wires":[]}]
-{% endrenderFlow %}
\ No newline at end of file
+```
+::
diff --git a/src/node-red/getting-started/string.md b/nuxt/content-guides/node-red/getting-started/string.md
similarity index 94%
rename from src/node-red/getting-started/string.md
rename to nuxt/content-guides/node-red/getting-started/string.md
index 399fb01cf3..3f3348e49d 100644
--- a/src/node-red/getting-started/string.md
+++ b/nuxt/content-guides/node-red/getting-started/string.md
@@ -1,16 +1,13 @@
---
+title: 'Strings in Node-RED: Convert String to Number, Split, Concatenate, Trim, and More'
metaTitle: "Strings in Node-RED: Convert, Split & Trim"
-eleventyNavigation:
- key: String
- order: 6
- parent: Getting Started
+navTitle: String
+navOrder: 6
meta:
- title: "Strings in Node-RED: Convert String to Number, Split, Concatenate, Trim, and More"
description: Learn essential string operations in Node-RED including converting between strings and numbers, splitting and concatenating text, parsing JSON, extracting substrings, trimming whitespace, and more. Step-by-step guide with practical examples.
keywords: node-red strings, working with strings in node-red, node-red string operations, node-red string manipulation, node-red text processing, node-red change node strings, node-red jsonata string functions, node-red template node strings, node-red function node strings, node-red parsing strings, node-red string conversion, node-red split string, node-red concatenate strings
---
-
-# {{ meta.title }}
+# Strings in Node-RED: Convert String to Number, Split, Concatenate, Trim, and More
Strings are one of the most common data types in Node-RED. Whether you're converting sensor values, parsing API responses, or building dynamic messages, understanding string operations is essential for building reliable flows.
@@ -26,9 +23,11 @@ One of the most frequent operations is converting string values to numbers for m
If your payload contains the string `"42"`, it becomes the number `42`. You can now use this in calculations or comparisons.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"2ac68ed1d9a7b380","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"42","payloadType":"str","x":530,"y":200,"wires":[["a14a67ac6574ae82"]]},{"id":"a14a67ac6574ae82","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"String to Number","rules":[{"t":"set","p":"payload","pt":"msg","to":"$number(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":200,"wires":[["225f4c6a47df2d3c"]]},{"id":"225f4c6a47df2d3c","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":200,"wires":[]}]
-{% endrenderFlow %}
+```
+::
## Converting Number to String
@@ -42,9 +41,11 @@ Converting numbers to strings is useful for displaying values, building messages
A number like `42` becomes the string `"42"`, ready for text operations.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"38b9110190ddba53","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"42","payloadType":"num","x":530,"y":260,"wires":[["06a4b6591a791f8d"]]},{"id":"06a4b6591a791f8d","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Number to String","rules":[{"t":"set","p":"payload","pt":"msg","to":"$string(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":260,"wires":[["c560426627a56137"]]},{"id":"c560426627a56137","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":260,"wires":[]}]
-{% endrenderFlow %}
+```
+::
## Splitting Strings
@@ -64,9 +65,11 @@ Splitting strings is essential when parsing CSV data, breaking apart delimited v
The Split node creates separate messages for each segment. For example, if you receive a log entry `"2024-12-15 14:30:45 ERROR Database connection failed"` and you split using spaces, it produces separate messages: first `"2024-12-15"`, then `"14:30:45"`, then `"ERROR"`, then `"Database"`, and so on. Each piece flows through your subsequent nodes one at a time, allowing you to extract the timestamp, severity level, and message separately.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"6a5c13d2e5bf152f","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"2024-12-15 14:30:45 ERROR Database connection failed","payloadType":"str","x":530,"y":320,"wires":[["4d3e4c715e94572b"]]},{"id":"9e90b663c08067fc","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":320,"wires":[]},{"id":"4d3e4c715e94572b","type":"split","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Split String","splt":" ","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":690,"y":320,"wires":[["9e90b663c08067fc"]]}]
-{% endrenderFlow %}
+```
+::
## Concatenating Strings
@@ -74,15 +77,17 @@ Combining strings is common when building messages, URLs, or formatted output.
1. Add a **Template** node after the nodes containing your data
2. Double-click to open the Template configuration
-3. Write your text and insert variables using {% raw %}`{{variableName}}`{% endraw %} syntax
+3. Write your text and insert variables using `{{variableName}}` syntax
4. Click **Done**
5. Connect to where you need the processed data
-Each {% raw %}`{{variableName}}`{% endraw %} is replaced with actual data. For example, the template {% raw %}`Hello {{payload.name}}, your order #{{payload.orderId}} has shipped to {{payload.city}}.`{% endraw %} with data containing name "Sarah", orderId "12345", and city "Portland" produces: `Hello Sarah, your order #12345 has shipped to Portland.`
+Each `{{variableName}}` is replaced with actual data. For example, the template `Hello {{payload.name}}, your order #{{payload.orderId}} has shipped to {{payload.city}}.` with data containing name "Sarah", orderId "12345", and city "Portland" produces: `Hello Sarah, your order #12345 has shipped to Portland.`
-{% renderFlow %}
+::render-flow
+```json
[{"id":"60cb0a1d79b095a3","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"name\":\"Sarah\",\"orderId\":\"12345\",\"city\":\"Portland\"}","payloadType":"json","x":530,"y":380,"wires":[["88d113db79d20417"]]},{"id":"9ed0bd64daa0cf35","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":380,"wires":[]},{"id":"88d113db79d20417","type":"template","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Concatenating Strings","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Hello {{payload.name}}, your order #{{payload.orderId}} has shipped to {{payload.city}}.","output":"str","x":720,"y":380,"wires":[["9ed0bd64daa0cf35"]]}]
-{% endrenderFlow %}
+```
+::
## Parsing JSON Strings
@@ -96,9 +101,11 @@ API responses and stored data often arrive as JSON strings, text that looks like
The JSON node detects your data type automatically. String `'{"temperature":22,"humidity":65}'` becomes an object `{temperature: 22, humidity: 65}` so you can access `msg.payload.temperature`.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"987d6b5ce96f863e","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"temperature\":22,\"humidity\":65}","payloadType":"str","x":530,"y":440,"wires":[["b92eb17c8dac49d8"]]},{"id":"b92eb17c8dac49d8","type":"json","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Parsing JSON Strings","property":"payload","action":"","pretty":false,"x":720,"y":440,"wires":[["a34030e2d9a085fe"]]},{"id":"a34030e2d9a085fe","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":440,"wires":[]}]
-{% endrenderFlow %}
+```
+::
## Extracting Substrings
@@ -117,9 +124,11 @@ Getting specific parts of a string is useful for parsing fixed-format data, extr
- `$substring(payload, 6, 5)` on `"Hello World"` gives `"World"`
- `$substring(payload, 6)` (no length) on `"Hello World"` gives `"World"` (all remaining characters)
-{% renderFlow %}
+::render-flow
+```json
[{"id":"1505bbcdda1ef70f","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello World","payloadType":"str","x":510,"y":500,"wires":[["7e13b90c9b8e48de"]]},{"id":"7b985161f48aaf74","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":500,"wires":[]},{"id":"7e13b90c9b8e48de","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Extracting Substrings","rules":[{"t":"set","p":"payload","pt":"msg","to":"$substring(payload, 0, 5)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":500,"wires":[["7b985161f48aaf74"]]}]
-{% endrenderFlow %}
+```
+::
## Trimming Whitespace
@@ -133,9 +142,11 @@ Removing unwanted spaces, tabs, or line breaks from strings prevents comparison
Whitespace from both ends is removed. `" Hello World "` becomes `"Hello World"`. The space between words stays, only edge spaces are removed.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"f43fff4b7a32185d","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":" Hello World ","payloadType":"str","x":510,"y":560,"wires":[["9ed2f66a591cefab"]]},{"id":"603d7024f06979bc","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":560,"wires":[]},{"id":"9ed2f66a591cefab","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Trimming Whitespace","rules":[{"t":"set","p":"payload","pt":"msg","to":"$trim(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":560,"wires":[["603d7024f06979bc"]]}]
-{% endrenderFlow %}
+```
+::
## Changing Case
@@ -149,13 +160,17 @@ Converting string case helps with standardization and comparison since computers
Using `$uppercase(payload)`, the string `"hello world"` becomes `"HELLO WORLD"`. Using `$lowercase(payload)`, the string `"Hello World"` becomes `"hello world"`.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"9b39fb9d0a75e5c2","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello World","payloadType":"str","x":510,"y":620,"wires":[["04389bee4b520eb3"]]},{"id":"3390eac6826821a7","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":620,"wires":[]},{"id":"04389bee4b520eb3","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Changing Case : Lowercase","rules":[{"t":"set","p":"payload","pt":"msg","to":"$lowercase(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":620,"wires":[["3390eac6826821a7"]]}]
-{% endrenderFlow %}
+```
+::
-{% renderFlow %}
+::render-flow
+```json
[{"id":"2bee50ed8273a7d7","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":680,"wires":[]},{"id":"b2d16a456b083325","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Changing Case : Uppercase","rules":[{"t":"set","p":"payload","pt":"msg","to":"$uppercase(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":680,"wires":[["2bee50ed8273a7d7"]]},{"id":"2f20f09b8146b397","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello World","payloadType":"str","x":510,"y":680,"wires":[["b2d16a456b083325"]]}]
-{% endrenderFlow %}
+```
+::
## Replacing Text
@@ -169,9 +184,11 @@ Finding and replacing text within strings lets you correct values, standardize f
All occurrences are replaced. `"I love apples and apples are great"` with `$replace(payload, "apples", "oranges")` gives `"I love oranges and oranges are great"`.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"dfbb9d1ce41c8672","type":"debug","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":740,"wires":[]},{"id":"33d81d6a0d2d0f0c","type":"change","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"Replacing Text","rules":[{"t":"set","p":"payload","pt":"msg","to":"$replace(payload, \"apples\", \"oranges\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":740,"wires":[["dfbb9d1ce41c8672"]]},{"id":"a8e1a932d619fa33","type":"inject","z":"c16e1fb8932e7e73","g":"09a33e651efa47a8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"I love apples and apples are great","payloadType":"str","x":530,"y":740,"wires":[["33d81d6a0d2d0f0c"]]}]
-{% endrenderFlow %}
+```
+::
## Checking String Length
@@ -185,9 +202,11 @@ Determining string length helps with validation or conditional processing.
The string `"Hello"` returns `5`. Use this value in conditions or validation logic.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"3791a3fac7be4833","type":"debug","z":"b446dfa04d79d359","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"length","targetType":"msg","statusVal":"","statusType":"auto","x":1110,"y":1260,"wires":[]},{"id":"fca2213c932b1fea","type":"change","z":"b446dfa04d79d359","name":"Checking String Length","rules":[{"t":"set","p":"length","pt":"msg","to":"$length(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":1260,"wires":[["3791a3fac7be4833"]]},{"id":"706d864345a0c62c","type":"inject","z":"b446dfa04d79d359","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello","payloadType":"str","x":710,"y":1260,"wires":[["fca2213c932b1fea"]]}]
-{% endrenderFlow %}
+```
+::
## Checking if String Contains Text
@@ -201,9 +220,11 @@ Testing whether a string contains specific text helps with filtering and conditi
Returns `true` if found, `false` if not. `"The quick brown fox"` with `$contains(payload, "quick")` returns `true`. Use in Switch nodes to route messages differently based on content.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"eb5fe8fe6e00e603","type":"debug","z":"b446dfa04d79d359","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":1740,"wires":[]},{"id":"daba355f3ca9693f","type":"change","z":"b446dfa04d79d359","name":"Checking if String Contains Text","rules":[{"t":"set","p":"contains","pt":"msg","to":"$contains(payload, \"quick\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":1740,"wires":[["eb5fe8fe6e00e603"]]},{"id":"ca2ab085f8edec8c","type":"inject","z":"b446dfa04d79d359","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"The quick brown fox","payloadType":"str","x":270,"y":1740,"wires":[["daba355f3ca9693f"]]}]
-{% endrenderFlow %}
+```
+::
## Complex String Operations
diff --git a/src/node-red/getting-started/update-node-red.md b/nuxt/content-guides/node-red/getting-started/update-node-red.md
similarity index 88%
rename from src/node-red/getting-started/update-node-red.md
rename to nuxt/content-guides/node-red/getting-started/update-node-red.md
index 260c1d9302..bd16b4bc70 100644
--- a/src/node-red/getting-started/update-node-red.md
+++ b/nuxt/content-guides/node-red/getting-started/update-node-red.md
@@ -1,23 +1,19 @@
---
-eleventyNavigation:
- key: Update Node-RED
- order: 3
- parent: Getting Started
+title: How to Update Node-RED
+metaTitle: "How to Update Node-RED"
+navTitle: Update Node-RED
+navOrder: 3
meta:
- title: How to Update Node-RED
description: Learn how to update Node-RED across different installation methods including npm, Raspberry Pi, Docker, and FlowFuse
keywords: Node-RED update, upgrade Node-RED, Node-RED version, update npm Node-RED
---
-# {{meta.title}}
+# How to Update Node-RED
Regular updates keep your Node-RED installation running smoothly with the latest features, improvements, and bug fixes. Each new release brings enhancements that expand what you can build and improve your development experience. Whether you installed Node-RED through npm, used the Raspberry Pi script, or are running it in Docker, this guide walks you through the update process step by step. We'll also cover how to check your version, update your installation, and handle updates in FlowFuse.
-
-
-
+::cta-image{src="/docs/node-red/getting-started/images/update-node-red-cta-1.png" alt="Update hundreds of Node-RED instances in one click, not one at a time" cta="sign-up" reference="Node-RED: How to Update Node-RED"}
+::
## Checking Your Current Version
@@ -133,4 +129,4 @@ Instead of updating instances manually, you can schedule automatic updates in fl
{data-zoomable}
-FlowFuse will then automatically update your Node-RED instances within the defined maintenance window, ensuring they stay up to date without manual intervention.
\ No newline at end of file
+FlowFuse will then automatically update your Node-RED instances within the defined maintenance window, ensuring they stay up to date without manual intervention.
diff --git a/nuxt/content-guides/node-red/hardware/README.md b/nuxt/content-guides/node-red/hardware/README.md
new file mode 100644
index 0000000000..42cecdf2ac
--- /dev/null
+++ b/nuxt/content-guides/node-red/hardware/README.md
@@ -0,0 +1,26 @@
+---
+title: Setting Up Node-RED on Different Hardware
+metaTitle: "Setting Up Node-RED on Different Hardware"
+navTitle: Hardware
+navOrder: 8
+meta:
+ description: Learn how to set up Node-RED on various hardware platforms, such as Raspberry Pi, Arduino, and more.
+ keywords: node-red, node-red hardware setup, raspberry pi, arduino, siemens iot2050,
+---
+
+# Setting Up Node-RED on Different Hardware
+
+Node-RED is highly versatile and can be set up on a wide range of hardware devices, including popular choices like Raspberry Pi, Ardiuno, Siemens 2050, and more. This flexibility allows you to connect Node-RED to diverse devices and sensors, which enables the creation of interactive and automated systems.
+
+By setting up Node-RED on different hardware, you can easily integrate physical inputs with digital systems. This capability is essential for IoT (Internet of Things) applications, where data from sensors and devices can trigger actions or responses in real-time.
+
+## Resources
+
+Here are some resources to help you get started with Node-RED on diffrent hardware devices:
+
+- [Run Node-RED on Siemens IoT2050](/docs/node-red/hardware/siemens-iot-2050/): In this guide, we will discuss how to install FlowFuse Device agent on Siemens IoT2050.
+- [Setting Node-RED on BLIIOT ARMxy BL340](/docs/node-red/hardware/armxy-bl340/): Guide to setting up Node-RED on BLIIOT ARMxy BL340, including installation and configuration steps.
+- [Setting Node-RED on Raspberry Pi 4](/docs/node-red/hardware/raspberry-pi-4/): Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 4 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
+- [Setting Node-RED on Robustel EG5120](/docs/node-red/hardware/robustel-eg5120/): In this guide, we will discuss how to install FlowFuse Device agent on Robustel EG5120.
+- [Setting up Node-RED on Opto-22 Groov Rio R7](/docs/node-red/hardware/opto-22-groove-rio-7-mm2001-10/): Learn how to install and configure Node-RED on the Opto-22 Groov Rio R7, a rugged edge I/O module for industrial applications.
+- [Setting Up Node-RED on Raspberry Pi 5](/docs/node-red/hardware/raspberry-pi-5/): Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 5 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
diff --git a/nuxt/content-guides/node-red/hardware/armxy-bl340.md b/nuxt/content-guides/node-red/hardware/armxy-bl340.md
new file mode 100644
index 0000000000..41fd339b94
--- /dev/null
+++ b/nuxt/content-guides/node-red/hardware/armxy-bl340.md
@@ -0,0 +1,117 @@
+---
+title: Setting Node-RED on BLIIOT ARMxy BL340
+metaTitle: "Setting Node-RED on BLIIOT ARMxy BL340"
+navTitle: BLIIOT ARMxy BL340
+navOrder: 50
+meta:
+ description: Guide to setting up Node-RED on BLIIOT ARMxy BL340, including installation and configuration steps.
+ keywords: node-red, flowfuse, BLIIOT ARMxy BL340
+image: /docs/node-red/hardware/images/armxy-bl340.jpg
+---
+
+# Setting Node-RED on BLIIOT ARMxy BL340
+
+## Specifications
+
+| | |
+|---|---|
+| Model | BLIIoT ARMxy BL340 Series |
+| RAM MB | 2048 |
+| Processor | ARM Cortex-A53 |
+| GPU | G31 MP2 |
+| IO Points | Optional (GPIO, RS485,CAN,RS232,DI/DO/AI/AO etc.,) |
+| Connectivity | Dual-band Wi-Fi 6, Bluetooth 5.2, Gigabit Ethernet, 4x USB 3.0, 1x USB-C |
+| Clock Speed | Up to 1.4 GHz |
+| Storage | SD, SDHC and SDXC(UHS-I) card |
+| Display Output | HDMI 2.0, DisplayPort |
+| Power Supply | 9~36V DC |
+
+The BLIIOT ARMxy BL340 is a high-performance single-board computer designed for demanding applications, including edge computing, automation, and embedded systems. Featuring an octa-core ARM processor, advanced connectivity options, and support for high-speed storage, it provides a powerful platform for developers and engineers.
+
+Integrating this powerful hardware with FlowFuse not only enhances its capabilities but also simplifies the management and deployment process.
+
+
Note
+
+Exciting Update! FlowFuse is now available as three different products: [FlowFuse Edge for OT teams](/product/edge/), [FlowFuse Hub for IT teams](/product/hub/), and [FlowFuse Fleet](/product/fleet/) for managing devices at scale. Visit the [FlowFuse Product Page](/product/) to learn how the platform enables you to build and manage industrial apps at scale.
+
+
+
+## Prerequisites
+
+Before proceeding with the installation, ensure you have the following:
+
+- **BLIIOT ARMxy BL340** – A functioning device with internet access.
+- **FlowFuse Account** - Ensure you have a FlowFuse account. If not, you can create a free account that allows you to manage up to two edge devices for free. For more information, refer to [FlowFuse Free Tier](/blog/2024/12/flowfuse-release-2-12/)
+- **Sudo Privileges** – Administrator access to install required packages.
+
+## Getting Started
+
+This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the BLIIOT ARMxy BL340, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
+
+### Installing FlowFuse Device Agent
+
+Before we start, it is recommended to update and upgrade your system to ensure all your packages are up to date:
+
+```bash
+sudo apt update && sudo apt upgrade -y
+```
+
+Next, let's install the FlowFuse device agent with the following script.
+
+```bash
+bash <(curl -sL https://raw.githubusercontent.com/FlowFuse/device-agent/main/service/raspbian-install-device-agent.sh)
+```
+
+This script installs the Node.js runtime (if not already installed), sets up the FlowFuse device agent, and configures the device to automatically run the FlowFuse agent on boot and restart it in case of a crash.
+
+To verify that the service is running, use the following command:
+
+```bash
+sudo systemctl status flowfuse-device-agent.service
+```
+
+If running, you should see a result similar to the one shown in the image below:
+
+{data-zoomable}
+
+### Registering the Device to Connect to FlowFuse
+
+Once you have installed the FlowFuse Device Agent, you need to register the hardware to connect it to your FlowFuse team.
+
+For instructions on how to register the hardware with your FlowFuse team, follow the documentation: [Register your Remote Instance](/docs/device-agent/register/).
+
+When registering your hardware, you will be presented with a dialog containing a one-time passcode command that the Device Agent uses to retrieve its configuration. **Make sure to copy it.**
+
+{data-zoomable}
+
+### Connecting Device
+
+Execute the command you have copied with sudo as shown below
+
+```bash
+sudo flowfuse-device-agent -o https://app.flowfuse.com
+```
+
+Once executed, you should see an output similar to the one below, indicating that the FlowFuse Device Agent has been successfully configured:
+
+```bash
+[AGENT] 3/21/2025 7:09:25 PM [info] Entering Device setup...
+[AGENT] 3/21/2025 7:09:27 PM [info] Device setup was successful
+[AGENT] 3/21/2025 7:09:27 PM [info] To start the Device Agent with the new configuration, run the following command:
+[AGENT] 3/21/2025 7:09:27 PM [info] flowfuse-device-agent
+```
+
+Now, you can check the remote instance in the FlowFuse platform, where its status should be displayed as **"running."**.
+
+{data-zoomable}
+
+Now, when your device reboots, the FlowFuse Device Agent will automatically start, ensuring that your BLIIOT ARMxy BL340 remains connected to the FlowFuse platform.
+
+## Accessing Node-RED Editor.
+
+1. Login into your FlowFuse account.
+2. Click on the remote instances option in the left sidebar.
+3. Click on the device and enable the developer mode by clicking on the top right-corner switch.
+4. Once Developer Mode is enabled, click on the Open Editor option located next to the that switch.
+
+For more information refer to [FlowFuse documentation](/docs/user/introduction/#working-with-devices)
diff --git a/src/node-red/hardware/images/GRV-R7-MM1001-10.jpeg b/nuxt/content-guides/node-red/hardware/images/GRV-R7-MM1001-10.jpeg
similarity index 100%
rename from src/node-red/hardware/images/GRV-R7-MM1001-10.jpeg
rename to nuxt/content-guides/node-red/hardware/images/GRV-R7-MM1001-10.jpeg
diff --git a/src/node-red/hardware/images/armxy-bl340.jpg b/nuxt/content-guides/node-red/hardware/images/armxy-bl340.jpg
similarity index 100%
rename from src/node-red/hardware/images/armxy-bl340.jpg
rename to nuxt/content-guides/node-red/hardware/images/armxy-bl340.jpg
diff --git a/src/node-red/hardware/images/configuration-dailog-with-one-time-code.png b/nuxt/content-guides/node-red/hardware/images/configuration-dailog-with-one-time-code.png
similarity index 100%
rename from src/node-red/hardware/images/configuration-dailog-with-one-time-code.png
rename to nuxt/content-guides/node-red/hardware/images/configuration-dailog-with-one-time-code.png
diff --git a/src/node-red/hardware/images/flowfuse-on-robustel-eg5120-installation-complete.png b/nuxt/content-guides/node-red/hardware/images/flowfuse-on-robustel-eg5120-installation-complete.png
similarity index 100%
rename from src/node-red/hardware/images/flowfuse-on-robustel-eg5120-installation-complete.png
rename to nuxt/content-guides/node-red/hardware/images/flowfuse-on-robustel-eg5120-installation-complete.png
diff --git a/src/node-red/hardware/images/flowfuse-on-robustel-eg5120-node-red.png b/nuxt/content-guides/node-red/hardware/images/flowfuse-on-robustel-eg5120-node-red.png
similarity index 100%
rename from src/node-red/hardware/images/flowfuse-on-robustel-eg5120-node-red.png
rename to nuxt/content-guides/node-red/hardware/images/flowfuse-on-robustel-eg5120-node-red.png
diff --git a/src/node-red/hardware/images/flowfuse-on-siemens-iot2050.png b/nuxt/content-guides/node-red/hardware/images/flowfuse-on-siemens-iot2050.png
similarity index 100%
rename from src/node-red/hardware/images/flowfuse-on-siemens-iot2050.png
rename to nuxt/content-guides/node-red/hardware/images/flowfuse-on-siemens-iot2050.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-debug-node.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-debug-node.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-debug-node.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-debug-node.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-device-configuration-dialog.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-device-configuration-dialog.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-device-configuration-dialog.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-device-configuration-dialog.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-dht-sensor.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-dht-sensor.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-dht-sensor.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-dht-sensor.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-inject-node.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-inject-node.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-inject-node.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-inject-node.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-pins.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-pins.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-pins.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi-pins.png
diff --git a/src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi.png b/nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi.png
similarity index 100%
rename from src/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi.png
rename to nuxt/content-guides/node-red/hardware/images/how-to-setup-node-red-on-raspberry-pi.png
diff --git a/src/node-red/hardware/images/raspberry-4-editor.png b/nuxt/content-guides/node-red/hardware/images/raspberry-4-editor.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-4-editor.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-4-editor.png
diff --git a/src/node-red/hardware/images/raspberry-pi-4-b.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-4-b.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-4-b.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-4-b.png
diff --git a/src/node-red/hardware/images/raspberry-pi-4.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-4.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-4.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-4.png
diff --git a/src/node-red/hardware/images/raspberry-pi-5-config-before-flash.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-config-before-flash.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-5-config-before-flash.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-config-before-flash.png
diff --git a/src/node-red/hardware/images/raspberry-pi-5-device-agent.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-device-agent.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-5-device-agent.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-device-agent.png
diff --git a/src/node-red/hardware/images/raspberry-pi-5-editor.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-editor.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-5-editor.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-editor.png
diff --git a/src/node-red/hardware/images/raspberry-pi-5-flash-os.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-flash-os.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-5-flash-os.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-5-flash-os.png
diff --git a/src/node-red/hardware/images/raspberry-pi-5.png b/nuxt/content-guides/node-red/hardware/images/raspberry-pi-5.png
similarity index 100%
rename from src/node-red/hardware/images/raspberry-pi-5.png
rename to nuxt/content-guides/node-red/hardware/images/raspberry-pi-5.png
diff --git a/src/node-red/hardware/images/raspberrypi-5.png b/nuxt/content-guides/node-red/hardware/images/raspberrypi-5.png
similarity index 100%
rename from src/node-red/hardware/images/raspberrypi-5.png
rename to nuxt/content-guides/node-red/hardware/images/raspberrypi-5.png
diff --git a/src/node-red/hardware/images/robustel-eg5120.png b/nuxt/content-guides/node-red/hardware/images/robustel-eg5120.png
similarity index 100%
rename from src/node-red/hardware/images/robustel-eg5120.png
rename to nuxt/content-guides/node-red/hardware/images/robustel-eg5120.png
diff --git a/src/node-red/hardware/images/siemens-iot-2050.jpg b/nuxt/content-guides/node-red/hardware/images/siemens-iot-2050.jpg
similarity index 100%
rename from src/node-red/hardware/images/siemens-iot-2050.jpg
rename to nuxt/content-guides/node-red/hardware/images/siemens-iot-2050.jpg
diff --git a/src/node-red/hardware/images/status-flowfuse.png b/nuxt/content-guides/node-red/hardware/images/status-flowfuse.png
similarity index 100%
rename from src/node-red/hardware/images/status-flowfuse.png
rename to nuxt/content-guides/node-red/hardware/images/status-flowfuse.png
diff --git a/src/node-red/hardware/images/systemctl-status.png b/nuxt/content-guides/node-red/hardware/images/systemctl-status.png
similarity index 100%
rename from src/node-red/hardware/images/systemctl-status.png
rename to nuxt/content-guides/node-red/hardware/images/systemctl-status.png
diff --git a/src/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md b/nuxt/content-guides/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md
similarity index 67%
rename from src/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md
rename to nuxt/content-guides/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md
index 613198ae38..3f0932daa1 100644
--- a/src/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md
+++ b/nuxt/content-guides/node-red/hardware/opto-22-groove-rio-7-mm2001-10.md
@@ -1,29 +1,28 @@
---
-eleventyNavigation:
- key: Opto-22 Groov Epic
- parent: Hardware
+title: Setting up Node-RED on Opto-22 Groov Rio R7
+metaTitle: "Setting up Node-RED on Opto-22 Groov Rio R7"
+navTitle: Opto-22 Groov Epic
+navOrder: 50
meta:
- title: Setting up Node-RED on Opto-22 Groov Rio R7
description: Learn how to install and configure Node-RED on the Opto-22 Groov Rio R7, a rugged edge I/O module for industrial applications.
keywords: node-red, flowfuse, Opto-22 Groov Rio, groov RIO, industrial IoT, edge computing
-image: "/node-red/hardware/images/GRV-R7-MM1001-10.jpeg"
-specifications:
- Model: GRV-R7-MM2001-10
- RAM: 1024 MB
- Processor: ARM Cortex-A8, 1 GHz
- I/O Channels: 10 multi-signal, multifunction channels (analog I/O, temperature, discrete I/O, mechanical relays)
- Connectivity:
- - Dual switched Gigabit Ethernet
- - USB 2.0 (host)
- - Power over Ethernet (PoE)
- - 10–32 VDC power input
- Clock Speed: 1 GHz
- Storage:
- - 4 GB eMMC (internal)
- - USB memory stick support (up to 32 GB)
-layout: layouts/hardware.njk
+image: /docs/node-red/hardware/images/GRV-R7-MM1001-10.jpeg
---
+# Setting up Node-RED on Opto-22 Groov Rio R7
+
+## Specifications
+
+| | |
+|---|---|
+| Model | GRV-R7-MM2001-10 |
+| RAM | 1024 MB |
+| Processor | ARM Cortex-A8, 1 GHz |
+| I/O Channels | 10 multi-signal, multifunction channels (analog I/O, temperature, discrete I/O, mechanical relays) |
+| Connectivity | Dual switched Gigabit Ethernet,USB 2.0 (host),Power over Ethernet (PoE),10–32 VDC power input |
+| Clock Speed | 1 GHz |
+| Storage | 4 GB eMMC (internal),USB memory stick support (up to 32 GB) |
+
The Opto-22 Groov Rio R7 is a rugged edge I/O module designed for industrial applications. Equipped with a powerful ARM Cortex-A8 processor, versatile I/O channels, and various connectivity options, it’s an ideal solution for edge computing and industrial IoT.
## Prerequisites
@@ -31,14 +30,23 @@ The Opto-22 Groov Rio R7 is a rugged edge I/O module designed for industrial app
Before proceeding with the installation, ensure you have the following:
- **Opto-22 Groov Rio R7** – A functioning device with internet access.
-- **FlowFuse Account** - You need an active FlowFuse account to access the platform and configure your instance. If you do not have one, please visit the FlowFuse website and [sign up]({% include "sign-up-url.njk" %}) for a new account before proceeding.
+- **FlowFuse Account** - You need an active FlowFuse account to access the platform and configure your instance. If you do not have one, please visit the FlowFuse website and [sign up](https://app.flowfuse.com/account/create) for a new account before proceeding.
- **Sudo Privileges** – Administrator access to install required packages.
## Getting Started
This guide will walk you through setting up Node-RED on the Groov Rio R7 using the FlowFuse Device Agent, allowing you to manage, scale, and secure your remote instances effectively.
-{% include "hardware/system/opto-22-groove-rio.md" %}
+### Installing FlowFuse Device Agent
+
+Before starting the installation, it is recommended to update your system to
+ensure that all your packages are up to date. You can use groov manage, which
+acts as the command central for your groov RIO devices. For detailed
+instructions on how to update the system, [watch this video](https://www.opto22.com/support/resources-tools/videos/playlist-what-is-groov-epic?wchannelid=61lkudfc8c&wmediaid=mxzzp2kudx).
+
+This guide is written for the firmware version of: `4.0.2-b.194`. Node.JS 20 is
+available on the device, and you should be good to go to register the edge device
+on FlowFuse.
### Registering the Device to Connect to FlowFuse
diff --git a/nuxt/content-guides/node-red/hardware/raspberry-pi-4.md b/nuxt/content-guides/node-red/hardware/raspberry-pi-4.md
new file mode 100644
index 0000000000..c43584b8dc
--- /dev/null
+++ b/nuxt/content-guides/node-red/hardware/raspberry-pi-4.md
@@ -0,0 +1,118 @@
+---
+title: Setting Node-RED on Raspberry Pi 4
+metaTitle: "Setting Node-RED on Raspberry Pi 4"
+navTitle: Raspberry Pi 4
+navOrder: 50
+meta:
+ description: Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 4 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
+ keywords: node-red, flowfuse, raspberry pi, raspberry pi 4
+image: /docs/node-red/hardware/images/raspberry-pi-4-b.png
+---
+
+# Setting Node-RED on Raspberry Pi 4
+
+## Specifications
+
+| | |
+|---|---|
+| Model | Raspberry Pi 4 B 8GB |
+| RAM MB | 8192 |
+| Processor | Broadcom BCM2711, ARM Cortex-A72 (ARMv8-A), 4 (Quad-core) |
+| GPIO | (Fully backwar ds-compatible with previous boards), Standard 40-pin GPIO Header |
+| Connectivity | Dual-band Wi-Fi, Bluetooth 5.0, Gigabit Ethernet, 2x USB 3.0, 2x USB 2.0 |
+| Clock Speed | 1.5 GHz |
+| Storage | microSD |
+
+## Raspberry Pi OS Installation
+
+To set up your Raspberry Pi 4 for use with Node-RED and FlowFuse, follow these steps:
+
+### Flashing Raspberry Pi OS
+
+1. Use the [official Raspberry Pi Imager](https://www.raspberrypi.com/software/) to flash the 64-bit version of Raspberry Pi OS to an SD card.
+
+
+
+2. Before writing to the SD card, configure the OS for headless mode, including Wi-Fi, SSH, and authentication settings.
+
+
+
+3. Write the OS and configuration to the SD card. This process takes about 10 minutes.
+
+4. Insert the SD card into the Raspberry Pi 4 and power it on. The device should appear on your network after a minute or so.
+
+5. Connect to the Raspberry Pi using SSH:
+
+ ```sh
+ ssh pi@raspberrypi.local
+ ```
+
+## Getting Started
+
+This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Raspberry Pi 4, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
+
+### Installing FlowFuse Device Agent
+
+Before we start, it is recommended to update and upgrade your system to ensure all your packages are up to date:
+
+```bash
+sudo apt update && sudo apt upgrade -y
+```
+
+Next, let's install the FlowFuse device agent with the following script.
+
+```bash
+bash <(curl -sL https://raw.githubusercontent.com/FlowFuse/device-agent/main/service/raspbian-install-device-agent.sh)
+```
+
+This script installs the Node.js runtime (if not already installed), sets up the FlowFuse device agent, and configures the device to automatically run the FlowFuse agent on boot and restart it in case of a crash.
+
+To verify that the service is running, use the following command:
+
+```bash
+sudo systemctl status flowfuse-device-agent.service
+```
+
+If running, you should see a result similar to the one shown in the image below:
+
+{data-zoomable}
+
+### Registering the Device to Connect to FlowFuse
+
+Once you have installed the FlowFuse Device Agent, you need to register the hardware to connect it to your FlowFuse team.
+
+For instructions on how to register the hardware with your FlowFuse team, follow the documentation: [Register your Remote Instance](/docs/device-agent/register/).
+
+When registering your hardware, you will be presented with a dialog containing a one-time passcode command that the Device Agent uses to retrieve its configuration. **Make sure to copy it.**
+
+{data-zoomable}
+
+### Connecting Device
+
+Execute the command you have copied with sudo as shown below
+
+```bash
+sudo flowfuse-device-agent -o https://app.flowfuse.com
+```
+
+Once executed, you should see an output similar to the one below, indicating that the FlowFuse Device Agent has been successfully configured:
+
+```bash
+[AGENT] 3/21/2025 7:09:25 PM [info] Entering Device setup...
+[AGENT] 3/21/2025 7:09:27 PM [info] Device setup was successful
+[AGENT] 3/21/2025 7:09:27 PM [info] To start the Device Agent with the new configuration, run the following command:
+[AGENT] 3/21/2025 7:09:27 PM [info] flowfuse-device-agent
+```
+
+Now, you can check the remote instance in the FlowFuse platform, where its status should be displayed as **"running."**.
+
+{data-zoomable}
+
+## Accessing Node-RED Editor.
+
+1. Login into your FlowFuse account.
+2. Click on the remote instances option in the left sidebar.
+3. Click on the device and enable the developer mode by clicking on the top right-corner switch.
+4. Once Developer Mode is enabled, click on the Open Editor option located next to the that switch.
+
+For more information refer to [FlowFuse documentation](/docs/user/introduction/#working-with-devices)
diff --git a/nuxt/content-guides/node-red/hardware/raspberry-pi-5.md b/nuxt/content-guides/node-red/hardware/raspberry-pi-5.md
new file mode 100644
index 0000000000..a523bf0c82
--- /dev/null
+++ b/nuxt/content-guides/node-red/hardware/raspberry-pi-5.md
@@ -0,0 +1,118 @@
+---
+title: Setting Up Node-RED on Raspberry Pi 5
+metaTitle: "Setting Up Node-RED on Raspberry Pi 5"
+navTitle: Raspberry Pi 5
+navOrder: 50
+meta:
+ description: Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 5 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
+ keywords: node-red, flowfuse, raspberry pi, raspberry pi 5
+image: /docs/node-red/hardware/images/raspberrypi-5.png
+---
+
+# Setting Up Node-RED on Raspberry Pi 5
+
+## Specifications
+
+| | |
+|---|---|
+| Model | Raspberry Pi 5 Model 8GB |
+| RAM MB | 8192 |
+| Processor | Broadcom BCM2712, ARM Cortex-A76 (ARMv8.2-A), 4 (Quad-core) |
+| GPIO | Standard 40-pin GPIO Header |
+| Connectivity | 2 × USB 2.0 Ports, 2 × USB 3.0 Ports, Bluetooth 5.0, USB-C, Wi-Fi + Bluetooth® Low Energy |
+| Clock Speed | 2.4 GHz |
+| Storage | microSD |
+
+## Raspberry Pi OS Installation
+
+To set up your Raspberry Pi 5 for use with Node-RED and FlowFuse, follow these steps:
+
+### Flashing Raspberry Pi OS
+
+1. Use the [official Raspberry Pi Imager](https://www.raspberrypi.com/software/) to flash the 64-bit version of Raspberry Pi OS to an SD card.
+
+
+
+2. Before writing to the SD card, configure the OS for headless mode, including Wi-Fi, SSH, and authentication settings.
+
+
+
+3. Write the OS and configuration to the SD card. This process takes about 10 minutes.
+
+4. Insert the SD card into the Raspberry Pi 5 and power it on. The device should appear on your network after a minute or so.
+
+5. Connect to the Raspberry Pi using SSH:
+
+ ```sh
+ ssh pi@raspberrypi.local
+ ```
+
+## Getting Started
+
+This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Raspberry Pi 5, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
+
+### Installing FlowFuse Device Agent
+
+Before we start, it is recommended to update and upgrade your system to ensure all your packages are up to date:
+
+```bash
+sudo apt update && sudo apt upgrade -y
+```
+
+Next, let's install the FlowFuse device agent with the following script.
+
+```bash
+bash <(curl -sL https://raw.githubusercontent.com/FlowFuse/device-agent/main/service/raspbian-install-device-agent.sh)
+```
+
+This script installs the Node.js runtime (if not already installed), sets up the FlowFuse device agent, and configures the device to automatically run the FlowFuse agent on boot and restart it in case of a crash.
+
+To verify that the service is running, use the following command:
+
+```bash
+sudo systemctl status flowfuse-device-agent.service
+```
+
+If running, you should see a result similar to the one shown in the image below:
+
+{data-zoomable}
+
+### Registering the Device to Connect to FlowFuse
+
+Once you have installed the FlowFuse Device Agent, you need to register the hardware to connect it to your FlowFuse team.
+
+For instructions on how to register the hardware with your FlowFuse team, follow the documentation: [Register your Remote Instance](/docs/device-agent/register/).
+
+When registering your hardware, you will be presented with a dialog containing a one-time passcode command that the Device Agent uses to retrieve its configuration. **Make sure to copy it.**
+
+{data-zoomable}
+
+### Connecting Device
+
+Execute the command you have copied with sudo as shown below
+
+```bash
+sudo flowfuse-device-agent -o https://app.flowfuse.com
+```
+
+Once executed, you should see an output similar to the one below, indicating that the FlowFuse Device Agent has been successfully configured:
+
+```bash
+[AGENT] 3/21/2025 7:09:25 PM [info] Entering Device setup...
+[AGENT] 3/21/2025 7:09:27 PM [info] Device setup was successful
+[AGENT] 3/21/2025 7:09:27 PM [info] To start the Device Agent with the new configuration, run the following command:
+[AGENT] 3/21/2025 7:09:27 PM [info] flowfuse-device-agent
+```
+
+Now, you can check the remote instance in the FlowFuse platform, where its status should be displayed as **"running."**.
+
+{data-zoomable}
+
+## Accessing Node-RED Editor.
+
+1. Login into your FlowFuse account.
+2. Click on the remote instances option in the left sidebar.
+3. Click on the device and enable the developer mode by clicking on the top right-corner switch.
+4. Once Developer Mode is enabled, click on the Open Editor option located next to the that switch.
+
+For more information refer to [FlowFuse documentation](/docs/user/introduction/#working-with-devices)
diff --git a/nuxt/content-guides/node-red/hardware/robustel-eg5120.md b/nuxt/content-guides/node-red/hardware/robustel-eg5120.md
new file mode 100644
index 0000000000..4864b1475a
--- /dev/null
+++ b/nuxt/content-guides/node-red/hardware/robustel-eg5120.md
@@ -0,0 +1,98 @@
+---
+title: Setting Node-RED on Robustel EG5120
+metaTitle: "Setting Node-RED on Robustel EG5120"
+navTitle: Robustel EG5120
+navOrder: 50
+meta:
+ description: In this guide, we will discuss how to install FlowFuse Device agent on Robustel EG5120.
+ keywords: node-red, flowfuse, robustel eg5120
+image: /docs/node-red/hardware/images/robustel-eg5120.png
+---
+
+# Setting Node-RED on Robustel EG5120
+
+## Specifications
+
+| | |
+|---|---|
+| Model | Robustel EG5120 |
+| RAM MB | 2048 |
+| Processor | Broadcom BCM2711, ARM Cortex-A72 (ARMv8-A), 4 (Quad-core) |
+| GPIO | Standard 40-pin GPIO Header |
+| Connectivity | Dual-band Wi-Fi, Bluetooth 5.0, Gigabit Ethernet, 2x USB 3.0, 2x USB 2.0 |
+| Clock Speed | 1.5 GHz |
+| Storage | microSD |
+
+The [Robustel EG5120](https://www.robustel.com/product/eg5120-industrial-edge-computing-gateway/) is a versatile gateway that facilitates robust connectivity for industrial IoT applications. Integrating this powerful hardware with FlowFuse not only enhances its capabilities but also simplifies the management and deployment process. In this documentation, we’ll walk through the steps to integrate the Robustel EG5120 with FlowFuse.
+
+The [Robustel EG5120](https://www.robustel.com/product/eg5120-industrial-edge-computing-gateway/), equipped with Linux-based Debian 11 supporting a wide variety of programming languages including Node.js, offers robust connectivity options. When combined with FlowFuse, this gateway becomes even more powerful, enabling seamless device management and deployment.
+
+The Robustel EG5120 supports multiple connectivity options including Ethernet, Wi-Fi, and cellular networks, which are essential for flexible deployments in various industrial scenarios. Its built-in support for Bluetooth, cellular connectivity, RS232, RS485, and Modbus facilitates seamless integration with a wide array of IoT devices and services. This blog will guide you through using FlowFuse to effectively manage your Node-RED instance, enhancing both the security and scalability of your IoT applications.
+
+## Getting Started
+
+This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Robustel EG5120, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
+
+### Installing FlowFuse Device Agent
+
+Before we start, it is recommended to update and upgrade your system to ensure all your packages are up to date:
+
+```bash
+sudo apt update && sudo apt upgrade -y
+```
+
+Next, let's install the FlowFuse device agent with the following script.
+
+```bash
+bash <(curl -sL https://raw.githubusercontent.com/FlowFuse/device-agent/main/service/raspbian-install-device-agent.sh)
+```
+
+This script installs the Node.js runtime (if not already installed), sets up the FlowFuse device agent, and configures the device to automatically run the FlowFuse agent on boot and restart it in case of a crash.
+
+To verify that the service is running, use the following command:
+
+```bash
+sudo systemctl status flowfuse-device-agent.service
+```
+
+If running, you should see a result similar to the one shown in the image below:
+
+{data-zoomable}
+
+### Registering the Device to Connect to FlowFuse
+
+Once you have installed the FlowFuse Device Agent, you need to register the hardware to connect it to your FlowFuse team.
+
+For instructions on how to register the hardware with your FlowFuse team, follow the documentation: [Register your Remote Instance](/docs/device-agent/register/).
+
+When registering your hardware, you will be presented with a dialog containing a one-time passcode command that the Device Agent uses to retrieve its configuration. **Make sure to copy it.**
+
+{data-zoomable}
+
+### Connecting Device
+
+Execute the command you have copied with sudo as shown below
+
+```bash
+sudo flowfuse-device-agent -o https://app.flowfuse.com
+```
+
+Once executed, you should see an output similar to the one below, indicating that the FlowFuse Device Agent has been successfully configured:
+
+```bash
+[AGENT] 3/21/2025 7:09:25 PM [info] Entering Device setup...
+[AGENT] 3/21/2025 7:09:27 PM [info] Device setup was successful
+[AGENT] 3/21/2025 7:09:27 PM [info] To start the Device Agent with the new configuration, run the following command:
+[AGENT] 3/21/2025 7:09:27 PM [info] flowfuse-device-agent
+```
+
+Now, you can check the remote instance in the FlowFuse platform, where its status should be displayed as **"running."**.
+
+## Accessing Node-RED Editor.
+
+1. Login into your FlowFuse account.
+2. Click on the remote instances option in the left sidebar.
+3. Click on the device and enable the developer mode by clicking on the top right-corner switch.
+4. Once Developer Mode is enabled, click on the Open Editor option located next to the that switch.
+
+For more information refer to [FlowFuse documentation](/docs/user/introduction/#working-with-devices)
diff --git a/src/node-red/hardware/siemens-iot-2050.md b/nuxt/content-guides/node-red/hardware/siemens-iot-2050.md
similarity index 90%
rename from src/node-red/hardware/siemens-iot-2050.md
rename to nuxt/content-guides/node-red/hardware/siemens-iot-2050.md
index 686a870d47..66eda7a402 100644
--- a/src/node-red/hardware/siemens-iot-2050.md
+++ b/nuxt/content-guides/node-red/hardware/siemens-iot-2050.md
@@ -1,23 +1,28 @@
---
-eleventyNavigation:
- key: Siemens IoT2050
- parent: Hardware
+title: Run Node-RED on Siemens IoT2050
+metaTitle: "Run Node-RED on Siemens IoT2050"
+navTitle: Siemens IoT2050
+navOrder: 50
meta:
- title: Run Node-RED on Siemens IoT2050
description: In this guide, we will discuss how to install FlowFuse Device agent on Siemens IoT2050.
keywords: node-red, flowfuse, siemens iot2050 flowfuse
-image: "/node-red/hardware/images/siemens-iot-2050.jpg"
-specifications:
- Model: IOT2050 Basic
- RAM_MB: 1024
- Processor: ARM TI AM6528 GP
- GPIO: x20 Digital I/O
- Connectivity: 1x RS 232 / 422 / 485, Ethernet, USB 2.0, Arduino, mPCIe
- Clock Speed: 1 GHz
- Storage: SD Card
-layout: layouts/hardware.njk
+image: /docs/node-red/hardware/images/siemens-iot-2050.jpg
---
+# Run Node-RED on Siemens IoT2050
+
+## Specifications
+
+| | |
+|---|---|
+| Model | IOT2050 Basic |
+| RAM MB | 1024 |
+| Processor | ARM TI AM6528 GP |
+| GPIO | x20 Digital I/O |
+| Connectivity | 1x RS 232 / 422 / 485, Ethernet, USB 2.0, Arduino, mPCIe |
+| Clock Speed | 1 GHz |
+| Storage | SD Card |
+
Siemens [announced](https://press.siemens.com/global/en/pressrelease/new-siemens-gateway-between-cloud-company-it-and-production) the IoT2000 series in March of 2020. With this tool many have been using it to function as a gateway between their plant operations and cloud infrastructure. Onboard it came with Node-RED pre-installed. To manage Node-RED as an organization the FlowFuse agent is recommended, this documentation shows you how to do so.
Warning: Later in the documentation we will be updating Node.js. This will break MRAA library. This will prevent communication to the GPIO of the device.
diff --git a/nuxt/content-guides/node-red/integration-technologies/README.md b/nuxt/content-guides/node-red/integration-technologies/README.md
new file mode 100644
index 0000000000..c5006825ff
--- /dev/null
+++ b/nuxt/content-guides/node-red/integration-technologies/README.md
@@ -0,0 +1,23 @@
+---
+title: Using Different Technologies for Building Applications with Node-RED.
+metaTitle: "Building Applications with Node-RED"
+navTitle: Integration technologies
+navOrder: 6
+meta:
+ description: Learn how to leverage various integration technologies with Node-RED for building robust and interconnected applications.
+ keywords: node-red, flowfuse, node-red integration, integration technologies, webhook, rest api
+---
+
+# Using Different Technologies for Building Applications with Node-RED.
+
+Developing powerful and scalable applications frequently necessitates the integration of various technologies. This integration is crucial for creating seamless and efficient systems that can handle complex tasks and large volumes of data. Whether you're working with REST APIs to enable communication between different services or implementing GraphQL for more efficient data querying, the ability to blend these technologies effectively is essential for modern application development.
+
+Node-RED offers a versatile and robust platform to meet these needs. Its intuitive flow-based interface allows developers to easily design and deploy sophisticated workflows, which makes it an invaluable tool for integrating REST APIs, GraphQL, webhooks, and more.
+
+## Resources
+
+Here are some resources to help you integrate Node-RED with various different technologies:
+
+- [Creating REST API's with Node-RED](/docs/node-red/integration-technologies/rest/): Learn how to create REST APIs in Node-RED and fetch data from an API.
+- [Integrating GraphQL APIs in Node-RED](/docs/node-red/integration-technologies/graphql/): Learn how to integrate GraphQL APIs in Node-RED. This guide covers setting up endpoints, executing queries, handling variables, and using mutations for dynamic data.
+- [Using Webhook with Node-RED](/docs/node-red/integration-technologies/webhook/): Learn how to seamlessly integrate webhooks into your Node-RED applications for automating tasks and enhancing communication.
diff --git a/src/node-red/integration-technologies/graphql.md b/nuxt/content-guides/node-red/integration-technologies/graphql.md
similarity index 98%
rename from src/node-red/integration-technologies/graphql.md
rename to nuxt/content-guides/node-red/integration-technologies/graphql.md
index 2e11f318c7..c5e4ee18d9 100644
--- a/src/node-red/integration-technologies/graphql.md
+++ b/nuxt/content-guides/node-red/integration-technologies/graphql.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: GraphQL API
- parent: "Integration Technologies"
+title: Integrating GraphQL APIs in Node-RED
+metaTitle: "Integrating GraphQL APIs in Node-RED"
+navTitle: GraphQL API
+navOrder: 50
meta:
- title: Integrating GraphQL APIs in Node-RED
- description: Learn how to integrate GraphQL APIs in Node-RED. This guide covers setting up endpoints, executing queries, handling variables, and using mutations for dynamic data.
- keywords: node-red, flowfuse, graphql apis, queries, mutations
+ description: Learn how to integrate GraphQL APIs in Node-RED. This guide covers setting up endpoints, executing queries, handling variables, and using mutations for dynamic data.
+ keywords: node-red, flowfuse, graphql apis, queries, mutations
---
-# {{meta.title}}
+# Integrating GraphQL APIs in Node-RED
GraphQL is transforming the way APIs are designed. Unlike traditional REST APIs, which often require multiple requests to different endpoints, GraphQL provides a single, flexible endpoint that allows you to fetch exactly the data you need, nothing more, nothing less. In this article, you will learn how to integrate GraphQL with Node-RED and build APIs that efficiently serve your application's data requirements.
@@ -507,6 +507,8 @@ Notice how the response includes all fields from `DeviceBasicInfo` (id, name, ty
The following example flow demonstrates creating, reading, updating, and deleting data using GraphQL, including performing queries with fragments for reusable field selections. This flow and the GraphQL node are for demonstration purposes only and do not include a demo API.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"7cb18349cfb7f014","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Get Single Device By ID","graphql":"fd163a325aa21cdb","format":"text","template":"query GetDevice($id: ID!) {\n device(id: $id) {\n id\n name\n type\n model\n location\n lastSeenStatus\n maintenanceDue\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":490,"y":240,"wires":[["1515cbad98355c5f"],["0c4068bd1821923b"]]},{"id":"6ac3b625b7e6e954","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{\"id\":\"1\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":240,"wires":[["7cb18349cfb7f014"]]},{"id":"66d017b14ed8c60d","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Get Devices","graphql":"fd163a325aa21cdb","format":"text","template":"query GetDevices {\n devices {\n id\n name\n type\n location\n lastSeenStatus\n createdAt\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":450,"y":140,"wires":[["fdcc15f68872b4d0"],["beb63abd92f155ce"]]},{"id":"572aa9e659f5e27e","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":140,"wires":[["66d017b14ed8c60d"]]},{"id":"6d4f9a2cb159d8e5","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Create Device","graphql":"fd163a325aa21cdb","format":"text","template":"mutation CreateDevice($input: DeviceInput!) {\n createDevice(input: $input) {\n id\n name\n type\n model\n location\n createdAt\n success\n errors {\n field\n message\n }\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":460,"y":340,"wires":[["f5527e179e1c8911"],["9fc70e8f8715f994"]]},{"id":"e0b89bf0a47dbae3","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{\"input\":{\"name\":\"Smart Thermostat\",\"type\":\"Controller\",\"model\":\"Nest V3\",\"location\":\"Office Area\"}}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":340,"wires":[["6d4f9a2cb159d8e5"]]},{"id":"fdcc15f68872b4d0","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":120,"wires":[]},{"id":"beb63abd92f155ce","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":160,"wires":[]},{"id":"1515cbad98355c5f","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":220,"wires":[]},{"id":"0c4068bd1821923b","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":260,"wires":[]},{"id":"f5527e179e1c8911","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":320,"wires":[]},{"id":"9fc70e8f8715f994","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":360,"wires":[]},{"id":"e0d2739c55386644","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Create Device","graphql":"fd163a325aa21cdb","format":"text","template":"mutation CreateDevice($input: DeviceInput!) {\n createDevice(input: $input) {\n id\n name\n type\n model\n location\n createdAt\n success\n errors {\n field\n message\n }\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":460,"y":440,"wires":[["f5c2e0346b4979aa"],["597bac49938cd7bc"]]},{"id":"b45422c8bffaa52d","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{\"input\":{\"name\":\"Smart Thermostat\",\"type\":\"Controller\",\"model\":\"Nest V3\",\"location\":\"Office Area\"}}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":440,"wires":[["e0d2739c55386644"]]},{"id":"f5c2e0346b4979aa","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":420,"wires":[]},{"id":"597bac49938cd7bc","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":460,"wires":[]},{"id":"dae18c118b5a7d25","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Update Device","graphql":"fd163a325aa21cdb","format":"text","template":"mutation UpdateDevice($id: ID!, $input: DeviceUpdateInput!) {\n updateDevice(id: $id, input: $input) {\n id\n name\n location\n lastSeenStatus\n updatedAt\n success\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":460,"y":540,"wires":[["8372c53fd374ca0c"],["81ee27d5d002cdf7"]]},{"id":"06e715476d4a05a1","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{ \"id\": \"1\", \"input\": { \"location\": \"Factory Floor 3\", \"lastSeenStatus\": \"Maintenance\" } }","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":540,"wires":[["dae18c118b5a7d25"]]},{"id":"8372c53fd374ca0c","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":520,"wires":[]},{"id":"81ee27d5d002cdf7","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":560,"wires":[]},{"id":"b59476221e135579","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Deactivate Device","graphql":"fd163a325aa21cdb","format":"text","template":"mutation DeactivateDevice($id: ID!) {\n deactivateDevice(id: $id) {\n id\n isActive\n deactivatedAt\n success\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":470,"y":640,"wires":[["bc0b5067c9b64b4a"],["9bcd78c44b2d304a"]]},{"id":"2f45ba641ea8d272","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{ \"id\": \"4\" }","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":640,"wires":[["b59476221e135579"]]},{"id":"bc0b5067c9b64b4a","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":620,"wires":[]},{"id":"9bcd78c44b2d304a","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":660,"wires":[]},{"id":"7d7e6689f0c42fac","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"fragment","graphql":"fd163a325aa21cdb","format":"text","template":"fragment DeviceBasicInfo on Device {\n id\n name\n type\n location\n createdAt\n}\n\nfragment DeviceOperationalInfo on Device {\n ...DeviceBasicInfo\n lastSeenStatus\n lastSeenAt\n maintenanceDue\n}\n\nquery GetDeviceProfile($deviceId: ID!) {\n device(id: $deviceId) {\n ...DeviceOperationalInfo\n }\n}","syntax":"mustache","token":"","showDebug":false,"x":440,"y":740,"wires":[["e818060c00087930"],["621b732245671f2f"]]},{"id":"ac37b7540e536255","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{ \"deviceId\": \"4\" }","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":740,"wires":[["7d7e6689f0c42fac"]]},{"id":"e818060c00087930","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":720,"wires":[]},{"id":"621b732245671f2f","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":760,"wires":[]},{"id":"f99baa69918d2a9a","type":"graphql","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Pagination","graphql":"fd163a325aa21cdb","format":"text","template":"query GetDevicesPaginated($limit: Int = 10, $offset: Int = 0, $searchTerm: String) {\n devices(limit: $limit, offset: $offset, search: $searchTerm) {\n id\n name\n type\n location\n lastSeenStatus\n createdAt\n lastSeenAt\n }\n deviceCount(search: $searchTerm)\n}","syntax":"mustache","token":"","showDebug":false,"x":450,"y":840,"wires":[["368fbd3d4f756b6a"],["cc1ef9d881065082"]]},{"id":"509af177c480ed03","type":"inject","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"","props":[{"p":"variables","v":"{ \"deviceId\": \"4\" }","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":840,"wires":[["f99baa69918d2a9a"]]},{"id":"368fbd3d4f756b6a","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Result","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":820,"wires":[]},{"id":"cc1ef9d881065082","type":"debug","z":"98a60b6dd0896e47","g":"9a0c28902989b739","name":"Error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":860,"wires":[]},{"id":"fd163a325aa21cdb","type":"graphql-server","name":"","endpoint":"none","token":""},{"id":"574504396881aa85","type":"global-config","env":[],"modules":{"node-red-contrib-graphql":"2.2.0"}}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/integration-technologies/images/change-node-prepare-data-chart.png b/nuxt/content-guides/node-red/integration-technologies/images/change-node-prepare-data-chart.png
similarity index 100%
rename from src/node-red/integration-technologies/images/change-node-prepare-data-chart.png
rename to nuxt/content-guides/node-red/integration-technologies/images/change-node-prepare-data-chart.png
diff --git a/src/node-red/integration-technologies/images/change-node-set-downloads-payload.png b/nuxt/content-guides/node-red/integration-technologies/images/change-node-set-downloads-payload.png
similarity index 100%
rename from src/node-red/integration-technologies/images/change-node-set-downloads-payload.png
rename to nuxt/content-guides/node-red/integration-technologies/images/change-node-set-downloads-payload.png
diff --git a/src/node-red/integration-technologies/images/chart-with-data.png b/nuxt/content-guides/node-red/integration-technologies/images/chart-with-data.png
similarity index 100%
rename from src/node-red/integration-technologies/images/chart-with-data.png
rename to nuxt/content-guides/node-red/integration-technologies/images/chart-with-data.png
diff --git a/src/node-red/integration-technologies/images/dashboard-config-chart.png b/nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-chart.png
similarity index 100%
rename from src/node-red/integration-technologies/images/dashboard-config-chart.png
rename to nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-chart.png
diff --git a/src/node-red/integration-technologies/images/dashboard-config-ui-base.png b/nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-ui-base.png
similarity index 100%
rename from src/node-red/integration-technologies/images/dashboard-config-ui-base.png
rename to nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-ui-base.png
diff --git a/src/node-red/integration-technologies/images/dashboard-config-ui-group.png b/nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-ui-group.png
similarity index 100%
rename from src/node-red/integration-technologies/images/dashboard-config-ui-group.png
rename to nuxt/content-guides/node-red/integration-technologies/images/dashboard-config-ui-group.png
diff --git a/src/node-red/integration-technologies/images/http-get-npmapi.png b/nuxt/content-guides/node-red/integration-technologies/images/http-get-npmapi.png
similarity index 100%
rename from src/node-red/integration-technologies/images/http-get-npmapi.png
rename to nuxt/content-guides/node-red/integration-technologies/images/http-get-npmapi.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-change-node-formating-sensor-data.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change-node-formating-sensor-data.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-change-node-formating-sensor-data.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change-node-formating-sensor-data.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-change-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-change-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-change1-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change1-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-change1-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change1-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-change2-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change2-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-change2-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-change2-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-dht-sensor-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-dht-sensor-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-dht-sensor-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-dht-sensor-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-diagram.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-diagram.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-diagram.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-diagram.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-flow.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-flow.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-flow.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-flow.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-function-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-function-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-function-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-function-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-how-webhook-works.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-how-webhook-works.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-how-webhook-works.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-how-webhook-works.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-http-in-node-endpoint-for-receiving-data-from-server-2.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-http-in-node-endpoint-for-receiving-data-from-server-2.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-http-in-node-endpoint-for-receiving-data-from-server-2.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-http-in-node-endpoint-for-receiving-data-from-server-2.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-request-node-sending-request-to-server3.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-request-node-sending-request-to-server3.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-request-node-sending-request-to-server3.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-request-node-sending-request-to-server3.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-scheduled-maintenance-table-dashboard-view.webm b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-scheduled-maintenance-table-dashboard-view.webm
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-scheduled-maintenance-table-dashboard-view.webm
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-scheduled-maintenance-table-dashboard-view.webm
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-sensor2-inject-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-sensor2-inject-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-sensor2-inject-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-sensor2-inject-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-server-1-instance.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-1-instance.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-server-1-instance.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-1-instance.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-server-2-instance.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-2-instance.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-server-2-instance.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-2-instance.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-server-3-instance.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-3-instance.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-server-3-instance.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-server-3-instance.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-switch-node.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-switch-node.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-switch-node.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-switch-node.png
diff --git a/src/node-red/integration-technologies/images/using-webhook-with-node-red-webhook-trigger.png b/nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-webhook-trigger.png
similarity index 100%
rename from src/node-red/integration-technologies/images/using-webhook-with-node-red-webhook-trigger.png
rename to nuxt/content-guides/node-red/integration-technologies/images/using-webhook-with-node-red-webhook-trigger.png
diff --git a/src/node-red/integration-technologies/images/webhooks-node-red.png b/nuxt/content-guides/node-red/integration-technologies/images/webhooks-node-red.png
similarity index 100%
rename from src/node-red/integration-technologies/images/webhooks-node-red.png
rename to nuxt/content-guides/node-red/integration-technologies/images/webhooks-node-red.png
diff --git a/src/node-red/integration-technologies/rest.md b/nuxt/content-guides/node-red/integration-technologies/rest.md
similarity index 95%
rename from src/node-red/integration-technologies/rest.md
rename to nuxt/content-guides/node-red/integration-technologies/rest.md
index ed358518b4..a25e51f494 100644
--- a/src/node-red/integration-technologies/rest.md
+++ b/nuxt/content-guides/node-red/integration-technologies/rest.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: REST API
- parent: "Integration Technologies"
+title: Creating REST API's with Node-RED
+metaTitle: "Creating REST API's with Node-RED"
+navTitle: REST API
+navOrder: 50
meta:
- title: Creating REST API's with Node-RED
- description: Learn how to create REST APIs in Node-RED and fetch data from an API.
- keywords: node-red, flowfuse, rest api
+ description: Learn how to create REST APIs in Node-RED and fetch data from an API.
+ keywords: node-red, flowfuse, rest api
---
-# {{meta.title}}
+# Creating REST API's with Node-RED
REST APIs are how applications talk to each other over the web. They use standard HTTP methods (GET, POST, PUT, DELETE) to send and receive data, usually in JSON format. This guide shows you how to build your own REST APIs in Node-RED and how to pull data from existing APIs.
@@ -19,9 +19,11 @@ REST APIs are how applications talk to each other over the web. They use standar
3. Then Drag an http response node, in it and set the status code if want.
4. Connect the "http-in" node's output to the input of the function node and the function node's output to the input of the http response node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"27333f67794bdc72","type":"http in","z":"977143edb097b685","name":"","url":"/test","method":"get","upload":false,"swaggerDoc":"","x":320,"y":220,"wires":[["f351033226953150"]]},{"id":"a7ee48616541a36a","type":"http response","z":"977143edb097b685","name":"","statusCode":"200","headers":{},"x":760,"y":220,"wires":[]},{"id":"dcfc8d1126f139d5","type":"comment","z":"977143edb097b685","name":"Http-in node created API sending todo list as response","info":"","x":540,"y":140,"wires":[]},{"id":"f351033226953150","type":"change","z":"977143edb097b685","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"todos","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":220,"wires":[["a7ee48616541a36a"]]}]
-{% endrenderFlow %}
+```
+::
## Creating a POST, PUT, and DELETE API
@@ -30,17 +32,23 @@ REST APIs are how applications talk to each other over the web. They use standar
3. Drag an "HTTP Response" node onto the workspace. Configure it and set the status code if needed.
4. Connect the output of the "HTTP In" node to the input of the node handling your application logic (e.g., Change node for DELETE operation). Then, connect the output of this node to the input of the HTTP Response node.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"8893fc84b3391b34","type":"http in","z":"977143edb097b685","name":"","url":"/todo/delete","method":"delete","upload":true,"swaggerDoc":"","x":250,"y":720,"wires":[["088808484586fdc1"]]},{"id":"04a60e7af4d6d522","type":"http response","z":"977143edb097b685","name":"","statusCode":"204","headers":{},"x":740,"y":720,"wires":[]},{"id":"088808484586fdc1","type":"function","z":"977143edb097b685","name":"Delete the todo item","func":"let todoList = global.get('todos') || [];\nlet id = msg.payload.id;\n\n// Find the index of the item to delete\nlet index = todoList.findIndex(item => item.id === id);\n\nif (index !== -1) {\n // Remove the item from the todoList array\n todoList.splice(index, 1);\n global.set('todos', todoList);\n msg.payload = \"Item deleted successfully.\";\n msg.statusCode = 204; // No Content\n} else {\n msg.payload = \"Item not found.\";\n msg.statusCode = 404; // Not Found\n}\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":720,"wires":[["04a60e7af4d6d522"]]}]
-{% endrenderFlow %}
+```
+::
-{% renderFlow %}
+::render-flow
+```json
[{"id":"825a6296456b7c27","type":"http in","z":"977143edb097b685","name":"","url":"/todo","method":"post","upload":true,"swaggerDoc":"","x":260,"y":1460,"wires":[["0133494821cf99ca","9fe48410514631f8"]]},{"id":"0133494821cf99ca","type":"debug","z":"977143edb097b685","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":1420,"wires":[]},{"id":"5284a06365a7f8f7","type":"http response","z":"977143edb097b685","name":"","statusCode":"201","headers":{},"x":860,"y":1500,"wires":[]},{"id":"9fe48410514631f8","type":"function","z":"977143edb097b685","name":"store todo in todolist ","func":"let todoList = global.get('todos') || [];\nlet newTodo = msg.payload;\n\ntodoList.push(newTodo);\nglobal.set('todos',todoList)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":1500,"wires":[["5284a06365a7f8f7"]]}]
-{% endrenderFlow %}
+```
+::
-{% renderFlow %}
+::render-flow
+```json
[{"id":"8893fc84b3391b34","type":"http in","z":"977143edb097b685","name":"","url":"/todo/update","method":"put","upload":true,"swaggerDoc":"","x":400,"y":280,"wires":[["088808484586fdc1"]]},{"id":"04a60e7af4d6d522","type":"http response","z":"977143edb097b685","name":"","statusCode":"200","headers":{},"x":900,"y":280,"wires":[]},{"id":"088808484586fdc1","type":"function","z":"977143edb097b685","name":"update the todo item","func":"let todoList = global.get('todos') || [];\nlet id = msg.payload.id;\nlet newTodo = msg.payload.newtodo;\n\n// Find the index of the item to update\nlet index = todoList.findIndex(item => item.id === id);\n\nif (index !== -1) {\n // Update the todo item\n todoList[index].task = newTodo;\n global.set('todos', todoList);\n msg.payload = \"Item updated successfully.\";\n msg.statusCode = 200; // OK\n} else {\n msg.payload = \"Item not found.\";\n msg.statusCode = 404; // Not Found\n}\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":280,"wires":[["04a60e7af4d6d522"]]},{"id":"ea3e7e96bbccf530","type":"comment","z":"977143edb097b685","name":"Http in node created api for updating the todo item","info":"","x":650,"y":200,"wires":[]}]
-{% endrenderFlow %}
+```
+::
For more details, refer to the [CRUD API Blueprint](/blueprints/getting-started/crud/), where we have created CRUD APIs to store, retrieve, delete, and update the data from MongoDB database.
@@ -112,9 +120,11 @@ For the example we will fetch the data of [Node-RED Dashboard 2.0](/platform/das
A simple flow to fetch data from npm registry would be:
-{% renderFlow %}
+::render-flow
+```json
[{"id":"32b083d0ca67265f","type":"inject","z":"977143edb097b685","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":1100,"wires":[["53db14b9a848d5ce"]]},{"id":"53db14b9a848d5ce","type":"http request","z":"977143edb097b685","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.npmjs.org/downloads/range/last-month/@flowforge/node-red-dashboard","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":410,"y":1100,"wires":[["9e08fa8d25a19f24"]]},{"id":"9e08fa8d25a19f24","type":"debug","z":"977143edb097b685","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":1100,"wires":[]}]
-{% endrenderFlow %}
+```
+::
Where we paste the API URL into the settings panel:
@@ -123,13 +133,13 @@ Where we paste the API URL into the settings panel:
When running this flow you'll see a blob of text in the `Debug` pane. This is a
great first start, but a blob isn't useful for the rest of the flow.
-We need to parse the data as JSON. While the [JSON node](/node-red/core-nodes/json)
+We need to parse the data as JSON. While the [JSON node](/docs/node-red/core-nodes/parsers/json/)
would work, the HTTP request node can do this natively. Let `a parsed JSON object`
the `Return` settings of the HTTP request node.
So now we got the data, and a little more than we need, so let's change the
message output to keep only what we're interested in; `payload.downloads`. To
-do this, we'll use the [change node](/node-red/core-nodes/change).
+do this, we'll use the [change node](/docs/node-red/core-nodes/function/change/).

@@ -154,7 +164,7 @@ The default theme is great, so just accept that, and save all dialogs to continu
#### Normalizing the data
The data for the chart needs to be changed before we can show it. The messages should have a `x` and `y` key. So let's prepare the data with
-a combination of the [Split](/node-red/core-nodes/split) and change node.
+a combination of the [Split](/docs/node-red/core-nodes/sequence/split/) and change node.
The Split node with the default configuration allows to 30 elements of the array
to be mapped individually. The change node will set the `payload.x` and `payload.y`
@@ -170,7 +180,7 @@ Connect the change node output to a new chart node, and voila:
While we created a chart and it has some data, there's one more thing to explain.
How can the data be kept up-to-date? It's straight forward to have the `Inject`
-node [run every night](/node-red/core-nodes/inject/),
+node [run every night](/docs/node-red/core-nodes/common/inject/),
but the chart would now have multiple data points
for the same day. This paints multiple lines on top of each other. While that works,
the hover of the chart will display the duplication and it's wastefull.
@@ -180,6 +190,8 @@ So before we update the chart we need to send a message to the chart where the
That way the chart is emptied first, and right afterwards it will
receive the new data to write.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"da9a67e8c3ea7742","type":"inject","z":"977143edb097b685","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"00 12 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"[]","payloadType":"json","x":250,"y":960,"wires":[["efd22a89abc3c06f","a6851a41dba2c39b"]]},{"id":"a6851a41dba2c39b","type":"http request","z":"977143edb097b685","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.npmjs.org/downloads/range/last-month/@flowforge/node-red-dashboard","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":960,"wires":[["7931f7457880f7c3"]]},{"id":"7931f7457880f7c3","type":"change","z":"977143edb097b685","name":"Only get the Downloads","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.downloads","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":960,"wires":[["74e3b15c7b09726a"]]},{"id":"74e3b15c7b09726a","type":"link out","z":"977143edb097b685","name":"link out 1","mode":"link","links":["43e4aff34b989e83"],"x":815,"y":960,"wires":[]},{"id":"43e4aff34b989e83","type":"link in","z":"977143edb097b685","name":"Normalize daily data","links":["74e3b15c7b09726a"],"x":195,"y":1040,"wires":[["ca8c62bfbdf75715"]]},{"id":"ca8c62bfbdf75715","type":"split","z":"977143edb097b685","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":310,"y":1040,"wires":[["3f462d2c7e3bca50"]]},{"id":"3f462d2c7e3bca50","type":"change","z":"977143edb097b685","name":"Prepare data for the chart","rules":[{"t":"set","p":"payload.x","pt":"msg","to":"$toMillis(payload.day)","tot":"jsonata"},{"t":"set","p":"payload.y","pt":"msg","to":"payload.downloads","tot":"msg"},{"t":"delete","p":"payload.day","pt":"msg"},{"t":"delete","p":"payload.downloads","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":1040,"wires":[["f4e6a85b8cb8dac0"]]},{"id":"4b71fc28c2da66e7","type":"ui-chart","z":"977143edb097b685","group":"bac8effac57694e1","name":"","label":"Daily Downloads","order":9007199254740991,"chartType":"line","xAxisType":"time","removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":0,"height":0,"className":"","x":330,"y":1120,"wires":[[]]},{"id":"f4e6a85b8cb8dac0","type":"link out","z":"977143edb097b685","name":"link out 2","mode":"link","links":["6f7068445bfe4311"],"x":675,"y":1040,"wires":[]},{"id":"6f7068445bfe4311","type":"link in","z":"977143edb097b685","name":"Update the chart","links":["f4e6a85b8cb8dac0","79067215ee592ec9","efd22a89abc3c06f"],"x":195,"y":1120,"wires":[["4b71fc28c2da66e7"]]},{"id":"efd22a89abc3c06f","type":"link out","z":"977143edb097b685","name":"link out 3","mode":"link","links":["6f7068445bfe4311"],"x":415,"y":920,"wires":[]},{"id":"bac8effac57694e1","type":"ui-group","name":"NPM Downloads","page":"f10b4d0259e43aeb","width":"6","height":"1","order":-1},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"Main","ui":"cb79bc4520925e32","path":"/","layout":"grid","theme":"2c5d702b11de7dd1","order":-1},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}]
-{% endrenderFlow %}
\ No newline at end of file
+```
+::
diff --git a/src/node-red/integration-technologies/webhook.md b/nuxt/content-guides/node-red/integration-technologies/webhook.md
similarity index 96%
rename from src/node-red/integration-technologies/webhook.md
rename to nuxt/content-guides/node-red/integration-technologies/webhook.md
index 41cb0e98f4..e6e8432d05 100644
--- a/src/node-red/integration-technologies/webhook.md
+++ b/nuxt/content-guides/node-red/integration-technologies/webhook.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: Webhook
- parent: "Integration Technologies"
+title: Using Webhook with Node-RED
+metaTitle: "Using Webhook with Node-RED"
+navTitle: Webhook
+navOrder: 50
meta:
- title: Using Webhook with Node-RED
- description: Learn how to seamlessly integrate webhooks into your Node-RED applications for automating tasks and enhancing communication.
- keywords: node-red, flowfuse, webhooks, automation, event-driven
-image: /node-red/hardware/images/webhooks-node-red.png
+ description: Learn how to seamlessly integrate webhooks into your Node-RED applications for automating tasks and enhancing communication.
+ keywords: node-red, flowfuse, webhooks, automation, event-driven
+image: /docs/node-red/hardware/images/webhooks-node-red.png
---
-# {{meta.title}}
+# Using Webhook with Node-RED
Webhooks let different systems talk to each other automatically when something happens. Instead of constantly asking "anything new?", one system just tells the other "hey, this just happened." This guide shows you how to set up webhooks in Node-RED, using a real manufacturing example where temperature sensors trigger maintenance alerts.
@@ -173,4 +173,4 @@ return msg;
1. With your flow updated to include the above, click the "Deploy" button in the top-right corner of the Node-RED Editor in each Node-RED instance.
2. In server 3 Node-RED instance (Maintenance scheduling system), Locate the 'Open Dashboard' button at the top-right corner of the Dashboard 2.0 sidebar and click on it to navigate to the dashboard.
-
\ No newline at end of file
+
diff --git a/src/node-red/keyboard/index.md b/nuxt/content-guides/node-red/keyboard/README.md
similarity index 94%
rename from src/node-red/keyboard/index.md
rename to nuxt/content-guides/node-red/keyboard/README.md
index 5063be5d68..ffd65ee868 100644
--- a/src/node-red/keyboard/index.md
+++ b/nuxt/content-guides/node-red/keyboard/README.md
@@ -1,11 +1,11 @@
---
-eleventyNavigation:
- key: Keyboard Shortcuts
- order: 3
+title: Node-RED Keyboard Shortcuts
+metaTitle: "Node-RED Keyboard Shortcuts"
+navTitle: Keyboard shortcuts
+navOrder: 11
meta:
- title: Node-RED Keyboard Shortcuts
- description: A comprehensive list of keyboard shortcuts for Node-RED to enhance productivity and streamline workflow.
- keywords: node-red, node-red keyboard shortcuts
+ description: A comprehensive list of keyboard shortcuts for Node-RED to enhance productivity and streamline workflow.
+ keywords: node-red, node-red keyboard shortcuts
---
# Node-RED Keyboard Shortcuts
@@ -110,4 +110,4 @@ Node-RED lets you customize keyboard shortcuts to fit your workflow, making it e
1. To set custom keyboard shortcuts, go to the keyboard settings in the user settings. Click `Shift + ?` or click the top-right menu icon and select "Settings." In the settings menu, switch to "Keyboard Settings."
2. In the Keyboard Settings, you will see actions with assigned shortcuts as well as those that are unassigned. To change or set shortcuts, click on "Unassigned" or the existing shortcut next to the action you want to modify.
-3. Enter your preferred key combination for the action. Then, select the appropriate scope and click the check icon to save your changes. Your new shortcuts will now be active.
\ No newline at end of file
+3. Enter your preferred key combination for the action. Then, select the appropriate scope and click the check icon to save your changes. Your new shortcuts will now be active.
diff --git a/nuxt/content-guides/node-red/notification/README.md b/nuxt/content-guides/node-red/notification/README.md
new file mode 100644
index 0000000000..d8c4b5216c
--- /dev/null
+++ b/nuxt/content-guides/node-red/notification/README.md
@@ -0,0 +1,21 @@
+---
+title: Notification Services in Node-RED
+metaTitle: "Notification Services in Node-RED"
+navTitle: Notification services
+navOrder: 7
+meta:
+ description: Learn how to integrate various notification services with Node-RED for real-time alerts and messaging.
+ keywords: node-red, notification services, email notifications, Telegram notifications, Slack notifications, WhatsApp notifications
+---
+
+# Notification Services
+
+Real-time notifications are essential in our automation world, helping to keep us informed, responsive, and efficient. Whether it's a critical system alert, a customer inquiry, or a simple reminder, timely notifications can significantly enhance productivity and efficiency. However, managing and integrating such services can be challenging in traditional development environments. Node-RED simplifies this process by supporting a wide range of notification services, including email, Telegram, Slack, WhatsApp, and more.
+
+## Resources
+
+Here are some resources to help you get started with Node-RED on diffrent notification services:
+
+- [Sending and receiving Discord messages with Node-RED](/docs/node-red/notification/discord/): Learn how to send and receive Discord messages with Node-RED.
+- [Sending and receiving emails with Node-RED](/docs/node-red/notification/email/): Learn how to send and receive emails using Node-RED, along with best practices for sending email notifications.
+- [Sending and receiving Telegram messages with Node-RED](/docs/node-red/notification/telegram/): Learn to seamlessly integrate Telegram with Node-RED for messaging. Create bots, obtain chat IDs, and send/receive messages, including group messaging.
diff --git a/src/node-red/notification/discord.md b/nuxt/content-guides/node-red/notification/discord.md
similarity index 91%
rename from src/node-red/notification/discord.md
rename to nuxt/content-guides/node-red/notification/discord.md
index a95f21645e..b8ddc77ca1 100644
--- a/src/node-red/notification/discord.md
+++ b/nuxt/content-guides/node-red/notification/discord.md
@@ -1,21 +1,21 @@
---
-eleventyNavigation:
- key: Discord
- parent: "Notification Services"
+title: Sending and receiving Discord messages with Node-RED
+metaTitle: "Sending and receiving Discord messages with Node-RED"
+navTitle: Discord
+navOrder: 50
meta:
- title: Sending and receiving Discord messages with Node-RED
- description: Learn how to send and receive Discord messages with Node-RED.
- keywords: nodered discord, node red discord
-image: /node-red/notification/images/sending-and-receiving-discord-message-with-node-red.png
+ description: Learn how to send and receive Discord messages with Node-RED.
+ keywords: nodered discord, node red discord
+image: /docs/node-red/notification/images/sending-and-receiving-discord-message-with-node-red.png
---
-# {{meta.title}}
+# Sending and receiving Discord messages with Node-RED
This guide explains how to integrate Discord with Node-RED to send and receive messages. You'll learn how to configure a Discord bot, send messages to users and channels, and handle incoming messages.
Discord is commonly used for notifications in IoT applications. This document covers the setup process and includes troubleshooting steps for common integration issues.
-For information on integrating other notification services, see the guides on [Email](/node-red/notification/email/) and [Telegram](/node-red/notification/telegram/).
+For information on integrating other notification services, see the guides on [Email](/docs/node-red/notification/email/) and [Telegram](/docs/node-red/notification/telegram/).
@@ -69,7 +69,7 @@ To send a message to a user, you will need the ID of that user. Before copying t
3. Set the `msg.payload` to the message you want to send and the `msg.user` to the user ID of the user you want to send the message to.
4. Connect the Inject node's output to the input of the DiscordMessageManager node.
-
+
## Sending messages to the Discord server
@@ -98,7 +98,7 @@ To send a message to the Discord server, you have to make sure that your bot is
3. Connect the Inject node's output to the input of the DiscordMessageManager node.
-
+
## Receiving messages from Discord
@@ -108,13 +108,15 @@ To send a message to the Discord server, you have to make sure that your bot is
After deploying the flow, you will start receiving messages sent to your bot. In the debug panel in the sidebar, you will see the message object printed for each message, which contains different objects. Each object shows different details; for example, the author object contains details about the sender, and the channel object includes information of the channel if the message was sent in a channel.
-
+
Below, I have provided the complete flow we built throughout the guide. Make sure to replace the environment variable 'BOT_TOKEN' with your actual bot token.
-{% renderFlow %}
+::render-flow
+```json
[{"id":"7a8dd49f9614608e","type":"inject","z":"4674ed668685adf6","name":"Sending mesasge to Discord server 's channel","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, This is from Node-RED","payloadType":"str","x":570,"y":420,"wires":[["3984c20a52db033f"]]},{"id":"3984c20a52db033f","type":"discordMessageManager","z":"4674ed668685adf6","name":"","channel":"56454645657765656","token":"","x":930,"y":420,"wires":[["b99ae75425047b6b"]]},{"id":"b99ae75425047b6b","type":"debug","z":"4674ed668685adf6","name":"debug 3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1200,"y":420,"wires":[]},{"id":"6af740e11aba6ca2","type":"inject","z":"4674ed668685adf6","name":"Sending message to Discord user","props":[{"p":"payload"},{"p":"user","v":"65454534534345365","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, Sumit","payloadType":"str","x":550,"y":320,"wires":[["f69363f341b62333"]]},{"id":"f69363f341b62333","type":"discordMessageManager","z":"4674ed668685adf6","name":"","channel":"","token":"","x":930,"y":320,"wires":[["c5001a783992ae01"]]},{"id":"c5001a783992ae01","type":"debug","z":"4674ed668685adf6","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1220,"y":320,"wires":[]},{"id":"820b70826545a401","type":"debug","z":"4674ed668685adf6","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1020,"y":540,"wires":[]},{"id":"f044d3784ef8c74a","type":"discordMessage","z":"4674ed668685adf6","name":"","channelIdFilter":"","token":"","x":720,"y":540,"wires":[["820b70826545a401"]]}]
-{% endrenderFlow %}
+```
+::
## Debugging and Troubleshooting
diff --git a/src/node-red/notification/email.md b/nuxt/content-guides/node-red/notification/email.md
similarity index 95%
rename from src/node-red/notification/email.md
rename to nuxt/content-guides/node-red/notification/email.md
index 82bc9d1ee0..158394c086 100644
--- a/src/node-red/notification/email.md
+++ b/nuxt/content-guides/node-red/notification/email.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: Email
- parent: "Notification Services"
+title: Sending and receiving emails with Node-RED
+metaTitle: "Sending and receiving emails with Node-RED"
+navTitle: Email
+navOrder: 50
meta:
- title: Sending and receiving emails with Node-RED
- description: Learn how to send and receive emails using Node-RED, along with best practices for sending email notifications.
- keywords: node-red, gmail, flowfuse device agent, anti-spam measures, email]
-image: /node-red/notification/images/email_node-red.png
+ description: Learn how to send and receive emails using Node-RED, along with best practices for sending email notifications.
+ keywords: node-red, gmail, flowfuse device agent, anti-spam measures, email]
+image: /docs/node-red/notification/images/email_node-red.png
---
-# {{meta.title}}
+# Sending and receiving emails with Node-RED
This guide shows you how to integrate email with Node-RED for sending and receiving messages. You'll learn how to configure email nodes, set up Gmail integration, and follow best practices to ensure your notifications reach their destination.
@@ -157,4 +157,4 @@ Even legitimate emails can sometimes trigger spam filters. Follow these practice
- **Authenticate your emails** - Implement SPF, DKIM, and DMARC protocols to verify your email's legitimacy and improve deliverability.
- **Manage your sending frequency** - Avoid sending too many emails in a short period. Maintain a consistent schedule and ensure each message provides value.
- **Keep your email list clean** - Regularly remove invalid or inactive addresses. High bounce rates and spam complaints damage your sender reputation.
-- **Monitor your reputation** - Use tools like SenderScore or Google Postmaster Tools to track your sender reputation and identify potential issues before they affect delivery.
\ No newline at end of file
+- **Monitor your reputation** - Use tools like SenderScore or Google Postmaster Tools to track your sender reputation and identify potential issues before they affect delivery.
diff --git a/src/node-red/notification/images/discord-with-node-red-bot-reset-token.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-bot-reset-token.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-bot-reset-token.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-bot-reset-token.png
diff --git a/src/node-red/notification/images/discord-with-node-red-channel-id.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-channel-id.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-channel-id.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-channel-id.png
diff --git a/src/node-red/notification/images/discord-with-node-red-conform-add-to-server.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-conform-add-to-server.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-conform-add-to-server.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-conform-add-to-server.png
diff --git a/src/node-red/notification/images/discord-with-node-red-create-app.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-create-app.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-create-app.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-create-app.png
diff --git a/src/node-red/notification/images/discord-with-node-red-developer-mode.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-developer-mode.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-developer-mode.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-developer-mode.png
diff --git a/src/node-red/notification/images/discord-with-node-red-error-1.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-1.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-error-1.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-1.png
diff --git a/src/node-red/notification/images/discord-with-node-red-error-2.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-2.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-error-2.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-2.png
diff --git a/src/node-red/notification/images/discord-with-node-red-error-3.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-3.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-error-3.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-error-3.png
diff --git a/src/node-red/notification/images/discord-with-node-red-new-application-button.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-new-application-button.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-new-application-button.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-new-application-button.png
diff --git a/src/node-red/notification/images/discord-with-node-red-oauth-copy-url.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-oauth-copy-url.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-oauth-copy-url.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-oauth-copy-url.png
diff --git a/src/node-red/notification/images/discord-with-node-red-oauth-scope.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-oauth-scope.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-oauth-scope.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-oauth-scope.png
diff --git a/src/node-red/notification/images/discord-with-node-red-outh-permission.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-outh-permission.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-outh-permission.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-outh-permission.png
diff --git a/src/node-red/notification/images/discord-with-node-red-privillage-itents.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-privillage-itents.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-privillage-itents.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-privillage-itents.png
diff --git a/src/node-red/notification/images/discord-with-node-red-receiving-messages.webm b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-receiving-messages.webm
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-receiving-messages.webm
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-receiving-messages.webm
diff --git a/src/node-red/notification/images/discord-with-node-red-select-the-server.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-select-the-server.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-select-the-server.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-select-the-server.png
diff --git a/src/node-red/notification/images/discord-with-node-red-sending-msg-to-server.webm b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-sending-msg-to-server.webm
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-sending-msg-to-server.webm
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-sending-msg-to-server.webm
diff --git a/src/node-red/notification/images/discord-with-node-red-sending-msg-to-user.webm b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-sending-msg-to-user.webm
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-sending-msg-to-user.webm
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-sending-msg-to-user.webm
diff --git a/src/node-red/notification/images/discord-with-node-red-user-id.png b/nuxt/content-guides/node-red/notification/images/discord-with-node-red-user-id.png
similarity index 100%
rename from src/node-red/notification/images/discord-with-node-red-user-id.png
rename to nuxt/content-guides/node-red/notification/images/discord-with-node-red-user-id.png
diff --git a/src/node-red/notification/images/email_node-red.png b/nuxt/content-guides/node-red/notification/images/email_node-red.png
similarity index 100%
rename from src/node-red/notification/images/email_node-red.png
rename to nuxt/content-guides/node-red/notification/images/email_node-red.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-in-node-configuration.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-in-node-configuration.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-in-node-configuration.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-in-node-configuration.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-node-configuration.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-node-configuration.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-node-configuration.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-e-mail-node-configuration.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-gmail-inbox.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-gmail-inbox.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-gmail-inbox.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-gmail-inbox.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-inject-node.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-inject-node.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-inject-node.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-inject-node.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red-flow.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red-flow.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red-flow.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red-flow.png
diff --git a/src/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red_setting_environment_variables.png b/nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red_setting_environment_variables.png
similarity index 100%
rename from src/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red_setting_environment_variables.png
rename to nuxt/content-guides/node-red/notification/images/sending-and-receiving-email-with-node-red-node-red_setting_environment_variables.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-activating-bot.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-activating-bot.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-activating-bot.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-activating-bot.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-botfather.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-botfather.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-botfather.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-botfather.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-change-node.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-change-node.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-change-node.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-change-node.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-enabling-send-error-to-second-option.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-enabling-send-error-to-second-option.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-enabling-send-error-to-second-option.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-enabling-send-error-to-second-option.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-flow.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-flow.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-flow.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-flow.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-flowfue-instance-settings.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-flowfue-instance-settings.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-flowfue-instance-settings.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-flowfue-instance-settings.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-getmyid.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-getmyid.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-getmyid.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-getmyid.png
diff --git a/src/node-red/notification/images/sending-telegram-with-node-red-telegram-node-configuration.png b/nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-telegram-node-configuration.png
similarity index 100%
rename from src/node-red/notification/images/sending-telegram-with-node-red-telegram-node-configuration.png
rename to nuxt/content-guides/node-red/notification/images/sending-telegram-with-node-red-telegram-node-configuration.png
diff --git a/src/node-red/notification/images/telegram_node-red.png b/nuxt/content-guides/node-red/notification/images/telegram_node-red.png
similarity index 100%
rename from src/node-red/notification/images/telegram_node-red.png
rename to nuxt/content-guides/node-red/notification/images/telegram_node-red.png
diff --git a/src/node-red/notification/telegram.md b/nuxt/content-guides/node-red/notification/telegram.md
similarity index 92%
rename from src/node-red/notification/telegram.md
rename to nuxt/content-guides/node-red/notification/telegram.md
index 5915a23aa7..abdfb63ea2 100644
--- a/src/node-red/notification/telegram.md
+++ b/nuxt/content-guides/node-red/notification/telegram.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: Telegram
- parent: "Notification Services"
+title: Sending and receiving Telegram messages with Node-RED
+metaTitle: "Sending and receiving Telegram messages with Node-RED"
+navTitle: Telegram
+navOrder: 50
meta:
- title: Sending and receiving Telegram messages with Node-RED
- description: Learn to seamlessly integrate Telegram with Node-RED for messaging. Create bots, obtain chat IDs, and send/receive messages, including group messaging.
- keywords: node-red, telegram, bot
-image: /node-red/notification/images/telegram_node-red.png
+ description: Learn to seamlessly integrate Telegram with Node-RED for messaging. Create bots, obtain chat IDs, and send/receive messages, including group messaging.
+ keywords: node-red, telegram, bot
+image: /docs/node-red/notification/images/telegram_node-red.png
---
-# {{meta.title}}
+# Sending and receiving Telegram messages with Node-RED
Telegram has become a popular choice for messaging in home automation applications. This guide shows you how to integrate Telegram with Node-RED, covering bot creation, chat ID retrieval, and both sending and receiving messages.
@@ -102,4 +102,4 @@ Environment variables keep your sensitive information secure by preventing it fr
1. Deploy the flow by clicking the Deploy button in the top-right corner.
-Your Telegram bot is now ready to use. Click the Inject button to send a message, and you'll receive a notification in Telegram. You can also check your bot's chat to see messages sent via Node-RED. To test receiving messages, send a message to your bot and watch the Debug panel display the message object containing the message content and additional information.
\ No newline at end of file
+Your Telegram bot is now ready to use. Click the Inject button to send a message, and you'll receive a notification in Telegram. You can also check your bot's chat to see messages sent via Node-RED. To test receiving messages, send a message to your bot and watch the Debug panel display the message object containing the message content and additional information.
diff --git a/src/node-red/peripheral/index.md b/nuxt/content-guides/node-red/peripheral/README.md
similarity index 53%
rename from src/node-red/peripheral/index.md
rename to nuxt/content-guides/node-red/peripheral/README.md
index 56fe7db2a9..cb8ade0103 100644
--- a/src/node-red/peripheral/index.md
+++ b/nuxt/content-guides/node-red/peripheral/README.md
@@ -1,13 +1,13 @@
---
-eleventyNavigation:
- key: "Peripheral Devices"
- order: 7
+title: Integrating Node-RED with Peripheral Devices
+metaTitle: "Integrating Node-RED with Peripheral Devices"
+navTitle: Peripheral devices
+navOrder: 9
meta:
- title: Integrating Node-RED with Peripheral Devices
- description: Learn how to integrate Node-RED with various peripheral devices, including keyboards, mice, printers, and more.
- keywords: node-red, flowfuse, peripheral devices, webcam, barcode scanner
+ description: Learn how to integrate Node-RED with various peripheral devices, including keyboards, mice, printers, and more.
+ keywords: node-red, flowfuse, peripheral devices, webcam, barcode scanner
---
# Peripheral Devices
-Node-RED supports a wide range of peripheral devices, allowing users to connect Node-RED to many external inputs and outputs. This enables the creation of interactive and automated systems where data from peripheral devices can trigger actions or responses in the digital realm. By bridging the gap between software and hardware, Node-RED expands its applicability to a wide range of use cases.
\ No newline at end of file
+Node-RED supports a wide range of peripheral devices, allowing users to connect Node-RED to many external inputs and outputs. This enables the creation of interactive and automated systems where data from peripheral devices can trigger actions or responses in the digital realm. By bridging the gap between software and hardware, Node-RED expands its applicability to a wide range of use cases.
diff --git a/src/node-red/peripheral/ardiuno.md b/nuxt/content-guides/node-red/peripheral/ardiuno.md
similarity index 90%
rename from src/node-red/peripheral/ardiuno.md
rename to nuxt/content-guides/node-red/peripheral/ardiuno.md
index ab42f332fa..c2386fce16 100644
--- a/src/node-red/peripheral/ardiuno.md
+++ b/nuxt/content-guides/node-red/peripheral/ardiuno.md
@@ -1,15 +1,15 @@
---
-eleventyNavigation:
- key: "Arduino"
- parent: "Peripheral Devices"
+title: Connecting Arduino to Node-RED
+metaTitle: "Connecting Arduino to Node-RED"
+navTitle: Arduino
+navOrder: 50
meta:
- title: Connecting Arduino to Node-RED
- description: Learn how to control and monitor Arduino hardware using Node-RED
- keywords: node-red, flowfuse, ardiuno
-image: /node-red/peripheral/images/barcode-scanner.png
+ description: Learn how to control and monitor Arduino hardware using Node-RED
+ keywords: node-red, flowfuse, ardiuno
+image: /docs/node-red/peripheral/images/barcode-scanner.png
---
-# {{meta.title}}
+# Connecting Arduino to Node-RED
This documentation explains how to use Node-RED to interact with an Arduino board via serial communication using the Firmata protocol. It covers how to write to and read from digital and analog pins using the `node-red-node-arduino` package.
diff --git a/src/node-red/peripheral/barcodescanner.md b/nuxt/content-guides/node-red/peripheral/barcodescanner.md
similarity index 87%
rename from src/node-red/peripheral/barcodescanner.md
rename to nuxt/content-guides/node-red/peripheral/barcodescanner.md
index 0b39e07010..127a2f64dd 100644
--- a/src/node-red/peripheral/barcodescanner.md
+++ b/nuxt/content-guides/node-red/peripheral/barcodescanner.md
@@ -1,16 +1,15 @@
---
+title: How to connect a barcode scanner to your Node-RED application
metaTitle: "How to Connect a Barcode Scanner to Node-RED"
-eleventyNavigation:
- key: "Barcode Scanner"
- parent: "Peripheral Devices"
+navTitle: Barcode Scanner
+navOrder: 50
meta:
- title: How to connect a barcode scanner to your Node-RED application
- description: Learn to seamlessly connect a barcode scanner to Node-RED for efficient data capture and automation.
- keywords: node-red, flowfuse, barcodescanner
-image: /node-red/peripheral/images/barcode-scanner.png
+ description: Learn to seamlessly connect a barcode scanner to Node-RED for efficient data capture and automation.
+ keywords: node-red, flowfuse, barcodescanner
+image: /docs/node-red/peripheral/images/barcode-scanner.png
---
-# {{meta.title}}
+# How to connect a barcode scanner to your Node-RED application
Barcode scanners, functioning as Human Interface Devices (HID) similar to keyboards, offer versatile programming options. Variations of barcode scanners can be seen used from anything from checkout counters, logistics, and to manufacturing erp systems. In our case, we kept it basic and we used one to trigger a Node-RED flow, keeping the process straightforward and efficient. Don't let that limit your imagination though, with QR codes, you can store just about anything including recipes in a JSON structure.
@@ -34,4 +33,4 @@ You could even take it a step further and create a [QR code](https://smalldev.to
## Linux Setup
-Linux users might face a slightly more complicated setup, as access to communication ports isn't always granted by default, and specific drivers are needed for optimal node functionality. This is due to the security around applications having access to specific devices connected to the system. For this, we recommend following the detailed instructions available in the project's [GitHub](https://github.com/gdziuba/node-red-contrib-usbhid) repository.
\ No newline at end of file
+Linux users might face a slightly more complicated setup, as access to communication ports isn't always granted by default, and specific drivers are needed for optimal node functionality. This is due to the security around applications having access to specific devices connected to the system. For this, we recommend following the detailed instructions available in the project's [GitHub](https://github.com/gdziuba/node-red-contrib-usbhid) repository.
diff --git a/src/node-red/peripheral/esp32.md b/nuxt/content-guides/node-red/peripheral/esp32.md
similarity index 97%
rename from src/node-red/peripheral/esp32.md
rename to nuxt/content-guides/node-red/peripheral/esp32.md
index 6741765876..39276356a7 100644
--- a/src/node-red/peripheral/esp32.md
+++ b/nuxt/content-guides/node-red/peripheral/esp32.md
@@ -1,14 +1,14 @@
---
-eleventyNavigation:
- key: "ESP32"
- parent: "Peripheral Devices"
+title: Connect ESP32 with Node-RED using MQTT
+metaTitle: "Connect ESP32 with Node-RED using MQTT"
+navTitle: ESP32
+navOrder: 50
meta:
- title: Connect ESP32 with Node-RED using MQTT
description: Learn how to send and receive MQTT messages between ESP32 and Node-RED using FlowFuse.
keywords: node-red, flowfuse, esp32, mqtt, esp32 node-red
---
-# {{meta.title}}
+# Connect ESP32 with Node-RED using MQTT
This document outlines the procedure for establishing MQTT communication between an ESP32 microcontroller and a Node-RED instance.
@@ -58,9 +58,11 @@ This section provides a practical demonstration with an importable Node-RED flow
Import the following JSON into your Node-RED editor. This flow creates a simple dashboard with ON/OFF buttons that publish to the `/esp32/led` topic. You must configure the **`mqtt out`** node with your specific broker credentials.
-{% renderFlow 300 %}
+::render-flow{:height="300"}
+```json
[{"id":"59887a8115c95eae","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"02c25e8a30f9379d","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"cfb2ab9ff30660fc","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"density":"default","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}},{"id":"d263574af6876c7a","type":"ui-page","name":"ESP32","ui":"02c25e8a30f9379d","path":"/page1","icon":"home","layout":"grid","theme":"cfb2ab9ff30660fc","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":1,"className":"","visible":"true","disabled":"false"},{"id":"3ae115ea7ede6827","type":"ui-group","name":"Group 1","page":"d263574af6876c7a","width":"6","height":"1","order":1,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"def97b29f5f7baab","type":"mqtt-broker","name":"","broker":"broker.flowfuse.cloud","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"5a9162986a34a4d6","type":"ui-button","z":"59887a8115c95eae","group":"3ae115ea7ede6827","name":"","label":"ON","order":1,"width":"3","height":"2","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"1","payloadType":"num","topic":"topic","topicType":"msg","buttonColor":"green","textColor":"","iconColor":"","enableClick":true,"enablePointerdown":false,"pointerdownPayload":"","pointerdownPayloadType":"str","enablePointerup":false,"pointerupPayload":"","pointerupPayloadType":"str","x":190,"y":120,"wires":[["9239f8a7cca5c858"]]},{"id":"f9c194994d9491a8","type":"ui-button","z":"59887a8115c95eae","group":"3ae115ea7ede6827","name":"","label":"OFF","order":2,"width":"3","height":"2","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"2","payloadType":"num","topic":"topic","topicType":"msg","buttonColor":"red","textColor":"","iconColor":"","enableClick":true,"enablePointerdown":false,"pointerdownPayload":"","pointerdownPayloadType":"str","enablePointerup":false,"pointerupPayload":"","pointerupPayloadType":"str","x":190,"y":160,"wires":[["9239f8a7cca5c858"]]},{"id":"9239f8a7cca5c858","type":"mqtt out","z":"59887a8115c95eae","name":"","topic":"/LedControl","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"def97b29f5f7baab","x":390,"y":140,"wires":[]}]
-{% endrenderFlow %}
+```
+::
### 2. ESP32 Demo Code
diff --git a/src/node-red/peripheral/images/barcode-scanner.png b/nuxt/content-guides/node-red/peripheral/images/barcode-scanner.png
similarity index 100%
rename from src/node-red/peripheral/images/barcode-scanner.png
rename to nuxt/content-guides/node-red/peripheral/images/barcode-scanner.png
diff --git a/src/node-red/peripheral/images/usbhid-barcode-node-red.png b/nuxt/content-guides/node-red/peripheral/images/usbhid-barcode-node-red.png
similarity index 100%
rename from src/node-red/peripheral/images/usbhid-barcode-node-red.png
rename to nuxt/content-guides/node-red/peripheral/images/usbhid-barcode-node-red.png
diff --git a/src/node-red/peripheral/images/usbhid-config-node-red.png b/nuxt/content-guides/node-red/peripheral/images/usbhid-config-node-red.png
similarity index 100%
rename from src/node-red/peripheral/images/usbhid-config-node-red.png
rename to nuxt/content-guides/node-red/peripheral/images/usbhid-config-node-red.png
diff --git a/src/node-red/peripheral/images/usbhid-qr-pizza-order.png b/nuxt/content-guides/node-red/peripheral/images/usbhid-qr-pizza-order.png
similarity index 100%
rename from src/node-red/peripheral/images/usbhid-qr-pizza-order.png
rename to nuxt/content-guides/node-red/peripheral/images/usbhid-qr-pizza-order.png
diff --git a/src/node-red/peripheral/images/usbhid-scanned-barcode.png b/nuxt/content-guides/node-red/peripheral/images/usbhid-scanned-barcode.png
similarity index 100%
rename from src/node-red/peripheral/images/usbhid-scanned-barcode.png
rename to nuxt/content-guides/node-red/peripheral/images/usbhid-scanned-barcode.png
diff --git a/src/node-red/peripheral/images/using_webcam_with_node-red.png b/nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red.png
similarity index 100%
rename from src/node-red/peripheral/images/using_webcam_with_node-red.png
rename to nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red.png
diff --git a/src/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_control.webm b/nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_control.webm
similarity index 100%
rename from src/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_control.webm
rename to nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_control.webm
diff --git a/src/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_passing_payload.webm b/nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_passing_payload.webm
similarity index 100%
rename from src/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_passing_payload.webm
rename to nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_capturing_images_by_passing_payload.webm
diff --git a/src/node-red/peripheral/images/using_webcam_with_node-red_selecting_different_camera.webm b/nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_selecting_different_camera.webm
similarity index 100%
rename from src/node-red/peripheral/images/using_webcam_with_node-red_selecting_different_camera.webm
rename to nuxt/content-guides/node-red/peripheral/images/using_webcam_with_node-red_selecting_different_camera.webm
diff --git a/src/node-red/peripheral/webcam.md b/nuxt/content-guides/node-red/peripheral/webcam.md
similarity index 82%
rename from src/node-red/peripheral/webcam.md
rename to nuxt/content-guides/node-red/peripheral/webcam.md
index e06e72b38d..96ee07bc4f 100644
--- a/src/node-red/peripheral/webcam.md
+++ b/nuxt/content-guides/node-red/peripheral/webcam.md
@@ -1,21 +1,15 @@
---
-eleventyNavigation:
- key: Webcam
- parent: "Peripheral Devices"
+title: Using webcam with Node-RED
+metaTitle: "Using webcam with Node-RED"
+navTitle: Webcam
+navOrder: 50
meta:
- title: Using webcam with Node-RED
- description: Learn how to seamlessly connect webcam with Node-RED
- keywords: node-red, flowfuse, webcam, capturing image
-image: /node-red/peripheral/images/using_webcam_with_node-red.png
-certified:
- - "@flowfuse-certified-nodes/rtsp"
-certifiedIntro: >
- This page covers browser webcams through the Dashboard widget. For network
- cameras that stream over RTSP, FlowFuse certifies and maintains a separate
- node:
+ description: Learn how to seamlessly connect webcam with Node-RED
+ keywords: node-red, flowfuse, webcam, capturing image
+image: /docs/node-red/peripheral/images/using_webcam_with_node-red.png
---
-# {{meta.title}}
+# Using webcam with Node-RED
Dashboard 2.0 has introduced its first third-party webcam widget, simplifying the integration of webcam features with Node-RED applications. In this documentation, you will learn how to utilize the ui-webcam widget in your Node-RED applications.
@@ -23,7 +17,9 @@ Additionally, if you are willing to develop your own third-party widget, we have
Install Node-RED Dashboard 2.0. Follow these [instructions](/blog/2024/03/dashboard-getting-started/) to get started.
-{% include "components/certified-node-callout.liquid" %}
+::callout{icon="i-lucide-badge-check"}
+**Certified nodes for this technology.** This page covers browser webcams through the Dashboard widget. For network cameras that stream over RTSP, FlowFuse certifies and maintains a separate node: [rtsp](/integrations/?certified=1)
+::
## Using a webcam custom widget
@@ -46,7 +42,7 @@ This webcam widget offers nice interactive controls that will allow you to inter
3. Once the webcam is active, you can capture images by clicking the button with the camera icon located at the bottom center of the webcam interface.
4. The widget returns a Base64 string containing the captured image in PNG format.
-
+
## Capturing images by passing payload
@@ -57,7 +53,7 @@ This webcam widget offers nice interactive controls that will allow you to inter
By passing the "capture" string as payload, the webcam widget will activate (if it's off) and capture images automatically, without requiring user interaction. This method is commonly used in industrial applications which depend on automated actions.
-
+
## Selecting different camera devices
@@ -66,11 +62,11 @@ The webcam widget also allows you to select different camera devices connected t
1. Click on the ellipsis icon located at the top-right corner of the webcam interface.
2. A dropdown menu will display the connected cameras. Select your preferred camera to use. Additionally, you can turn off the camera by selecting the "Turn camera off" option.
-
+
## Browser support and privacy
- Browser Compatibility: The webcam widget is compatible with all modern browsers, except Internet Explorer. Whether you're using Chrome, Firefox, Safari, or Edge, you can seamlessly integrate webcam features into your Node-RED applications.
- Control Limitation: It's important to note that this widget is designed to interact with webcams directly accessible to the system running Node-RED. For example, if the webcam is connected to a different device or network and not directly accessible to the Node-RED running system, the video stream from that webcam won't be displayed on a dashboard using this widget.
- HTTPS Requirement: When accessing Dashboard 2.0 remotely (not via `localhost`), it's crucial to use HTTPS. Failure to do so may result in the browser blocking access to the webcam.
-- User Permission: Before the webcam can be activated, the browser will prompt the user for permission to access the webcam device. This ensures user privacy and consent before any image capture occurs. The widget cannot capture images until the user has given their permission.
\ No newline at end of file
+- User Permission: Before the webcam can be activated, the browser will prompt the user for permission to access the webcam device. This ensures user privacy and consent before any image capture occurs. The widget cannot capture images until the user has given their permission.
diff --git a/nuxt/content-guides/node-red/protocol/README.md b/nuxt/content-guides/node-red/protocol/README.md
new file mode 100644
index 0000000000..b5a89a7a71
--- /dev/null
+++ b/nuxt/content-guides/node-red/protocol/README.md
@@ -0,0 +1,30 @@
+---
+title: Using Different Protocols for Building Applications with Node-RED
+metaTitle: "Using Different Protocols with Node-RED"
+navTitle: Communication protocols
+navOrder: 4
+meta:
+ description: Learn how to leverage various communication protocols with Node-RED for building robust and interconnected applications.
+ keywords: node-red, iot, mqtt, http, coap, websockets, diffrent protocols with node-red
+---
+
+# Using Different Protocols for Building Applications with Node-RED
+
+In IoT development, effective communication between devices is essential. This communication is facilitated by various protocols like MQTT, HTTP, CoAP, and WebSockets. Each protocol brings its own set of strengths and is suited for different IoT scenarios. However, understanding which protocol is suited for what scenario and utilizing it can be quite difficult. That's why we have created this section of resources where you will find documentation on using different communication protocols with Node-RED.
+
+Node-RED, with its intuitive visual programming interface, simplifies the integration of these protocols. Whether you're publishing sensor data over MQTT, triggering HTTP requests, querying CoAP endpoints, or enabling real-time communication with WebSockets, Node-RED provides a flexible and powerful platform.
+
+## Resources
+
+Here are some resources to help you get started with integrating Node-RED with various communication protocols:
+
+- [Building Secure OPC-UA Server in Node-RED.](/docs/node-red/protocol/opc-ua/): Learn how to build Build and Deploy a custom OPC UA Server in Node-RED
+- [Using AMQP with Node-RED](/docs/node-red/protocol/amqp/): Learn how to integrate AMQP with Node-RED for reliable message delivery, advanced routing, and improved data management in your flows.
+- [Using LwM2M with Node-RED](/docs/node-red/protocol/lwm2m/): Learn how to integrate LwM2M with Node-RED for effective IoT device management. This guide covers setup, data handling, and remote commands.
+- [Using Modbus with Node-RED](/docs/node-red/protocol/modbus/): Learn to use Modbus with Node-RED, including how to build a Modbus server and how to send and read data to and from that server.
+- [Using MQTT with Node-RED](/docs/node-red/protocol/mqtt/): Learn how to use MQTT with Node-RED.
+- [Using Websocket with Node-RED](/docs/node-red/protocol/websocket/)
+
+::callout{icon="i-lucide-badge-check"}
+**Certified nodes for these protocols.** Two protocols are also covered by a FlowFuse certified node, maintained for production use. EtherNet/IP, for Rockwell and Allen-Bradley controllers, has no page of its own in this section, and is documented with its certified node: [cip-suite](/integrations/?certified=1), [opcua](/integrations/?certified=1)
+::
diff --git a/src/node-red/protocol/amqp.md b/nuxt/content-guides/node-red/protocol/amqp.md
similarity index 97%
rename from src/node-red/protocol/amqp.md
rename to nuxt/content-guides/node-red/protocol/amqp.md
index 6cdca8a1b1..abc014545c 100644
--- a/src/node-red/protocol/amqp.md
+++ b/nuxt/content-guides/node-red/protocol/amqp.md
@@ -1,17 +1,17 @@
---
-eleventyNavigation:
- key: AMQP
- parent: "Communication Protocols"
+title: Using AMQP with Node-RED
+metaTitle: "Using AMQP with Node-RED"
+navTitle: AMQP
+navOrder: 50
meta:
- title: Using AMQP with Node-RED
description: Learn how to integrate AMQP with Node-RED for reliable message delivery, advanced routing, and improved data management in your flows.
keywords: node-red amqp, node-red rabbitmq, how to use amqp with node-red, how to use rabbitmq with node-red, rabbitmq node red, amqp node red
-image: /node-red/protocol/images/amqp-with-node-red.png
+image: /docs/node-red/protocol/images/amqp-with-node-red.png
---
-# {{meta.title}}
+# Using AMQP with Node-RED
-Imagine your Node-RED flow working well, handling data from different sources, until suddenly, messages start disappearing or arriving out of order. [MQTT](/node-red/protocol/mqtt/) works fine for basic messaging, but it can struggle in more complex situations where you need delivery guarantees and advanced routing.
+Imagine your Node-RED flow working well, handling data from different sources, until suddenly, messages start disappearing or arriving out of order. [MQTT](/docs/node-red/protocol/mqtt/) works fine for basic messaging, but it can struggle in more complex situations where you need delivery guarantees and advanced routing.
That’s where AMQP comes in. AMQP solves these issues with features that MQTT doesn’t have. In this guide, we'll explain what AMQP is and how to use it with Node-RED.
@@ -108,12 +108,14 @@ Configure the node by dragging an AMQP node onto the canvas. Double-click the no
1. Add two `amqp-in` nodes on to the canvas. Configure one to listen for messages with the `routingKey` of `"zone1"` and the other with `"zone2"`. Both nodes should be set to the `"irrigation_control"` exchange.
2. Connect each `amqp-in` node to a `debug` node to see the received commands for each zone.
-
+
_Video showing the flow that uses the Direct exchange type to send messages and receive messages_
-{% renderFlow %}
+::render-flow
+```json
[{"id":"efe7a260307e6202","type":"amqp-out","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","reconnectOnError":true,"exchangeName":"irrigation_control","exchangeType":"direct","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":true,"amqpProperties":"{ \"headers\": {} }","rpcTimeoutMilliseconds":3000,"outputs":0,"x":470,"y":160,"wires":[]},{"id":"538de33f548833ac","type":"inject","z":"807758ec576fbfd8","name":"Send command to zone 1","props":[{"p":"payload"},{"p":"routingKey","v":"zone1","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{ \"command\": \"start\" }","payloadType":"json","x":230,"y":100,"wires":[["efe7a260307e6202"]]},{"id":"20cfe04fab562ea9","type":"inject","z":"807758ec576fbfd8","name":"Send command to zone 2","props":[{"p":"payload"},{"p":"routingKey","v":"zone2","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{ \"command\": \"stop\" }","payloadType":"str","x":230,"y":240,"wires":[["efe7a260307e6202"]]},{"id":"7a5e0f3a66dc1ccc","type":"amqp-in","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","prefetch":0,"reconnectOnError":true,"noAck":true,"exchangeName":"irrigation_control","exchangeType":"direct","exchangeRoutingKey":"zone1","exchangeDurable":true,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{}","x":230,"y":360,"wires":[["63c5671d6f4efd07"]]},{"id":"4bf1b44b656c35c2","type":"amqp-in","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","prefetch":0,"reconnectOnError":true,"noAck":true,"exchangeName":"irrigation_control","exchangeType":"direct","exchangeRoutingKey":"zone2","exchangeDurable":true,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{}","x":230,"y":440,"wires":[["e7d4fabe9ef668fe"]]},{"id":"63c5671d6f4efd07","type":"debug","z":"807758ec576fbfd8","name":"Zone 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":500,"y":360,"wires":[]},{"id":"e7d4fabe9ef668fe","type":"debug","z":"807758ec576fbfd8","name":"Zone 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":500,"y":440,"wires":[]},{"id":"bfb1e7e97eef5e04","type":"amqp-broker","name":"AMQP Config","host":"localhost","port":"5672","vhost":"","tls":false,"credsFromSettings":false}]
-{% endrenderFlow %}
+```
+::
We configured a Direct type exchange in Node-RED to route messages to specific queues based on the routing key. We demonstrated how to send and receive commands in a smart irrigation system, ensuring that messages for different zones are delivered correctly. This setup is proper when you need precise message delivery based on an exact match with the routing key.
@@ -133,12 +135,14 @@ We configured a Direct type exchange in Node-RED to route messages to specific q
1. Add two `amqp-in` nodes on to the canvas. Configure one to listen for messages with the `routingKey` of `"temperature.*"` and the other with `"humidity.*"`. Both nodes should be set to the `"weather_data"` exchange.
2. Connect each `amqp-in` node to a `debug` node to view the sensor data received.
-
+
_Video showing the flow that uses the Topic exchange type to send messages and receive messages_
-{% renderFlow %}
+::render-flow
+```json
[{"id":"06ca737a23c93c75","type":"inject","z":"807758ec576fbfd8","name":"Temp sensor 1","props":[{"p":"payload"},{"p":"routingKey","v":"temperature.sensor1","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 100\t","payloadType":"jsonata","x":180,"y":600,"wires":[["653aec372ecb68a3"]]},{"id":"653aec372ecb68a3","type":"amqp-out","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","reconnectOnError":false,"exchangeName":"weather_data","exchangeType":"topic","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":true,"amqpProperties":"{ \"headers\": {} }","rpcTimeoutMilliseconds":3000,"outputs":0,"x":420,"y":660,"wires":[]},{"id":"39546cb6c75044e2","type":"inject","z":"807758ec576fbfd8","name":"Temp sensor 2","props":[{"p":"payload"},{"p":"routingKey","v":"temperature.sensor2","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 100\t","payloadType":"jsonata","x":180,"y":660,"wires":[["653aec372ecb68a3"]]},{"id":"04d4056a8719343d","type":"inject","z":"807758ec576fbfd8","name":"Temp sensor 3","props":[{"p":"payload"},{"p":"routingKey","v":"temperature.sensor3","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 100\t","payloadType":"jsonata","x":180,"y":720,"wires":[["653aec372ecb68a3"]]},{"id":"a7c55eb38bb5f828","type":"amqp-in","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","prefetch":0,"reconnectOnError":false,"noAck":true,"exchangeName":"weather_data","exchangeType":"topic","exchangeRoutingKey":"temperature.*","exchangeDurable":true,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{}","x":460,"y":840,"wires":[["0052a9fab812002f"]]},{"id":"4ac0d82df137f4be","type":"amqp-in","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","prefetch":0,"reconnectOnError":false,"noAck":true,"exchangeName":"weather_data","exchangeType":"topic","exchangeRoutingKey":"humidity.*","exchangeDurable":true,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{}","x":450,"y":920,"wires":[["58f86db958f9c32d"]]},{"id":"a367734d77bd5dcd","type":"inject","z":"807758ec576fbfd8","name":"Hum sensor 1","props":[{"p":"payload"},{"p":"routingKey","v":"humidity.sensor1","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 200\t","payloadType":"jsonata","x":690,"y":580,"wires":[["04248194cccf8c7a"]]},{"id":"04248194cccf8c7a","type":"amqp-out","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","reconnectOnError":false,"exchangeName":"weather_data","exchangeType":"topic","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":true,"amqpProperties":"{ \"headers\": {} }","rpcTimeoutMilliseconds":3000,"outputs":0,"x":940,"y":640,"wires":[]},{"id":"3cd4806e1bb64564","type":"inject","z":"807758ec576fbfd8","name":"Hum sensor 2","props":[{"p":"payload"},{"p":"routingKey","v":"humidity.sensor2","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 100\t","payloadType":"jsonata","x":690,"y":640,"wires":[["04248194cccf8c7a"]]},{"id":"35725dfe285e0db1","type":"inject","z":"807758ec576fbfd8","name":"Hum sensor 3","props":[{"p":"payload"},{"p":"routingKey","v":"humidity.sensor3","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 100\t","payloadType":"jsonata","x":690,"y":700,"wires":[["04248194cccf8c7a"]]},{"id":"0052a9fab812002f","type":"debug","z":"807758ec576fbfd8","name":"Temperature sensors data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":840,"wires":[]},{"id":"58f86db958f9c32d","type":"debug","z":"807758ec576fbfd8","name":"Humidity sensors data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":760,"y":920,"wires":[]},{"id":"bfb1e7e97eef5e04","type":"amqp-broker","name":"AMQP Config","host":"localhost","port":"5672","vhost":"","tls":false,"credsFromSettings":false}]
-{% endrenderFlow %}
+```
+::
We explored the Topic type exchange, which allows for more flexible routing using wildcard patterns in the routing key. The example involved a smart weather station where data from various sensors is published and handled based on sensor types. This setup is ideal for situations where you need to route messages based on partial matches or patterns, offering more granular control over message delivery.
@@ -157,12 +161,14 @@ Scenario: You have a smart home system with various components, such as lights,
1. Drag `amqp-in` nodes onto the canvas. Configure one to listen for messages from the `"weather_data"` exchange.
2. Connect the `amqp-in` node to a `debug` node to see the update received from all your components' data.
-
+
_Video showing the flow that uses the Fanout exchange type to send and receive messages._
-{% renderFlow %}
+::render-flow
+```json
[{"id":"7beb4237ba09010b","type":"inject","z":"807758ec576fbfd8","name":"Light update","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Light turned on","payloadType":"str","x":170,"y":1220,"wires":[["d699cd735cc8a0ae"]]},{"id":"8818f122c8937e58","type":"inject","z":"807758ec576fbfd8","name":"thermostats update","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"A new firmware update is available for your thermostat","payloadType":"str","x":190,"y":1280,"wires":[["d699cd735cc8a0ae"]]},{"id":"517aad7b163d5bde","type":"inject","z":"807758ec576fbfd8","name":"Camera update","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Movement detected","payloadType":"str","x":180,"y":1340,"wires":[["d699cd735cc8a0ae"]]},{"id":"d699cd735cc8a0ae","type":"amqp-out","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","reconnectOnError":false,"exchangeName":"system_updates","exchangeType":"fanout","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":true,"amqpProperties":"{ \"headers\": {} }","rpcTimeoutMilliseconds":3000,"outputs":0,"x":460,"y":1280,"wires":[]},{"id":"1db4056b4c66cb22","type":"amqp-in","z":"807758ec576fbfd8","name":"","broker":"bfb1e7e97eef5e04","prefetch":0,"reconnectOnError":true,"noAck":false,"exchangeName":"system_updates","exchangeType":"fanout","exchangeRoutingKey":"","exchangeDurable":true,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{}","x":180,"y":1520,"wires":[["2392e7d9139813a3"]]},{"id":"2392e7d9139813a3","type":"debug","z":"807758ec576fbfd8","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":420,"y":1520,"wires":[]},{"id":"bfb1e7e97eef5e04","type":"amqp-broker","name":"AMQP Config","host":"localhost","port":"5672","vhost":"","tls":false,"credsFromSettings":false}]
-{% endrenderFlow %}
+```
+::
We used a Fanout type exchange to broadcast messages to all queues connected to the exchange. We illustrated this with a smart home system where status updates from different components are sent to all devices simultaneously. This type of exchange is perfect for scenarios where you need to send the same message to multiple recipients without concern for routing keys.
@@ -181,11 +187,13 @@ We used a Fanout type exchange to broadcast messages to all queues connected to
1. Drag two `amqp-in` nodes on to the canvas. Configure one to listen for messages with the `headers` of `{ "x-match": "all," "machine-type": "CNC," "status": "error," "priority": "high"}` and the other with `{ "x-match": "any," machine-type": "A," "status": "idle," "priority": "high"}.` Both nodes should be set to the `system_update` exchange.
2. Connect each `amqp-in` node to a `debug` node to see the updates received for each component.
-
+
_Video showing the flow that uses the Headers exchange type to send messages and receive messages_
-{% renderFlow %}
+::render-flow
+```json
[{"id":"12c8048f.4eaefb","type":"amqp-in","z":"e4fe9c44.6dee1","name":"","broker":"83e9bf71fbe099c8","prefetch":0,"reconnectOnError":true,"noAck":true,"exchangeName":"machines_update","exchangeType":"headers","exchangeRoutingKey":"","exchangeDurable":false,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{\"x-match\":\"all\",\"machine-type\":\"CNC\",\"status\":\"error\",\"priority\":\"high\"}","x":170,"y":1000,"wires":[["8ec3fa87.70c338"]]},{"id":"6eccc4f.c6a2a3c","type":"amqp-out","z":"e4fe9c44.6dee1","name":"","broker":"83e9bf71fbe099c8","reconnectOnError":true,"exchangeName":"machines_update","exchangeType":"headers","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":false,"amqpProperties":"{}","rpcTimeoutMilliseconds":"","outputs":0,"x":530,"y":780,"wires":[]},{"id":"cb5093bf.1d524","type":"inject","z":"e4fe9c44.6dee1","name":"CNC machine: error occured","props":[{"p":"payload"},{"p":"properties","v":"{\"headers\":{\"machine-type\":\"CNC\",\"status\":\"error\",\"priority\":\"high\"}}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Errror occured in the CNC machine","payloadType":"str","x":200,"y":780,"wires":[["6eccc4f.c6a2a3c"]]},{"id":"8ec3fa87.70c338","type":"debug","z":"e4fe9c44.6dee1","name":"Only from CNC machines that has status error and priority high","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":610,"y":1000,"wires":[]},{"id":"d4c2f84b51d2d3cb","type":"amqp-out","z":"e4fe9c44.6dee1","name":"","broker":"83e9bf71fbe099c8","reconnectOnError":true,"exchangeName":"machines_update","exchangeType":"headers","exchangeRoutingKey":"","exchangeRoutingKeyType":"str","exchangeDurable":false,"amqpProperties":"{}","rpcTimeoutMilliseconds":"","outputs":0,"x":530,"y":840,"wires":[]},{"id":"81c21e9941e06a58","type":"inject","z":"e4fe9c44.6dee1","name":"Update from Machine A","props":[{"p":"payload"},{"p":"properties","v":"{\"headers\":{\"machine-type\":\"A\",\"status\":\"idle\",\"priority\":\"high\"}}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Machine A is currently idle, awaiting next operation.","payloadType":"str","x":180,"y":840,"wires":[["d4c2f84b51d2d3cb"]]},{"id":"abe55aafb5f65eac","type":"debug","z":"e4fe9c44.6dee1","name":"From all of the machines having status idle or priority high","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":570,"y":1120,"wires":[]},{"id":"adfcaa95122a3556","type":"amqp-in","z":"e4fe9c44.6dee1","name":"","broker":"83e9bf71fbe099c8","prefetch":0,"reconnectOnError":true,"noAck":true,"exchangeName":"machines_update","exchangeType":"headers","exchangeRoutingKey":"","exchangeDurable":false,"queueName":"","queueExclusive":true,"queueDurable":false,"queueAutoDelete":true,"headers":"{\"x-match\":\"any\",\"machine-type\":\"A\",\"status\":\"idle\",\"priority\":\"high\"}","x":170,"y":1120,"wires":[["abe55aafb5f65eac"]]},{"id":"83e9bf71fbe099c8","type":"amqp-broker","name":"","host":"localhost","port":"5672","vhost":"","tls":false,"credsFromSettings":false}]
-{% endrenderFlow %}
+```
+::
Finally, we configured a Headers type exchange, which routes messages based on attributes in the message headers. The example focused on a factory monitoring system, where updates from machines are routed based on criteria like machine type, status, and priority. This exchange type is powerful for complex routing scenarios where decisions are based on multiple attributes rather than just the routing key.
diff --git a/src/node-red/protocol/images/PLC-Information-Model-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-1.png
diff --git a/src/node-red/protocol/images/PLC-Information-Model-2-of-6-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-2-of-6-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-2-of-6-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-2-of-6-1.png
diff --git a/src/node-red/protocol/images/PLC-Information-Model-3-of-6-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-3-of-6-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-3-of-6-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-3-of-6-1.png
diff --git a/src/node-red/protocol/images/PLC-Information-Model-4-of-6-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-4-of-6-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-4-of-6-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-4-of-6-1.png
diff --git a/src/node-red/protocol/images/PLC-Information-Model-5-of-6-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-5-of-6-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-5-of-6-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-5-of-6-1.png
diff --git a/src/node-red/protocol/images/PLC-Information-Model-6-of-6-1.png b/nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-6-of-6-1.png
similarity index 100%
rename from src/node-red/protocol/images/PLC-Information-Model-6-of-6-1.png
rename to nuxt/content-guides/node-red/protocol/images/PLC-Information-Model-6-of-6-1.png
diff --git a/src/node-red/protocol/images/amqp-with-node-red.png b/nuxt/content-guides/node-red/protocol/images/amqp-with-node-red.png
similarity index 100%
rename from src/node-red/protocol/images/amqp-with-node-red.png
rename to nuxt/content-guides/node-red/protocol/images/amqp-with-node-red.png
diff --git a/src/node-red/protocol/images/cert-list.png b/nuxt/content-guides/node-red/protocol/images/cert-list.png
similarity index 100%
rename from src/node-red/protocol/images/cert-list.png
rename to nuxt/content-guides/node-red/protocol/images/cert-list.png
diff --git a/src/node-red/protocol/images/cert-tab-filled.png b/nuxt/content-guides/node-red/protocol/images/cert-tab-filled.png
similarity index 100%
rename from src/node-red/protocol/images/cert-tab-filled.png
rename to nuxt/content-guides/node-red/protocol/images/cert-tab-filled.png
diff --git a/src/node-red/protocol/images/change-node-palette.png b/nuxt/content-guides/node-red/protocol/images/change-node-palette.png
similarity index 100%
rename from src/node-red/protocol/images/change-node-palette.png
rename to nuxt/content-guides/node-red/protocol/images/change-node-palette.png
diff --git a/src/node-red/protocol/images/change-node-properties.png b/nuxt/content-guides/node-red/protocol/images/change-node-properties.png
similarity index 100%
rename from src/node-red/protocol/images/change-node-properties.png
rename to nuxt/content-guides/node-red/protocol/images/change-node-properties.png
diff --git a/src/node-red/protocol/images/client-cert-path-filled.png b/nuxt/content-guides/node-red/protocol/images/client-cert-path-filled.png
similarity index 100%
rename from src/node-red/protocol/images/client-cert-path-filled.png
rename to nuxt/content-guides/node-red/protocol/images/client-cert-path-filled.png
diff --git a/src/node-red/protocol/images/client-cert-path.png b/nuxt/content-guides/node-red/protocol/images/client-cert-path.png
similarity index 100%
rename from src/node-red/protocol/images/client-cert-path.png
rename to nuxt/content-guides/node-red/protocol/images/client-cert-path.png
diff --git a/src/node-red/protocol/images/client-testing.webm b/nuxt/content-guides/node-red/protocol/images/client-testing.webm
similarity index 100%
rename from src/node-red/protocol/images/client-testing.webm
rename to nuxt/content-guides/node-red/protocol/images/client-testing.webm
diff --git a/src/node-red/protocol/images/compact-server-active.png b/nuxt/content-guides/node-red/protocol/images/compact-server-active.png
similarity index 100%
rename from src/node-red/protocol/images/compact-server-active.png
rename to nuxt/content-guides/node-red/protocol/images/compact-server-active.png
diff --git a/src/node-red/protocol/images/compact-server-node-address-space.png b/nuxt/content-guides/node-red/protocol/images/compact-server-node-address-space.png
similarity index 100%
rename from src/node-red/protocol/images/compact-server-node-address-space.png
rename to nuxt/content-guides/node-red/protocol/images/compact-server-node-address-space.png
diff --git a/src/node-red/protocol/images/connect-rejected.png b/nuxt/content-guides/node-red/protocol/images/connect-rejected.png
similarity index 100%
rename from src/node-red/protocol/images/connect-rejected.png
rename to nuxt/content-guides/node-red/protocol/images/connect-rejected.png
diff --git a/src/node-red/protocol/images/connected-mqtt-node.png b/nuxt/content-guides/node-red/protocol/images/connected-mqtt-node.png
similarity index 100%
rename from src/node-red/protocol/images/connected-mqtt-node.png
rename to nuxt/content-guides/node-red/protocol/images/connected-mqtt-node.png
diff --git a/src/node-red/protocol/images/context-data-1.png b/nuxt/content-guides/node-red/protocol/images/context-data-1.png
similarity index 100%
rename from src/node-red/protocol/images/context-data-1.png
rename to nuxt/content-guides/node-red/protocol/images/context-data-1.png
diff --git a/src/node-red/protocol/images/context-refresh.png b/nuxt/content-guides/node-red/protocol/images/context-refresh.png
similarity index 100%
rename from src/node-red/protocol/images/context-refresh.png
rename to nuxt/content-guides/node-red/protocol/images/context-refresh.png
diff --git a/src/node-red/protocol/images/conveyor-context-function.png b/nuxt/content-guides/node-red/protocol/images/conveyor-context-function.png
similarity index 100%
rename from src/node-red/protocol/images/conveyor-context-function.png
rename to nuxt/content-guides/node-red/protocol/images/conveyor-context-function.png
diff --git a/src/node-red/protocol/images/copied-certs-with-pubkey.png b/nuxt/content-guides/node-red/protocol/images/copied-certs-with-pubkey.png
similarity index 100%
rename from src/node-red/protocol/images/copied-certs-with-pubkey.png
rename to nuxt/content-guides/node-red/protocol/images/copied-certs-with-pubkey.png
diff --git a/src/node-red/protocol/images/copied-certs.png b/nuxt/content-guides/node-red/protocol/images/copied-certs.png
similarity index 100%
rename from src/node-red/protocol/images/copied-certs.png
rename to nuxt/content-guides/node-red/protocol/images/copied-certs.png
diff --git a/src/node-red/protocol/images/copy-certs.png b/nuxt/content-guides/node-red/protocol/images/copy-certs.png
similarity index 100%
rename from src/node-red/protocol/images/copy-certs.png
rename to nuxt/content-guides/node-red/protocol/images/copy-certs.png
diff --git a/src/node-red/protocol/images/custom-nodes-installed.png b/nuxt/content-guides/node-red/protocol/images/custom-nodes-installed.png
similarity index 100%
rename from src/node-red/protocol/images/custom-nodes-installed.png
rename to nuxt/content-guides/node-red/protocol/images/custom-nodes-installed.png
diff --git a/src/node-red/protocol/images/debug-data.png b/nuxt/content-guides/node-red/protocol/images/debug-data.png
similarity index 100%
rename from src/node-red/protocol/images/debug-data.png
rename to nuxt/content-guides/node-red/protocol/images/debug-data.png
diff --git a/src/node-red/protocol/images/deploy-flow.png b/nuxt/content-guides/node-red/protocol/images/deploy-flow.png
similarity index 100%
rename from src/node-red/protocol/images/deploy-flow.png
rename to nuxt/content-guides/node-red/protocol/images/deploy-flow.png
diff --git a/src/node-red/protocol/images/der-file.png b/nuxt/content-guides/node-red/protocol/images/der-file.png
similarity index 100%
rename from src/node-red/protocol/images/der-file.png
rename to nuxt/content-guides/node-red/protocol/images/der-file.png
diff --git a/src/node-red/protocol/images/direct.webm b/nuxt/content-guides/node-red/protocol/images/direct.webm
similarity index 100%
rename from src/node-red/protocol/images/direct.webm
rename to nuxt/content-guides/node-red/protocol/images/direct.webm
diff --git a/src/node-red/protocol/images/eth-ip-debug.png b/nuxt/content-guides/node-red/protocol/images/eth-ip-debug.png
similarity index 100%
rename from src/node-red/protocol/images/eth-ip-debug.png
rename to nuxt/content-guides/node-red/protocol/images/eth-ip-debug.png
diff --git a/src/node-red/protocol/images/eth-ip-endpoint-tags.png b/nuxt/content-guides/node-red/protocol/images/eth-ip-endpoint-tags.png
similarity index 100%
rename from src/node-red/protocol/images/eth-ip-endpoint-tags.png
rename to nuxt/content-guides/node-red/protocol/images/eth-ip-endpoint-tags.png
diff --git a/src/node-red/protocol/images/eth-ip-in-palette.png b/nuxt/content-guides/node-red/protocol/images/eth-ip-in-palette.png
similarity index 100%
rename from src/node-red/protocol/images/eth-ip-in-palette.png
rename to nuxt/content-guides/node-red/protocol/images/eth-ip-in-palette.png
diff --git a/src/node-red/protocol/images/eth-ip-in-properties.png b/nuxt/content-guides/node-red/protocol/images/eth-ip-in-properties.png
similarity index 100%
rename from src/node-red/protocol/images/eth-ip-in-properties.png
rename to nuxt/content-guides/node-red/protocol/images/eth-ip-in-properties.png
diff --git a/src/node-red/protocol/images/ethip-node-connection.png b/nuxt/content-guides/node-red/protocol/images/ethip-node-connection.png
similarity index 100%
rename from src/node-red/protocol/images/ethip-node-connection.png
rename to nuxt/content-guides/node-red/protocol/images/ethip-node-connection.png
diff --git a/src/node-red/protocol/images/example-flow.png b/nuxt/content-guides/node-red/protocol/images/example-flow.png
similarity index 100%
rename from src/node-red/protocol/images/example-flow.png
rename to nuxt/content-guides/node-red/protocol/images/example-flow.png
diff --git a/src/node-red/protocol/images/executing-command-from-server.webm b/nuxt/content-guides/node-red/protocol/images/executing-command-from-server.webm
similarity index 100%
rename from src/node-red/protocol/images/executing-command-from-server.webm
rename to nuxt/content-guides/node-red/protocol/images/executing-command-from-server.webm
diff --git a/src/node-red/protocol/images/fanout.webm b/nuxt/content-guides/node-red/protocol/images/fanout.webm
similarity index 100%
rename from src/node-red/protocol/images/fanout.webm
rename to nuxt/content-guides/node-red/protocol/images/fanout.webm
diff --git a/src/node-red/protocol/images/flow-manage-palette.png b/nuxt/content-guides/node-red/protocol/images/flow-manage-palette.png
similarity index 100%
rename from src/node-red/protocol/images/flow-manage-palette.png
rename to nuxt/content-guides/node-red/protocol/images/flow-manage-palette.png
diff --git a/src/node-red/protocol/images/flow-with-change-palette.png b/nuxt/content-guides/node-red/protocol/images/flow-with-change-palette.png
similarity index 100%
rename from src/node-red/protocol/images/flow-with-change-palette.png
rename to nuxt/content-guides/node-red/protocol/images/flow-with-change-palette.png
diff --git a/src/node-red/protocol/images/flow-with-compact-server.png b/nuxt/content-guides/node-red/protocol/images/flow-with-compact-server.png
similarity index 100%
rename from src/node-red/protocol/images/flow-with-compact-server.png
rename to nuxt/content-guides/node-red/protocol/images/flow-with-compact-server.png
diff --git a/src/node-red/protocol/images/flowforge-nodered-mqtt-hivemq.png b/nuxt/content-guides/node-red/protocol/images/flowforge-nodered-mqtt-hivemq.png
similarity index 100%
rename from src/node-red/protocol/images/flowforge-nodered-mqtt-hivemq.png
rename to nuxt/content-guides/node-red/protocol/images/flowforge-nodered-mqtt-hivemq.png
diff --git a/src/node-red/protocol/images/header.webm b/nuxt/content-guides/node-red/protocol/images/header.webm
similarity index 100%
rename from src/node-red/protocol/images/header.webm
rename to nuxt/content-guides/node-red/protocol/images/header.webm
diff --git a/src/node-red/protocol/images/image-20230717-212515.png b/nuxt/content-guides/node-red/protocol/images/image-20230717-212515.png
similarity index 100%
rename from src/node-red/protocol/images/image-20230717-212515.png
rename to nuxt/content-guides/node-red/protocol/images/image-20230717-212515.png
diff --git a/src/node-red/protocol/images/image-20230718-155245.png b/nuxt/content-guides/node-red/protocol/images/image-20230718-155245.png
similarity index 100%
rename from src/node-red/protocol/images/image-20230718-155245.png
rename to nuxt/content-guides/node-red/protocol/images/image-20230718-155245.png
diff --git a/src/node-red/protocol/images/image-20230718-164326.png b/nuxt/content-guides/node-red/protocol/images/image-20230718-164326.png
similarity index 100%
rename from src/node-red/protocol/images/image-20230718-164326.png
rename to nuxt/content-guides/node-red/protocol/images/image-20230718-164326.png
diff --git a/src/node-red/protocol/images/import-context.png b/nuxt/content-guides/node-red/protocol/images/import-context.png
similarity index 100%
rename from src/node-red/protocol/images/import-context.png
rename to nuxt/content-guides/node-red/protocol/images/import-context.png
diff --git a/src/node-red/protocol/images/import.png b/nuxt/content-guides/node-red/protocol/images/import.png
similarity index 100%
rename from src/node-red/protocol/images/import.png
rename to nuxt/content-guides/node-red/protocol/images/import.png
diff --git a/src/node-red/protocol/images/individual-cert-file-option.png b/nuxt/content-guides/node-red/protocol/images/individual-cert-file-option.png
similarity index 100%
rename from src/node-red/protocol/images/individual-cert-file-option.png
rename to nuxt/content-guides/node-red/protocol/images/individual-cert-file-option.png
diff --git a/src/node-red/protocol/images/install-eth-ip-node.png b/nuxt/content-guides/node-red/protocol/images/install-eth-ip-node.png
similarity index 100%
rename from src/node-red/protocol/images/install-eth-ip-node.png
rename to nuxt/content-guides/node-red/protocol/images/install-eth-ip-node.png
diff --git a/src/node-red/protocol/images/lwm2m-server-reading.webm b/nuxt/content-guides/node-red/protocol/images/lwm2m-server-reading.webm
similarity index 100%
rename from src/node-red/protocol/images/lwm2m-server-reading.webm
rename to nuxt/content-guides/node-red/protocol/images/lwm2m-server-reading.webm
diff --git a/src/node-red/protocol/images/modbus-1-1.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-1.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-1.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-1.png
diff --git a/src/node-red/protocol/images/modbus-1-10.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-10.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-10.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-10.png
diff --git a/src/node-red/protocol/images/modbus-1-11.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-11.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-11.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-11.png
diff --git a/src/node-red/protocol/images/modbus-1-12.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-12.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-12.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-12.png
diff --git a/src/node-red/protocol/images/modbus-1-13.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-13.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-13.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-13.png
diff --git a/src/node-red/protocol/images/modbus-1-14.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-14.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-14.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-14.png
diff --git a/src/node-red/protocol/images/modbus-1-15.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-15.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-15.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-15.png
diff --git a/src/node-red/protocol/images/modbus-1-16.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-16.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-16.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-16.png
diff --git a/src/node-red/protocol/images/modbus-1-2.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-2.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-2.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-2.png
diff --git a/src/node-red/protocol/images/modbus-1-3.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-3.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-3.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-3.png
diff --git a/src/node-red/protocol/images/modbus-1-4.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-4.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-4.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-4.png
diff --git a/src/node-red/protocol/images/modbus-1-5.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-5.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-5.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-5.png
diff --git a/src/node-red/protocol/images/modbus-1-6.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-6.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-6.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-6.png
diff --git a/src/node-red/protocol/images/modbus-1-7.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-7.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-7.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-7.png
diff --git a/src/node-red/protocol/images/modbus-1-8.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-8.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-8.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-8.png
diff --git a/src/node-red/protocol/images/modbus-1-9.png b/nuxt/content-guides/node-red/protocol/images/modbus-1-9.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-1-9.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-1-9.png
diff --git a/src/node-red/protocol/images/modbus-1.jpg b/nuxt/content-guides/node-red/protocol/images/modbus-1.jpg
similarity index 100%
rename from src/node-red/protocol/images/modbus-1.jpg
rename to nuxt/content-guides/node-red/protocol/images/modbus-1.jpg
diff --git a/src/node-red/protocol/images/modbus-node-red-cta-1.png b/nuxt/content-guides/node-red/protocol/images/modbus-node-red-cta-1.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-node-red-cta-1.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-node-red-cta-1.png
diff --git a/src/node-red/protocol/images/modbus-server.png b/nuxt/content-guides/node-red/protocol/images/modbus-server.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-server.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-server.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-change-node.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-change-node.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-change-node.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-change-node.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-combine-holding-register-data.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-combine-holding-register-data.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-combine-holding-register-data.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-combine-holding-register-data.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-combine-output-coils-data.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-combine-output-coils-data.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-combine-output-coils-data.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-combine-output-coils-data.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-dashboard.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-dashboard.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-dashboard.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-dashboard.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-send-holding-registers.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-send-holding-registers.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-send-holding-registers.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-send-holding-registers.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-send-output-coil.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-send-output-coil.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-send-output-coil.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-send-output-coil.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-template-widget-stylesheet.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-template-widget-stylesheet.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-template-widget-stylesheet.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-template-widget-stylesheet.png
diff --git a/src/node-red/protocol/images/modbus-with-node-red-text-node.png b/nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-text-node.png
similarity index 100%
rename from src/node-red/protocol/images/modbus-with-node-red-text-node.png
rename to nuxt/content-guides/node-red/protocol/images/modbus-with-node-red-text-node.png
diff --git a/src/node-red/protocol/images/mqtt-broker-config.png b/nuxt/content-guides/node-red/protocol/images/mqtt-broker-config.png
similarity index 100%
rename from src/node-red/protocol/images/mqtt-broker-config.png
rename to nuxt/content-guides/node-red/protocol/images/mqtt-broker-config.png
diff --git a/src/node-red/protocol/images/mqtt-in-config-node-red.png b/nuxt/content-guides/node-red/protocol/images/mqtt-in-config-node-red.png
similarity index 100%
rename from src/node-red/protocol/images/mqtt-in-config-node-red.png
rename to nuxt/content-guides/node-red/protocol/images/mqtt-in-config-node-red.png
diff --git a/src/node-red/protocol/images/mqtt-in-config.png b/nuxt/content-guides/node-red/protocol/images/mqtt-in-config.png
similarity index 100%
rename from src/node-red/protocol/images/mqtt-in-config.png
rename to nuxt/content-guides/node-red/protocol/images/mqtt-in-config.png
diff --git a/src/node-red/protocol/images/mqtt-out.png b/nuxt/content-guides/node-red/protocol/images/mqtt-out.png
similarity index 100%
rename from src/node-red/protocol/images/mqtt-out.png
rename to nuxt/content-guides/node-red/protocol/images/mqtt-out.png
diff --git a/src/node-red/protocol/images/msg-payload.png b/nuxt/content-guides/node-red/protocol/images/msg-payload.png
similarity index 100%
rename from src/node-red/protocol/images/msg-payload.png
rename to nuxt/content-guides/node-red/protocol/images/msg-payload.png
diff --git a/src/node-red/protocol/images/node-red-config-mqtt-server.png b/nuxt/content-guides/node-red/protocol/images/node-red-config-mqtt-server.png
similarity index 100%
rename from src/node-red/protocol/images/node-red-config-mqtt-server.png
rename to nuxt/content-guides/node-red/protocol/images/node-red-config-mqtt-server.png
diff --git a/src/node-red/protocol/images/opc-client-accept-cert.png b/nuxt/content-guides/node-red/protocol/images/opc-client-accept-cert.png
similarity index 100%
rename from src/node-red/protocol/images/opc-client-accept-cert.png
rename to nuxt/content-guides/node-red/protocol/images/opc-client-accept-cert.png
diff --git a/src/node-red/protocol/images/opc-client-connect.png b/nuxt/content-guides/node-red/protocol/images/opc-client-connect.png
similarity index 100%
rename from src/node-red/protocol/images/opc-client-connect.png
rename to nuxt/content-guides/node-red/protocol/images/opc-client-connect.png
diff --git a/src/node-red/protocol/images/opc-folder-structure.png b/nuxt/content-guides/node-red/protocol/images/opc-folder-structure.png
similarity index 100%
rename from src/node-red/protocol/images/opc-folder-structure.png
rename to nuxt/content-guides/node-red/protocol/images/opc-folder-structure.png
diff --git a/src/node-red/protocol/images/opc-nodes-install.png b/nuxt/content-guides/node-red/protocol/images/opc-nodes-install.png
similarity index 100%
rename from src/node-red/protocol/images/opc-nodes-install.png
rename to nuxt/content-guides/node-red/protocol/images/opc-nodes-install.png
diff --git a/src/node-red/protocol/images/opc-nodes.png b/nuxt/content-guides/node-red/protocol/images/opc-nodes.png
similarity index 100%
rename from src/node-red/protocol/images/opc-nodes.png
rename to nuxt/content-guides/node-red/protocol/images/opc-nodes.png
diff --git a/src/node-red/protocol/images/opc-ua-2-title-image.png b/nuxt/content-guides/node-red/protocol/images/opc-ua-2-title-image.png
similarity index 100%
rename from src/node-red/protocol/images/opc-ua-2-title-image.png
rename to nuxt/content-guides/node-red/protocol/images/opc-ua-2-title-image.png
diff --git a/src/node-red/protocol/images/reading-data-from-lwm2m-from-server.webm b/nuxt/content-guides/node-red/protocol/images/reading-data-from-lwm2m-from-server.webm
similarity index 100%
rename from src/node-red/protocol/images/reading-data-from-lwm2m-from-server.webm
rename to nuxt/content-guides/node-red/protocol/images/reading-data-from-lwm2m-from-server.webm
diff --git a/src/node-red/protocol/images/reading-data-from-server-in-nr.webm b/nuxt/content-guides/node-red/protocol/images/reading-data-from-server-in-nr.webm
similarity index 100%
rename from src/node-red/protocol/images/reading-data-from-server-in-nr.webm
rename to nuxt/content-guides/node-red/protocol/images/reading-data-from-server-in-nr.webm
diff --git a/src/node-red/protocol/images/security-tab-default.png b/nuxt/content-guides/node-red/protocol/images/security-tab-default.png
similarity index 100%
rename from src/node-red/protocol/images/security-tab-default.png
rename to nuxt/content-guides/node-red/protocol/images/security-tab-default.png
diff --git a/src/node-red/protocol/images/server-testing.webm b/nuxt/content-guides/node-red/protocol/images/server-testing.webm
similarity index 100%
rename from src/node-red/protocol/images/server-testing.webm
rename to nuxt/content-guides/node-red/protocol/images/server-testing.webm
diff --git a/src/node-red/protocol/images/sign&encrypt.png b/nuxt/content-guides/node-red/protocol/images/sign&encrypt.png
similarity index 100%
rename from src/node-red/protocol/images/sign&encrypt.png
rename to nuxt/content-guides/node-red/protocol/images/sign&encrypt.png
diff --git a/src/node-red/protocol/images/sine-wave-gen.png b/nuxt/content-guides/node-red/protocol/images/sine-wave-gen.png
similarity index 100%
rename from src/node-red/protocol/images/sine-wave-gen.png
rename to nuxt/content-guides/node-red/protocol/images/sine-wave-gen.png
diff --git a/src/node-red/protocol/images/ssl-pub-keygen.png b/nuxt/content-guides/node-red/protocol/images/ssl-pub-keygen.png
similarity index 100%
rename from src/node-red/protocol/images/ssl-pub-keygen.png
rename to nuxt/content-guides/node-red/protocol/images/ssl-pub-keygen.png
diff --git a/src/node-red/protocol/images/topic.webm b/nuxt/content-guides/node-red/protocol/images/topic.webm
similarity index 100%
rename from src/node-red/protocol/images/topic.webm
rename to nuxt/content-guides/node-red/protocol/images/topic.webm
diff --git a/src/node-red/protocol/images/using-lwm2m-with-node-red.png b/nuxt/content-guides/node-red/protocol/images/using-lwm2m-with-node-red.png
similarity index 100%
rename from src/node-red/protocol/images/using-lwm2m-with-node-red.png
rename to nuxt/content-guides/node-red/protocol/images/using-lwm2m-with-node-red.png
diff --git a/src/node-red/protocol/images/websocket-handshake.png b/nuxt/content-guides/node-red/protocol/images/websocket-handshake.png
similarity index 100%
rename from src/node-red/protocol/images/websocket-handshake.png
rename to nuxt/content-guides/node-red/protocol/images/websocket-handshake.png
diff --git a/src/node-red/protocol/images/writing-data-to-server-from-nr.webm b/nuxt/content-guides/node-red/protocol/images/writing-data-to-server-from-nr.webm
similarity index 100%
rename from src/node-red/protocol/images/writing-data-to-server-from-nr.webm
rename to nuxt/content-guides/node-red/protocol/images/writing-data-to-server-from-nr.webm
diff --git a/src/node-red/protocol/images/writing-in-server.webm b/nuxt/content-guides/node-red/protocol/images/writing-in-server.webm
similarity index 100%
rename from src/node-red/protocol/images/writing-in-server.webm
rename to nuxt/content-guides/node-red/protocol/images/writing-in-server.webm
diff --git a/src/node-red/protocol/lwm2m.md b/nuxt/content-guides/node-red/protocol/lwm2m.md
similarity index 89%
rename from src/node-red/protocol/lwm2m.md
rename to nuxt/content-guides/node-red/protocol/lwm2m.md
index e0b94b5113..0e520d8f86 100644
--- a/src/node-red/protocol/lwm2m.md
+++ b/nuxt/content-guides/node-red/protocol/lwm2m.md
@@ -1,16 +1,15 @@
---
-eleventyNavigation:
- key: LwM2M
- parent: "Communication Protocols"
+title: Using LwM2M with Node-RED
+metaTitle: "Using LwM2M with Node-RED"
+navTitle: LwM2M
+navOrder: 50
meta:
- title: Using LwM2M with Node-RED
description: Learn how to integrate LwM2M with Node-RED for effective IoT device management. This guide covers setup, data handling, and remote commands.
- keywords: how to use lwm2m with node red, lwm2m protocol, node-red modbus, lightweight m2m with node red
- modbus
-image: /node-red/protocol/images/using-lwm2m-with-node-red.png
+ keywords: how to use lwm2m with node red, lwm2m protocol, node-red modbus, lightweight m2m with node red modbus
+image: /docs/node-red/protocol/images/using-lwm2m-with-node-red.png
---
-# {{meta.title}}
+# Using LwM2M with Node-RED
IoT devices, especially those designed for low-power operation, can be difficult to manage due to their limited resources and the need for efficient communication and control. This is where LwM2M (Lightweight Machine-to-Machine) comes in. LwM2M is designed to help you monitor, update, and control your devices with minimal overhead, making it ideal for everything from smart sensors to industrial equipment. In this post, we'll explore how you can use LwM2M with Node-RED. It is ideal for anyone starting their journey with LwM2M or Node-RED.
@@ -82,7 +81,7 @@ Once you've configured the LwM2M node with the server details, you can confirm t
3. Below this, you'll find the available objects that you can control for your devices and server.
4. Click on the "Device" object option to read device realted information. In the instance 0 section click on the "R" for each object you want. Alternatively, you can click on the top "R" next to instance 0 or "Device-v1.0" to read all values at once. Note that this may not work if any values are unavailable for your device, it will return 404 not found.
-
+
_Video showing LwM2M Server reading the device details_
You can now read information such as device battery level, available memory, device manufacturer, timezone, device type, and a lot.
@@ -95,7 +94,7 @@ You can now read information such as device battery level, available memory, dev
4. In the form that opens, enter the new value in the correct format.
5. Click on "Write" to update the value for that resource.
-
+
*Video showing how to perform write operation in the LwM2M server*
6. Drag the **lwm2m client** node onto the canvas, select the correct configuration, and enable the "Subscribe LwM2M object events" option. This setting will trigger and send an event object when commands are executed on the server.
@@ -103,7 +102,7 @@ You can now read information such as device battery level, available memory, dev
8. Connect the output of the **lwm2m client** node to the input of the **exec** node.
9. To execute the commands, click on the 'exec' option next to resources such as Reboot.
-
+
*Video showing the LwM2M server executing reboot command for device*
### Reading Data and Configuration from the LwM2M Server in Node-RED
@@ -114,7 +113,7 @@ You can now read information such as device battery level, available memory, dev
4. Connect the output of the **inject** node to the input of the LwM2M client node, and connect the output of the **lwm2m client** node to the input of the **debug** node.
5. Deploy the flow by clicking on the top-right "deploy" button.
-
+
_Video showing Node-RED flow that is reading data from LwM2M Server_
### Writing data and configuration to the LwM2M Server from Node-RED
@@ -126,7 +125,7 @@ _Video showing Node-RED flow that is reading data from LwM2M Server_
5. Connect the **inject** node's output to the input of **lwm2m client out** node.
6. Deploy the flow and click the inject button to perform the write operation.
-
+
_Video showing Node-RED flow that is writing data to LwM2M Server_
-In the same way, you can execute commands from node-red. You have to replace the notion and end that notion with `execute`, like `0/0/4/execute.` When executing the command, you will not have to specify the `msg.payload`.
\ No newline at end of file
+In the same way, you can execute commands from node-red. You have to replace the notion and end that notion with `execute`, like `0/0/4/execute.` When executing the command, you will not have to specify the `msg.payload`.
diff --git a/src/node-red/protocol/modbus.md b/nuxt/content-guides/node-red/protocol/modbus.md
similarity index 97%
rename from src/node-red/protocol/modbus.md
rename to nuxt/content-guides/node-red/protocol/modbus.md
index 9bf7a3e122..504c2d64b6 100644
--- a/src/node-red/protocol/modbus.md
+++ b/nuxt/content-guides/node-red/protocol/modbus.md
@@ -1,25 +1,21 @@
---
-eleventyNavigation:
- key: Modbus
- parent: "Communication Protocols"
+title: Using Modbus with Node-RED
+metaTitle: "Using Modbus with Node-RED"
+navTitle: Modbus
+navOrder: 50
meta:
- title: Using Modbus with Node-RED
description: Learn to use Modbus with Node-RED, including how to build a Modbus server and how to send and read data to and from that server.
- keywords: node red modbus, node-red-contrib-modbus, node-red modbus, modbus node red, modbus nodered, node red modbus rtu, modbus failure on state sending get more about it by logging, node red modbus server
- modbus
+ keywords: node red modbus, node-red-contrib-modbus, node-red modbus, modbus node red, modbus nodered, node red modbus rtu, modbus failure on state sending get more about it by logging, node red modbus server modbus
---
-# {{meta.title}}
+# Using Modbus with Node-RED
In manufacturing companies there is often a small set of production data, currently only available to an equipment operator through the HMI, which would be enormously valuable to a greater audience if there were some way to easily display and share it.
Node-RED, along with Modbus and Dashboard modules, can easily create a web-based dashboard, shareable with a weblink and viewable on any web browser on the network. Imagine the advantages of digital signage in the breakroom spurring healthy competition or a manager being able to check daily totals and live process values from the phone in their pocket.
-
-
-
+::cta-image{src="/docs/node-red/protocol/images/modbus-node-red-cta-1.png" alt="Read Modbus data from every device on your floor, not just one instance" cta="sign-up" reference="Node-RED: Using Modbus with Node-RED"}
+::
## What is Modbus
@@ -141,9 +137,11 @@ The output coil data is displayed on the dashboard using a text widget. When the
Final flow is given below:
-{% renderFlow 300 %}
+::render-flow{:height="300"}
+```json
[{"id":"4cf44f4cbc592b99","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"b48b43414657ca4e","type":"modbus-read","z":"4cf44f4cbc592b99","name":"","topic":"text","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"Coil","adr":"0","quantity":"5","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"145bc96e15c34554","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":130,"y":540,"wires":[["f6fb47f18928d28f","3bf66c619694a1a4","35bc45f58dc5c661","5b3a8b0c7cd968fa","f87af242b2287b7c"],[]]},{"id":"e28ae04240af481e","type":"modbus-read","z":"4cf44f4cbc592b99","name":"","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"HoldingRegister","adr":"0","quantity":"4","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"145bc96e15c34554","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":130,"y":800,"wires":[["9dd39216e9bbd6fd","c4389848cebd29c7","dffa222847521883","286d69415ef78e7c"],[]]},{"id":"c302edd625716894","type":"modbus-server","z":"4cf44f4cbc592b99","name":"Modbus server","logEnabled":false,"hostname":"127.0.0.1","serverPort":"10502","responseDelay":100,"delayUnit":"ms","coilsBufferSize":10000,"holdingBufferSize":10000,"inputBufferSize":10000,"discreteBufferSize":10000,"showErrors":false,"x":520,"y":260,"wires":[[],[],[],[],[]]},{"id":"7f20fcaea773cb1b","type":"inject","z":"4cf44f4cbc592b99","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":260,"wires":[["c302edd625716894"]]},{"id":"bc7bdfd9d81369af","type":"inject","z":"4cf44f4cbc592b99","name":"","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$random() * 150","payloadType":"jsonata","x":110,"y":1020,"wires":[["2c019b52b54a2e0d"]]},{"id":"2c019b52b54a2e0d","type":"join","z":"4cf44f4cbc592b99","name":"combine holiding register data","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"4","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":1020,"wires":[["8bf7d588de60fb33"]]},{"id":"6c14cb9ab888c12d","type":"inject","z":"4cf44f4cbc592b99","name":"","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":110,"y":1140,"wires":[["1a59e443e0258194"]]},{"id":"1a59e443e0258194","type":"join","z":"4cf44f4cbc592b99","name":"combine coil output data","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"5","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":330,"y":1140,"wires":[["cdb7e5d53210cb6d"]]},{"id":"62338bd2af1d3c0d","type":"modbus-response","z":"4cf44f4cbc592b99","name":"","registerShowMax":20,"x":870,"y":1020,"wires":[]},{"id":"d1eff51eac0af203","type":"modbus-response","z":"4cf44f4cbc592b99","name":"","registerShowMax":20,"x":870,"y":1120,"wires":[]},{"id":"8bf7d588de60fb33","type":"modbus-write","z":"4cf44f4cbc592b99","name":"send holding registers","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"MHoldingRegisters","adr":"0","quantity":"4","server":"145bc96e15c34554","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":640,"y":1020,"wires":[["62338bd2af1d3c0d"],[]]},{"id":"cdb7e5d53210cb6d","type":"modbus-write","z":"4cf44f4cbc592b99","name":"send output coils ","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"MCoils","adr":"0","quantity":"5","server":"145bc96e15c34554","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":630,"y":1140,"wires":[["d1eff51eac0af203"],[]]},{"id":"405acf6300a072d6","type":"ui-text","z":"4cf44f4cbc592b99","group":"a00b86fb96b216a6","order":1,"width":0,"height":0,"name":"","label":"isEStopReleased","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":690,"y":460,"wires":[]},{"id":"52cb610e23488ba2","type":"ui-text","z":"4cf44f4cbc592b99","group":"a00b86fb96b216a6","order":3,"width":0,"height":0,"name":"","label":"isMotorSwitchedOn","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":690,"y":500,"wires":[]},{"id":"224a2c2948d7d9a5","type":"ui-text","z":"4cf44f4cbc592b99","group":"a00b86fb96b216a6","order":4,"width":0,"height":0,"name":"","label":"isMotorRunning","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":680.111083984375,"y":537.7777709960938,"wires":[]},{"id":"82fce135993ad1ab","type":"ui-text","z":"4cf44f4cbc592b99","group":"a00b86fb96b216a6","order":5,"width":0,"height":0,"name":"","label":"isTailswitchPulsing","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":690,"y":580,"wires":[]},{"id":"f6fb47f18928d28f","type":"change","z":"4cf44f4cbc592b99","name":"isEStopReleased","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0]","tot":"msg"},{"t":"set","p":"class","pt":"msg","to":"msg.payload ? \"green\":\"red\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":460,"wires":[["405acf6300a072d6"]]},{"id":"3bf66c619694a1a4","type":"change","z":"4cf44f4cbc592b99","name":"isMotorSwitchedOn","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[1]","tot":"msg"},{"t":"set","p":"class","pt":"msg","to":"msg.payload ? \"green\":\"red\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":500,"wires":[["52cb610e23488ba2"]]},{"id":"35bc45f58dc5c661","type":"change","z":"4cf44f4cbc592b99","name":"isMotorRunning","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[2]","tot":"msg"},{"t":"set","p":"class","pt":"msg","to":"msg.payload ? \"green\":\"red\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":540,"wires":[["224a2c2948d7d9a5"]]},{"id":"5b3a8b0c7cd968fa","type":"change","z":"4cf44f4cbc592b99","name":"isTailswitchPulsing","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[3]","tot":"msg"},{"t":"set","p":"class","pt":"msg","to":"msg.payload ? \"green\":\"red\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":580,"wires":[["82fce135993ad1ab"]]},{"id":"f87af242b2287b7c","type":"change","z":"4cf44f4cbc592b99","name":"isMaterialOnBelt","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[4]","tot":"msg"},{"t":"set","p":"class","pt":"msg","to":"msg.payload ? \"green\":\"red\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":620,"wires":[["7ab41bd5d19d5f7f"]]},{"id":"7ab41bd5d19d5f7f","type":"ui-text","z":"4cf44f4cbc592b99","group":"a00b86fb96b216a6","order":2,"width":0,"height":0,"name":"","label":"isMaterialOnBelt","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":680,"y":620,"wires":[]},{"id":"cc8b32c267214e28","type":"ui-template","z":"4cf44f4cbc592b99","group":"","page":"","ui":"5ff82627d2caf841","name":"stylesheet","order":0,"width":0,"height":0,"head":"","format":".green span {\n color: green;\n}\n\n.red span {\n color: red;\n}\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"site:style","className":"","x":940,"y":560,"wires":[[]]},{"id":"c4f0157670882335","type":"ui-gauge","z":"4cf44f4cbc592b99","name":"motorAmps","group":"ef2cffe3b927bbb6","order":1,"width":"0","height":"0","gtype":"gauge-half","gstyle":"needle","title":"gauge","units":"units","icon":"","prefix":"","suffix":"","segments":[{"from":"0","color":"#ba6e26"},{"from":"100","color":"#ba6e26"}],"min":0,"max":"150","sizeThickness":16,"sizeGap":4,"sizeKeyThickness":8,"styleRounded":true,"styleGlow":false,"className":"","x":710,"y":760,"wires":[]},{"id":"df73d7c58bbf6069","type":"ui-text","z":"4cf44f4cbc592b99","group":"ef2cffe3b927bbb6","order":2,"width":0,"height":0,"name":"","label":"motorHourMeter","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":720,"y":800,"wires":[]},{"id":"4d14a50a008a4606","type":"ui-text","z":"4cf44f4cbc592b99","group":"98ab0c19d66959eb","order":2,"width":0,"height":0,"name":"","label":"beltTotalTons","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":710,"y":880,"wires":[]},{"id":"9dd39216e9bbd6fd","type":"change","z":"4cf44f4cbc592b99","name":"motorAmps","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":760,"wires":[["c4f0157670882335"]]},{"id":"c4389848cebd29c7","type":"change","z":"4cf44f4cbc592b99","name":"motorHourMeter","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[1]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":800,"wires":[["df73d7c58bbf6069"]]},{"id":"dffa222847521883","type":"change","z":"4cf44f4cbc592b99","name":"beltTonsPerHour","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[2]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":840,"wires":[["b45120d07ed4a8bb"]]},{"id":"286d69415ef78e7c","type":"change","z":"4cf44f4cbc592b99","name":"beltTotalTons","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[3]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":880,"wires":[["4d14a50a008a4606"]]},{"id":"b45120d07ed4a8bb","type":"ui-chart","z":"4cf44f4cbc592b99","group":"98ab0c19d66959eb","name":"beltTonsPerHour","label":"chart","order":1,"chartType":"line","category":"beltTonsPerHour","categoryType":"str","xAxisLabel":"","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"time","yAxisLabel":"","yAxisProperty":"","ymin":"","ymax":"","action":"append","pointShape":"false","pointRadius":4,"showLegend":true,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"6","height":"5","className":"","x":730,"y":840,"wires":[[]]},{"id":"af0626137803b160","type":"comment","z":"4cf44f4cbc592b99","name":"Reading holding register data from modbus server","info":"","x":510,"y":700,"wires":[]},{"id":"bf74f24e625763ff","type":"comment","z":"4cf44f4cbc592b99","name":"Sending output coil data to modbus server","info":"","x":480,"y":1080,"wires":[]},{"id":"c5ab6f8dcb96b79b","type":"comment","z":"4cf44f4cbc592b99","name":"Sending holding register data to modbus server","info":"","x":500,"y":960,"wires":[]},{"id":"8e1387959a33f353","type":"comment","z":"4cf44f4cbc592b99","name":"Reading output coil data from modbus server","info":"","x":490,"y":400,"wires":[]},{"id":"b85a4192ee8a8c38","type":"comment","z":"4cf44f4cbc592b99","name":"Modbus server ","info":"","x":300,"y":180,"wires":[]},{"id":"145bc96e15c34554","type":"modbus-client","name":"Modbus server","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showErrors":false,"showWarnings":true,"showLogs":true},{"id":"a00b86fb96b216a6","type":"ui-group","name":"Output coils","page":"3876c3cdc50d68a5","width":"3","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"5ff82627d2caf841","type":"ui-base","name":"My Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"navigationStyle":"default","titleBarStyle":"default"},{"id":"ef2cffe3b927bbb6","type":"ui-group","name":"Holding registers","page":"3876c3cdc50d68a5","width":"3","height":"3","order":2,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"98ab0c19d66959eb","type":"ui-group","name":"holding register ","page":"3876c3cdc50d68a5","width":"6","height":"1","order":3,"showTitle":false,"className":"","visible":"true","disabled":"false"},{"id":"3876c3cdc50d68a5","type":"ui-page","name":"Home","ui":"5ff82627d2caf841","path":"/","icon":"home","layout":"grid","theme":"36efce4ebdf1ae91","order":1,"className":"","visible":false,"disabled":"false"},{"id":"36efce4ebdf1ae91","type":"ui-theme","name":"Default Theme","colors":{"surface":"#0094ce","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
-{% endrenderFlow %}
+```
+::
The way that we set up this example worked well for the small sample size and quickly getting content on the dashboard, but as you work through your own needs, think about the data structures that will be the most conducive to efficiently working with your data.
diff --git a/src/node-red/protocol/mqtt.md b/nuxt/content-guides/node-red/protocol/mqtt.md
similarity index 97%
rename from src/node-red/protocol/mqtt.md
rename to nuxt/content-guides/node-red/protocol/mqtt.md
index eec5f60105..08982507e2 100644
--- a/src/node-red/protocol/mqtt.md
+++ b/nuxt/content-guides/node-red/protocol/mqtt.md
@@ -1,15 +1,14 @@
---
-eleventyNavigation:
- key: MQTT
- parent: "Communication Protocols"
- title: MQTT
+title: Using MQTT with Node-RED
+metaTitle: "Using MQTT with Node-RED"
+navTitle: MQTT
+navOrder: 50
meta:
- title: Using MQTT with Node-RED
description: Learn how to use MQTT with Node-RED.
keywords: node red mqtt in, nodered mqtt, mqtt node red, node-red mqtt, node-red mqtt broker, node red mqtt dynamic subscription, mqtt broker node red, nodered mqtt broker, node red mqtt out, mqtt in node red
---
-# {{meta.title}}
+# Using MQTT with Node-RED
Getting devices to talk to each other in industrial environments isn't trivial. You're dealing with spotty networks, power constraints, and devices that need to share data without constant back-and-forth polling. MQTT solves these problems by keeping communication lightweight and flexible. This guide walks you through what MQTT is, why it works well for IIoT, and how to get it running with Node-RED.
diff --git a/src/node-red/protocol/opc-ua.md b/nuxt/content-guides/node-red/protocol/opc-ua.md
similarity index 98%
rename from src/node-red/protocol/opc-ua.md
rename to nuxt/content-guides/node-red/protocol/opc-ua.md
index d180ae0d28..36cbe748ba 100644
--- a/src/node-red/protocol/opc-ua.md
+++ b/nuxt/content-guides/node-red/protocol/opc-ua.md
@@ -1,22 +1,15 @@
---
-eleventyNavigation:
- key: OPC-UA
- parent: "Communication Protocols"
+title: Building Secure OPC-UA Server in Node-RED.
+metaTitle: "Building Secure OPC-UA Server in Node-RED."
+navTitle: OPC-UA
+navOrder: 50
meta:
- title: Building Secure OPC-UA Server in Node-RED.
- description: Learn how to build Build and Deploy a custom OPC UA Server in Node-RED
- keywords: node-red,flowfuse, opc-ua,
-image: /node-red/protocol/images/opc-ua-2-title-image.png
-certified:
- - "@flowfuse-certified-nodes/opcua"
- - "@flowfuse-certified-nodes/cip-suite"
-certifiedIntro: >
- This guide builds the server from community packages. Both halves of it, OPC UA
- and the Allen Bradley Ethernet/IP link, also have a FlowFuse certified node
- maintained for production use:
+ description: Learn how to build Build and Deploy a custom OPC UA Server in Node-RED
+ keywords: node-red,flowfuse, opc-ua,
+image: /docs/node-red/protocol/images/opc-ua-2-title-image.png
---
-# {{meta.title}}
+# Building Secure OPC-UA Server in Node-RED.
OPC-UA (OPC Unified Architecture) is a communication protocol designed for industrial automation. It enables seamless data exchange and interoperability between various devices, systems, and software applications in the industrial domain. OPC-UA offers secure and reliable communication, making it a preferred choice for building robust industrial solutions. In this document, we will delve into the creation of a fully custom secure OPC-UA Server for PLCs in Node-RED.
@@ -62,7 +55,9 @@ Now that we have laid out a concept for our application, let’s build it.
## Install Custom Nodes
-{% include "components/certified-node-callout.liquid" %}
+::callout{icon="i-lucide-badge-check"}
+**Certified nodes for this technology.** This guide builds the server from community packages. Both halves of it, OPC UA and the Allen Bradley Ethernet/IP link, also have a FlowFuse certified node maintained for production use: [opcua](/integrations/?certified=1), [cip-suite](/integrations/?certified=1)
+::
First, we need to add three custom nodes that will allow Node-RED to read Ethernet/IP data and add OPC UA Server functionality.
@@ -631,6 +626,8 @@ OPC UA is one of several industrial protocols FlowFuse uses to connect PLCs to t
Source code for flow used in this documentation -
-{% renderFlow %}
+::render-flow
+```json
[{"id":"2e8c7f5c.ab73d","type":"tab","label":"OPC-UA Custom Context Server","disabled":false,"info":""},{"id":"38ce10de.7d8c","type":"opcua-compact-server","z":"2e8c7f5c.ab73d","port":"54845","endpoint":"","productUri":"","acceptExternalCommands":true,"maxAllowedSessionNumber":"10","maxConnectionsPerEndpoint":"10","maxAllowedSubscriptionNumber":"100","alternateHostname":"","name":"","showStatusActivities":false,"showErrors":true,"allowAnonymous":false,"individualCerts":true,"isAuditing":false,"serverDiscovery":true,"users":[],"xmlsetsOPCUA":[],"publicCertificateFile":"/root/.node-red/node_modules/node-red-contrib-opcua-server/certificates/server_selfsigned_cert_2048.pem","privateCertificateFile":"/root/.node-red/node_modules/node-red-contrib-opcua-server/certificates/server_key_2048.pem","registerServerMethod":"1","discoveryServerEndpointUrl":"opc.tcp://192.168.0.114:54845","capabilitiesForMDNS":"","maxNodesPerRead":1000,"maxNodesPerWrite":1000,"maxNodesPerHistoryReadData":100,"maxNodesPerBrowse":3000,"maxBrowseContinuationPoints":"10","maxHistoryContinuationPoints":"10","delayToInit":"1000","delayToClose":"200","serverShutdownTimeout":"100","addressSpaceScript":"function constructAlarmAddressSpace(server, addressSpace, eventObjects, done) {\n // server = the created node-opcua server\n // addressSpace = address space of the node-opcua server\n // eventObjects = add event variables here to hold them in memory from this script\n\n // internal sandbox objects are:\n // node = the compact server node,\n // coreServer = core compact server object for debug and access to NodeOPCUA\n // this.sandboxNodeContext = node context node-red\n // this.sandboxFlowContext = flow context node-red\n // this.sandboxGlobalContext = global context node-red\n // this.sandboxEnv = env variables\n // timeout and interval functions as expected from nodejs\n\n const opcua = coreServer.choreCompact.opcua;\n const LocalizedText = opcua.LocalizedText;\n const namespace = addressSpace.getOwnNamespace();\n\n const Variant = opcua.Variant;\n const DataType = opcua.DataType;\n const DataValue = opcua.DataValue;\n\n var flexServerInternals = this;\n\n this.sandboxFlowContext.set(\"conveyorData.Conveyor_RTS\", false);\n this.sandboxFlowContext.set(\"conveyorData.Robot_RTS\", false);\n this.sandboxFlowContext.set(\"conveyorData.Robot_Position\", 0);\n this.sandboxFlowContext.set(\"conveyorData.Conveyor_Running\", false);\n this.sandboxFlowContext.set(\"conveyorData.Line4_State\", 0);\n this.sandboxFlowContext.set(\"conveyorData.Line4_Fault\", false);\n\n // this.sandboxFlowContext.set(\"isoInput1\", 0);\n // this.setInterval(() => {\n // flexServerInternals.sandboxFlowContext.set(\n // \"isoInput1\",\n // Math.random() + 50.0\n // );\n // }, 500);\n // this.sandboxFlowContext.set(\"isoInput2\", 0);\n // this.sandboxFlowContext.set(\"isoInput3\", 0);\n // this.sandboxFlowContext.set(\"isoInput4\", 0);\n // this.sandboxFlowContext.set(\"isoInput5\", 0);\n // this.sandboxFlowContext.set(\"isoInput6\", 0);\n // this.sandboxFlowContext.set(\"isoInput7\", 0);\n // this.sandboxFlowContext.set(\"isoInput8\", 0);\n // this.sandboxFlowContext.set(\"isoOutput1\", 0);\n // this.setInterval(() => {\n // flexServerInternals.sandboxFlowContext.set(\n // \"isoOutput1\",\n // Math.random() + 10.0\n // );\n // }, 500);\n\n // this.sandboxFlowContext.set(\"isoOutput2\", 0);\n // this.sandboxFlowContext.set(\"isoOutput3\", 0);\n // this.sandboxFlowContext.set(\"isoOutput4\", 0);\n // this.sandboxFlowContext.set(\"isoOutput5\", 0);\n // this.sandboxFlowContext.set(\"isoOutput6\", 0);\n // this.sandboxFlowContext.set(\"isoOutput7\", 0);\n // this.sandboxFlowContext.set(\"isoOutput8\", 0);\n\n coreServer.debugLog(\"init dynamic address space\");\n const rootFolder = addressSpace.findNode(\"RootFolder\");\n\n node.warn(\"construct new address space for OPC UA\");\n\n const myDevice = namespace.addFolder(rootFolder.objects, {\n \"browseName\": \"Line 4 PLC\"\n });\n const conveyorFolder = namespace.addFolder(myDevice, { \"browseName\": \"Conveyor\" });\n const conveyorBools = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"Bools\"\n });\n const conveyorDINTs = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"DINTs\"\n });\n const conveyorFloats = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"Floats\"\n });\n\n // Construct Nodes\n const Conveyor_RTS = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Conveyor Ready to Start\",\n \"nodeId\": \"ns=1;s=Conveyor_RTS\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Conveyor_RTS\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Conveyor_RTS\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Robot_RTS = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Robot Ready to Start\",\n \"nodeId\": \"ns=1;s=Robot_RTS\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Robot_RTS\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Robot_RTS\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Conveyor_Running = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Conveyor Running\",\n \"nodeId\": \"ns=1;s=Conveyor_Running\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Conveyor_Running\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Conveyor_Running\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Line4_Fault = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Line 4 Faulted\",\n \"nodeId\": \"ns=1;s=Line4_Fault\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Line4_Fault\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Line4_Fault\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Line4_State = namespace.addVariable({\n \"organizedBy\": conveyorDINTs,\n \"browseName\": \"Line 4 State\",\n \"nodeId\": \"ns=1;s=Line4_State\",\n \"dataType\": \"Int32\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Int32,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Line4_State\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Line4_State\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Robot_Position = namespace.addVariable({\n \"organizedBy\": conveyorFloats,\n \"browseName\": \"Robot Axis A1 Position\",\n \"nodeId\": \"ns=1;s=Robot_Position\",\n \"dataType\": \"Float\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Float,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Robot_Position\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Robot_Position\",\n parseFloat(variant.value)\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n //------------------------------------------------------------------------------\n // Add a view\n //------------------------------------------------------------------------------\n const viewBools = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line 4 Conveyor Bools\"\n });\n\n const viewDINTs = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line4 Conveyor DINTs\"\n });\n\n const viewFloats = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line4 Conveyor Floats\"\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Conveyor_RTS.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Robot_RTS.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Conveyor_Running.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Line4_Fault.nodeId\n });\n\n\n viewDINTs.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Line4_State.nodeId\n });\n\n viewFloats.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Robot_Position.nodeId\n });\n coreServer.debugLog(\"create dynamic address space done\");\n node.warn(\"construction of new address space for OPC UA done\");\n\n done();\n}\n","x":960,"y":600,"wires":[]},{"id":"7ae89f134415c51e","type":"eth-ip in","z":"2e8c7f5c.ab73d","endpoint":"f012042b75173b77","mode":"all","variable":"","program":"","name":"Read Line4 Conveyor tags","x":150,"y":600,"wires":[["0c51f44baa08a3b2"]]},{"id":"a0592280baea975b","type":"comment","z":"2e8c7f5c.ab73d","name":"read data from PLC & store in conveyorData context flow memory","info":"","x":350,"y":540,"wires":[]},{"id":"b411a5ce4749fa61","type":"comment","z":"2e8c7f5c.ab73d","name":"Secure OPC UA Server Publishing PLC conveyorData","info":"","x":980,"y":540,"wires":[]},{"id":"0c51f44baa08a3b2","type":"change","z":"2e8c7f5c.ab73d","name":"store PLC Data in flow context memory","rules":[{"t":"set","p":"conveyorData.Conveyor_RTS","pt":"flow","to":"payload.Conveyor_RTS","tot":"msg"},{"t":"set","p":"conveyorData.Conveyor_Running","pt":"flow","to":"payload.Conveyor_Running","tot":"msg"},{"t":"set","p":"conveyorData.Line4_Fault","pt":"flow","to":"payload.Line4_Fault","tot":"msg"},{"t":"set","p":"conveyorData.Line4_State","pt":"flow","to":"payload.Line4_State","tot":"msg"},{"t":"set","p":"conveyorData.Robot_Position","pt":"flow","to":"payload.Robot_Position","tot":"msg"},{"t":"set","p":"conveyorData.Robot_RTS","pt":"flow","to":"payload.Robot_RTS","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":600,"wires":[[]]},{"id":"f012042b75173b77","type":"eth-ip endpoint","address":"192.168.0.5","slot":"0","cycletime":"1000","name":"Line 4 PLC","vartable":{"":{"Conveyor_RTS":{"type":"BOOL"},"Conveyor_Running":{"type":"BOOL"},"Line4_Fault":{"type":"BOOL"},"Line4_State":{"type":"DINT"},"Robot_Position":{"type":"REAL"},"Robot_RTS":{"type":"BOOL"}}}}]
-{% endrenderFlow %}
+```
+::
diff --git a/src/node-red/protocol/websocket.md b/nuxt/content-guides/node-red/protocol/websocket.md
similarity index 93%
rename from src/node-red/protocol/websocket.md
rename to nuxt/content-guides/node-red/protocol/websocket.md
index 5f16a47e93..5830bbb5c9 100644
--- a/src/node-red/protocol/websocket.md
+++ b/nuxt/content-guides/node-red/protocol/websocket.md
@@ -1,15 +1,13 @@
---
-eleventyNavigation:
- key: Websocket
- parent: "Communication Protocols"
+title: Using Websocket with Node-RED
+metaTitle: "Using Websocket with Node-RED"
+navTitle: Websocket
+navOrder: 50
meta:
- title: Using Websocket with Node-RED
- description:
- keywords: node-red websocket, websocket in node-red, websocket node-red
-image:
+ keywords: node-red websocket, websocket in node-red, websocket node-red
---
-# {{meta.title}}
+# Using Websocket with Node-RED
This guide covers WebSocket communication in Node-RED. You'll learn how to connect as a client and set up your own WebSocket server.
@@ -64,7 +62,7 @@ Before creating the server, it's important to understand that we will need to li
### Testing the WebSocket Server
-
+
_Testing the WebSocket server with a Websocket client_
Now that you have deployed the Node-RED flow, it is acting as a server that can both send and receive data. To test the server, you can use the [Simple WebSocket Client](https://chromewebstore.google.com/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo?hl=en) extension in your browser. Make sure to install this extension if you want to test the server.
@@ -104,9 +102,9 @@ Now, as the section states, we are going to see how you can connect to the WebSo
### Testing the WebSocket Client
-
+
_Testing Websocket Client with Websocket Server_
Now, to test the client, you can send messages from the server and see the debug window for that message in the client instance. Similarly, you can send messages from the client Instance to the server and observe the responses in the debug window of server instance.
-For more information on the advaced websocket node configuration refer to the [Websocket Node Documentation](/node-red/core-nodes/websocket/)
\ No newline at end of file
+For more information on the advaced websocket node configuration refer to the [Websocket Node Documentation](/docs/node-red/core-nodes/network/websocket/)
diff --git a/src/node-red/terminology/index.md b/nuxt/content-guides/node-red/terminology/README.md
similarity index 95%
rename from src/node-red/terminology/index.md
rename to nuxt/content-guides/node-red/terminology/README.md
index 40a00f8b79..97eae7cd8c 100644
--- a/src/node-red/terminology/index.md
+++ b/nuxt/content-guides/node-red/terminology/README.md
@@ -1,11 +1,11 @@
---
-eleventyNavigation:
- key: Terminology
- order: 2
+title: Node-RED Terminology
+metaTitle: "Node-RED Terminology"
+navTitle: Terminology
+navOrder: 10
meta:
- title: Node-RED Terminology
- description: Explore key terms and concepts used within the Node-RED community, including flows, nodes, subflows, workspace, and more.
- keywords: node-red, node-red terminology, node-red concepts, node-red key terms
+ description: Explore key terms and concepts used within the Node-RED community, including flows, nodes, subflows, workspace, and more.
+ keywords: node-red, node-red terminology, node-red concepts, node-red key terms
---
# Node-RED Terminology
@@ -33,7 +33,7 @@ A Node is a fundamental building block used to create flows. Each node represent
{data-zoomable}
## Core-Node
-The core nodes are the set of nodes that are included with the Node-RED runtime by default, without the need for a node installation procedure. For more information on core nodes, refer to the [Core node docs](/node-red/core-nodes/).
+The core nodes are the set of nodes that are included with the Node-RED runtime by default, without the need for a node installation procedure. For more information on core nodes, refer to the [Core node docs](/docs/node-red/core-nodes/).
## Wires
The "wires" refer to the connections that link nodes together to define the flow of data. These wires visually represent the direction and flow of information from one node to another within a Node-RED flow.
diff --git a/src/node-red/terminology/images/editor-flow-tabs.png b/nuxt/content-guides/node-red/terminology/images/editor-flow-tabs.png
similarity index 100%
rename from src/node-red/terminology/images/editor-flow-tabs.png
rename to nuxt/content-guides/node-red/terminology/images/editor-flow-tabs.png
diff --git a/src/node-red/terminology/images/editor-workspace.png b/nuxt/content-guides/node-red/terminology/images/editor-workspace.png
similarity index 100%
rename from src/node-red/terminology/images/editor-workspace.png
rename to nuxt/content-guides/node-red/terminology/images/editor-workspace.png
diff --git a/src/node-red/terminology/images/node-input-ouput-port.png b/nuxt/content-guides/node-red/terminology/images/node-input-ouput-port.png
similarity index 100%
rename from src/node-red/terminology/images/node-input-ouput-port.png
rename to nuxt/content-guides/node-red/terminology/images/node-input-ouput-port.png
diff --git a/src/node-red/terminology/images/node-palette.png b/nuxt/content-guides/node-red/terminology/images/node-palette.png
similarity index 100%
rename from src/node-red/terminology/images/node-palette.png
rename to nuxt/content-guides/node-red/terminology/images/node-palette.png
diff --git a/src/node-red/terminology/images/node-red-editor-deploy-button.png b/nuxt/content-guides/node-red/terminology/images/node-red-editor-deploy-button.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-editor-deploy-button.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-editor-deploy-button.png
diff --git a/src/node-red/terminology/images/node-red-editor.png b/nuxt/content-guides/node-red/terminology/images/node-red-editor.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-editor.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-editor.png
diff --git a/src/node-red/terminology/images/node-red-message-object.png b/nuxt/content-guides/node-red/terminology/images/node-red-message-object.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-message-object.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-message-object.png
diff --git a/src/node-red/terminology/images/node-red-node.png b/nuxt/content-guides/node-red/terminology/images/node-red-node.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-node.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-node.png
diff --git a/src/node-red/terminology/images/node-red-palette-manager.png b/nuxt/content-guides/node-red/terminology/images/node-red-palette-manager.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-palette-manager.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-palette-manager.png
diff --git a/src/node-red/terminology/images/node-red-subflow.png b/nuxt/content-guides/node-red/terminology/images/node-red-subflow.png
similarity index 100%
rename from src/node-red/terminology/images/node-red-subflow.png
rename to nuxt/content-guides/node-red/terminology/images/node-red-subflow.png
diff --git a/src/node-red/terminology/images/node-wire.png b/nuxt/content-guides/node-red/terminology/images/node-wire.png
similarity index 100%
rename from src/node-red/terminology/images/node-wire.png
rename to nuxt/content-guides/node-red/terminology/images/node-wire.png
diff --git a/nuxt/content.config.ts b/nuxt/content.config.ts
index 2980ad4135..3212253a2d 100644
--- a/nuxt/content.config.ts
+++ b/nuxt/content.config.ts
@@ -29,6 +29,11 @@ export default defineContentConfig({
source: 'docs/**/*.md',
schema: z.object({
navTitle: z.string().optional(),
+ // The browser/search-result title, when the sidebar label is too short to
+ // serve as one. Read by nuxt/pages/docs/[...slug].vue; like navGroupOrder
+ // below, an undeclared key is stripped from frontmatter, which would make
+ // that read silently undefined.
+ metaTitle: z.string().optional(),
navGroup: z.string().optional(),
// Read by useDocsNav to rank the sidebar group headings; without it
// declared here @nuxt/content strips the key from frontmatter.
diff --git a/nuxt/content/certified-nodes.yml b/nuxt/content/certified-nodes.yml
index da18573170..d566ec04a9 100644
--- a/nuxt/content/certified-nodes.yml
+++ b/nuxt/content/certified-nodes.yml
@@ -19,27 +19,27 @@ bundles:
- name: Redis
abbr: RE
description: In-memory cache and fast key/value store.
- url: /node-red/flowfuse/hub/redis/
+ url: /docs/flowfuse-nodes/hub/redis/
- name: MQTT
abbr: MQ
description: Lightweight pub/sub messaging for IoT and event-driven flows.
- url: /node-red/flowfuse/mqtt/
+ url: /docs/flowfuse-nodes/mqtt/
- name: HTTP Request
abbr: HT
description: Call REST APIs and web services.
- url: /node-red/core-nodes/http-request/
+ url: /docs/node-red/core-nodes/network/http-request/
- label: AI
nodes:
- name: AI nodes
abbr: AI
description: LLM-powered flows with Gemini, Claude, ChatGPT, and Ollama.
both: true
- url: /node-red/flowfuse/ai/llm-nodes/
+ url: /docs/flowfuse-nodes/ai/llm-nodes/
- name: MCP Server
abbr: MCP
description: Turn your flows into a Model Context Protocol server so AI agents can call your logic as tools.
both: true
- url: /node-red/flowfuse/mcp/
+ url: /docs/flowfuse-nodes/mcp/
- id: ot
label: Certified Nodes — OT
@@ -52,28 +52,28 @@ bundles:
- name: OPC-UA
abbr: OP
description: The standard for industrial machine interoperability.
- url: /node-red/flowfuse/edge/opcua/
+ url: /docs/flowfuse-nodes/edge/opcua/
- name: Modbus TCP & RTU
abbr: MO
description: Ubiquitous protocol for PLCs and field devices.
- url: /node-red/flowfuse/edge/modbus/
+ url: /docs/flowfuse-nodes/edge/modbus/
- name: RTSP
abbr: RT
description: Stream video from IP cameras.
- url: /node-red/flowfuse/edge/rtsp/
+ url: /docs/flowfuse-nodes/edge/rtsp/
- name: EtherNet/IP
abbr: EI
description: Rockwell / Allen-Bradley industrial Ethernet protocol.
- url: /node-red/flowfuse/edge/cip-suite/
+ url: /docs/flowfuse-nodes/edge/cip-suite/
- label: AI
nodes:
- name: AI nodes
abbr: AI
description: LLM-powered flows with Gemini, Claude, ChatGPT, and Ollama.
both: true
- url: /node-red/flowfuse/ai/llm-nodes/
+ url: /docs/flowfuse-nodes/ai/llm-nodes/
- name: MCP Server
abbr: MCP
description: Turn your flows into a Model Context Protocol server so AI agents can call your logic as tools.
both: true
- url: /node-red/flowfuse/mcp/
+ url: /docs/flowfuse-nodes/mcp/
diff --git a/nuxt/content/feature-catalog.yml b/nuxt/content/feature-catalog.yml
index c8d39316ef..b871670852 100644
--- a/nuxt/content/feature-catalog.yml
+++ b/nuxt/content/feature-catalog.yml
@@ -70,7 +70,7 @@ sections:
- id: mcp-servers
title: Agentic Operations
description: "Expose your Node-RED flows as tools an AI agent can call directly, so agents can query the state of the factory or trigger actions without custom integration work."
- docsLink: /node-red/flowfuse/mcp/
+ docsLink: /docs/flowfuse-nodes/mcp/
tiers: { edge: true, hub: true, fleet: true }
- id: onnx-integration
title: ONNX Integration
diff --git a/nuxt/content/products/edge.yml b/nuxt/content/products/edge.yml
index bf9db16721..71c70324a6 100644
--- a/nuxt/content/products/edge.yml
+++ b/nuxt/content/products/edge.yml
@@ -29,7 +29,7 @@ included:
- label: "MQTT Broker"
href: "/docs/user/teambroker/"
- label: "HTTP Request"
- href: "/node-red/core-nodes/http-request/"
+ href: "/docs/node-red/core-nodes/network/http-request/"
- title: "Develop & deploy at the edge"
chips:
- label: "Edge Development (remote editor proxy)"
diff --git a/nuxt/content/products/hub.yml b/nuxt/content/products/hub.yml
index 544ca7d072..dd8dbff788 100644
--- a/nuxt/content/products/hub.yml
+++ b/nuxt/content/products/hub.yml
@@ -37,14 +37,14 @@ included:
- title: "Certified for IT systems"
chips:
- label: "MQTT"
- href: "/node-red/flowfuse/mqtt/"
+ href: "/docs/flowfuse-nodes/mqtt/"
- label: "HTTP Request"
- href: "/node-red/core-nodes/http-request/"
+ href: "/docs/node-red/core-nodes/network/http-request/"
- "Kafka"
- label: "Redis"
- href: "/node-red/flowfuse/hub/redis/"
+ href: "/docs/flowfuse-nodes/hub/redis/"
- label: "AI nodes (Gemini, Claude, ChatGPT, Ollama)"
- href: "/node-red/flowfuse/ai/llm-nodes/"
+ href: "/docs/flowfuse-nodes/ai/llm-nodes/"
- title: "Governed by default"
chips:
- label: "Application-Level RBAC"
diff --git a/nuxt/lib/chrome.test.mjs b/nuxt/lib/chrome.test.mjs
index 5a4cac65d4..ffe5ac947a 100644
--- a/nuxt/lib/chrome.test.mjs
+++ b/nuxt/lib/chrome.test.mjs
@@ -42,9 +42,17 @@ test('no nav or footer link points at a redirected path', () => {
// accept it. So a page that was removed and redirected can sit in the nav
// indefinitely, still labelled, pointing somewhere it was never meant to.
// Advertise the destination, not the redirect.
+ // Both maps, because they are written in different shapes. nuxt/redirects.ts uses the
+ // full Nitro rule object; nuxt/redirects-node-red.ts is a plain `from: to` record fed
+ // through a builder. Reading only the first left every /node-red/** redirect invisible
+ // here, which is exactly the set most likely to be left behind in the nav.
const redirectsSrc = readFileSync(join(repo, 'nuxt/redirects.ts'), 'utf8')
+ const nodeRedSrc = readFileSync(join(repo, 'nuxt/redirects-node-red.ts'), 'utf8')
const sources = new Set(
- [...redirectsSrc.matchAll(/^\s*'([^']+)':\s*{\s*redirect:\s*{\s*to:\s*'([^']+)'/gm)]
+ [
+ ...redirectsSrc.matchAll(/^\s*'([^']+)':\s*{\s*redirect:\s*{\s*to:\s*'([^']+)'/gm),
+ ...nodeRedSrc.matchAll(/^\s*'([^']+)':\s*'([^']+)',/gm),
+ ]
// A rule whose destination is its own source sends the link nowhere
// else, so it is not the drift this test is looking for. There is one
// in the file today (/docs/user/expert/), which is its own bug.
diff --git a/nuxt/lib/custom-cta-destinations.ts b/nuxt/lib/custom-cta-destinations.ts
index c215211d6d..6a251d91d2 100644
--- a/nuxt/lib/custom-cta-destinations.ts
+++ b/nuxt/lib/custom-cta-destinations.ts
@@ -64,7 +64,7 @@ export const CUSTOM_CTA_DESTINATIONS = {
// Event name preserved from the hand-written capture() call this replaces
// on the OPC UA integration page (see the note above on migrated events).
opcuaCertifiedNodeDocs: {
- href: '/node-red/flowfuse/edge/opcua/',
+ href: '/docs/flowfuse-nodes/edge/opcua/',
event: 'cta-certified-opcua-node',
},
} as const
diff --git a/nuxt/lib/docs-page-title.mjs b/nuxt/lib/docs-page-title.mjs
new file mode 100644
index 0000000000..1eab7742aa
--- /dev/null
+++ b/nuxt/lib/docs-page-title.mjs
@@ -0,0 +1,20 @@
+// Which of a docs page's several titles becomes the browser and search-result title.
+//
+// Lives here rather than inline in nuxt/pages/docs/[...slug].vue so `node --test` can
+// assert the order. It is one expression, but it is the expression that decides what
+// Google shows for every page under /docs, and getting it wrong is invisible: the page
+// still renders, still builds, still passes the link checker, and simply has the wrong
+// title. That is exactly how the Node-RED library's pages lost theirs.
+
+/**
+ * @param {{metaTitle?: string|null, navTitle?: string|null, title?: string|null}|null} page
+ * @param {string[]} slugParts the docs path segments, used only as a last resort
+ * @returns {string}
+ */
+export function docsPageTitle (page, slugParts = []) {
+ // metaTitle first: navTitle is the sidebar label, kept short enough to fit the nav
+ // column, so a page whose full title is longer needs a way to say which one Google
+ // gets. Pages migrated off Eleventy carry it, and nothing in FlowFuse/flowfuse's docs
+ // sets it, so their titles are unaffected by its presence here.
+ return page?.metaTitle || page?.navTitle || page?.title || slugParts.at(-1) || 'Documentation'
+}
diff --git a/nuxt/lib/docs-page-title.test.mjs b/nuxt/lib/docs-page-title.test.mjs
new file mode 100644
index 0000000000..3cf5e075b7
--- /dev/null
+++ b/nuxt/lib/docs-page-title.test.mjs
@@ -0,0 +1,37 @@
+import { test } from 'node:test'
+import assert from 'node:assert/strict'
+
+import { docsPageTitle } from './docs-page-title.mjs'
+
+test('metaTitle wins, because navTitle is only the sidebar label', () => {
+ // The defect this pins: with navTitle first, every migrated library page's title
+ // collapsed to its nav label and "Using MySQL with Node-RED (2026 Updated)" shipped
+ // as "MySQL". Nothing failed; the pages just had the wrong title.
+ assert.equal(
+ docsPageTitle({
+ metaTitle: 'Using MySQL with Node-RED (2026 Updated)',
+ navTitle: 'MySQL',
+ title: 'Using MySQL with Node-RED (2026 Updated)',
+ }),
+ 'Using MySQL with Node-RED (2026 Updated)'
+ )
+})
+
+test('a page from FlowFuse/flowfuse still titles by its nav label', () => {
+ // Nothing in that repo sets metaTitle, so adding the field must not move their titles.
+ assert.equal(docsPageTitle({ navTitle: 'Getting Started', title: 'Getting Started' }), 'Getting Started')
+})
+
+test('title carries the page when there is no nav label', () => {
+ assert.equal(docsPageTitle({ title: 'Concepts' }), 'Concepts')
+})
+
+test('the last path segment is the last resort, then a generic name', () => {
+ assert.equal(docsPageTitle(null, ['user', 'concepts']), 'concepts')
+ assert.equal(docsPageTitle(null, []), 'Documentation')
+ assert.equal(docsPageTitle(undefined), 'Documentation')
+})
+
+test('an empty string is skipped rather than winning', () => {
+ assert.equal(docsPageTitle({ metaTitle: '', navTitle: 'MySQL' }), 'MySQL')
+})
diff --git a/nuxt/lib/guides-frontmatter.mjs b/nuxt/lib/guides-frontmatter.mjs
new file mode 100644
index 0000000000..66f2a2fea2
--- /dev/null
+++ b/nuxt/lib/guides-frontmatter.mjs
@@ -0,0 +1,106 @@
+// Frontmatter checks over the guides tree, for the two ways a page's titles go wrong
+// silently. Both of these shipped in the Node-RED library migration and neither produced
+// a build error, a broken link or a failing test - the only symptom was the rendered page
+// being wrong, which is why they are asserted here rather than left to review.
+//
+// Test-only, so unlike guides-sync.mjs this may depend on node_modules.
+
+import { join } from 'node:path'
+
+import { listGuideFiles } from './guides-sync.mjs'
+import { readFrontmatter } from './meta-title-length.mjs'
+
+/** Every markdown page under the guides tree, with its parsed frontmatter. */
+export function readGuidePages (guidesDir) {
+ return listGuideFiles(guidesDir)
+ .filter(relPath => relPath.endsWith('.md'))
+ .map(relPath => ({ relPath, frontmatter: readFrontmatter(join(guidesDir, relPath)) || {} }))
+}
+
+// A directory index, under either name. A guide's section index is a README.md in the
+// authored tree and an index.md in the content tree, and where that rename happens has
+// already moved once, so both spellings have to count. Recognising only one leaves every
+// nested index alone in its own bucket, and the duplicate-label check below then passes
+// for the wrong reason instead of failing.
+const INDEX_NAMES = new Set(['README.md', 'index.md'])
+
+/**
+ * The nav node a page labels: an index titles the directory it sits in, any other page
+ * titles itself. `node-red/getting-started/README.md` and `node-red/getting-started.md`
+ * would both label `node-red/getting-started`.
+ */
+function navNodeFor (relPath) {
+ const segments = relPath.split('/')
+ if (INDEX_NAMES.has(segments.at(-1))) return segments.slice(0, -1).join('/')
+ return [...segments.slice(0, -1), segments.at(-1).replace(/\.md$/, '')].join('/')
+}
+
+/**
+ * Groups of nav entries a reader cannot tell apart, because they share both a label and a
+ * position in the sidebar.
+ *
+ * The sidebar nests by directory and labels each entry with `navTitle`, so a label is only
+ * useful if it is unique among the entries it appears next to: its siblings, and the
+ * parent it is indented under. nuxt/lib/docs-nav.mjs cannot catch this, because as far as
+ * it is concerned the titles it was handed are the titles.
+ *
+ * The migration hit this by giving every nested directory index the nav key of its
+ * *parent* Eleventy nav entry instead of its own, so getting-started/{editor,library,
+ * programming}/README.md all came out as "Getting started" nested underneath a "Getting
+ * started" that was already there.
+ */
+export function findDuplicateSiblingNavTitles (guidesDir) {
+ const labelled = readGuidePages(guidesDir)
+ .filter(({ frontmatter }) => typeof frontmatter.navTitle === 'string')
+ .map(({ relPath, frontmatter }) => ({
+ relPath,
+ node: navNodeFor(relPath),
+ navTitle: frontmatter.navTitle,
+ }))
+
+ const fileFor = new Map(labelled.map(p => [p.node, p.relPath]))
+ const labelFor = new Map(labelled.map(p => [p.node, p.navTitle]))
+ const groups = new Map()
+
+ for (const { relPath, node, navTitle } of labelled) {
+ const parent = node.split('/').slice(0, -1).join('/')
+ const key = `${parent} ${navTitle}`
+
+ if (!groups.has(key)) groups.set(key, { under: parent || '.', navTitle, files: new Set() })
+ groups.get(key).files.add(relPath)
+
+ // A parent indented directly above its children is as ambiguous as two siblings,
+ // and it is the shape the screenshot on #5750 showed.
+ if (labelFor.get(parent) === navTitle) groups.get(key).files.add(fileFor.get(parent))
+ }
+
+ return [...groups.values()]
+ .filter(group => group.files.size > 1)
+ .map(({ under, navTitle, files }) => ({ under, navTitle, files: [...files].sort() }))
+}
+
+/**
+ * Pages whose full title can never reach a browser tab or a search result.
+ *
+ * nuxt/pages/docs/[...slug].vue titles a page `metaTitle || navTitle || title`. `navTitle`
+ * is deliberately short, because it has to fit the sidebar column, so a page that gives
+ * `title` the whole phrase and `navTitle` an abbreviation of it needs `metaTitle` to say
+ * which one Google gets. Without it the abbreviation wins and the phrase is only ever
+ * visible as the on-page heading.
+ *
+ * This is how 121 moved library pages lost their titles: "Using MySQL with Node-RED (2026
+ * Updated)" became "MySQL", with nothing anywhere reporting a problem.
+ */
+export function findPagesWithUnreachableTitle (guidesDir) {
+ return readGuidePages(guidesDir)
+ .filter(({ frontmatter: fm }) =>
+ typeof fm.title === 'string' &&
+ typeof fm.navTitle === 'string' &&
+ fm.navTitle !== fm.title &&
+ typeof fm.metaTitle !== 'string')
+ .map(({ relPath, frontmatter }) => ({
+ file: relPath,
+ title: frontmatter.title,
+ navTitle: frontmatter.navTitle,
+ }))
+}
diff --git a/nuxt/lib/guides-frontmatter.test.mjs b/nuxt/lib/guides-frontmatter.test.mjs
new file mode 100644
index 0000000000..0ae0ca2b5a
--- /dev/null
+++ b/nuxt/lib/guides-frontmatter.test.mjs
@@ -0,0 +1,127 @@
+import { test } from 'node:test'
+import assert from 'node:assert/strict'
+import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
+import { tmpdir } from 'node:os'
+import { dirname, join } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+import { findDuplicateSiblingNavTitles, findPagesWithUnreachableTitle } from './guides-frontmatter.mjs'
+import { GUIDES_SOURCE } from './guides-sync.mjs'
+import { isDirectory } from './meta-title-length.mjs'
+
+const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../..')
+const guidesDir = join(repoRoot, GUIDES_SOURCE)
+
+function scratch (files) {
+ const root = mkdtempSync(join(tmpdir(), 'guides-frontmatter-'))
+ for (const [relPath, content] of Object.entries(files)) {
+ const path = join(root, relPath)
+ mkdirSync(dirname(path), { recursive: true })
+ writeFileSync(path, content, 'utf8')
+ }
+ return root
+}
+
+function page (fm) {
+ const lines = Object.entries(fm).map(([k, v]) => `${k}: "${v}"`)
+ return `---\n${lines.join('\n')}\n---\n\n# Heading\n`
+}
+
+// Guards the real-tree tests below against a silent no-op if the source layout moves.
+test('the guides tree exists where these tests expect it', () => {
+ assert.ok(isDirectory(guidesDir), `expected ${guidesDir} to exist`)
+})
+
+test('every sidebar entry is distinguishable from the ones beside it', () => {
+ const duplicates = findDuplicateSiblingNavTitles(guidesDir)
+ assert.deepEqual(duplicates, [], duplicates
+ .map(d => `under ${d.under}/: ${d.files.length} nav entries all labelled "${d.navTitle}" (${d.files.join(', ')})`)
+ .join('\n'))
+})
+
+test('every page whose title is longer than its nav label says which one Google gets', () => {
+ const unreachable = findPagesWithUnreachableTitle(guidesDir)
+ assert.deepEqual(unreachable, [], unreachable
+ .map(p => `${p.file}: title "${p.title}" can never render, navTitle "${p.navTitle}" wins; set metaTitle`)
+ .join('\n'))
+})
+
+test('a directory index competes with its parent\'s children, not with its own', () => {
+ // The exact shape the migration got wrong: three nested indexes carrying the nav label
+ // of the section they sit under, which is already used by that section's own index.
+ const root = scratch({
+ 'node-red/README.md': page({ navTitle: 'Using Node-RED' }),
+ 'node-red/getting-started/README.md': page({ navTitle: 'Getting started' }),
+ 'node-red/getting-started/editor/README.md': page({ navTitle: 'Getting started' }),
+ 'node-red/getting-started/library/README.md': page({ navTitle: 'Getting started' }),
+ })
+
+ try {
+ const [group, ...rest] = findDuplicateSiblingNavTitles(root)
+ assert.deepEqual(rest, [])
+ assert.equal(group.navTitle, 'Getting started')
+ // The section's own index is named alongside its children: the reader sees one
+ // "Getting started" indented under another, which is what the reviewer screenshotted.
+ assert.deepEqual(group.files, [
+ 'node-red/getting-started/README.md',
+ 'node-red/getting-started/editor/README.md',
+ 'node-red/getting-started/library/README.md',
+ ].sort())
+ } finally {
+ rmSync(root, { recursive: true, force: true })
+ }
+})
+
+test('a directory index is recognised under either name, so the rename cannot blind this', () => {
+ // #5752 renames every guide README.md to index.md. Keying only off README.md put each
+ // nested index in a bucket of its own, and this check went green with the duplicate
+ // labels still in place.
+ for (const indexName of ['README.md', 'index.md']) {
+ const root = scratch({
+ [`node-red/getting-started/${indexName}`]: page({ navTitle: 'Getting started' }),
+ [`node-red/getting-started/editor/${indexName}`]: page({ navTitle: 'Getting started' }),
+ })
+
+ try {
+ const [group, ...rest] = findDuplicateSiblingNavTitles(root)
+ assert.deepEqual(rest, [], `${indexName}: expected exactly one clash`)
+ assert.deepEqual(group.files, [
+ `node-red/getting-started/${indexName}`,
+ `node-red/getting-started/editor/${indexName}`,
+ ].sort())
+ } finally {
+ rmSync(root, { recursive: true, force: true })
+ }
+ }
+})
+
+test('the same nav label in two different sections is fine', () => {
+ const root = scratch({
+ 'application-guide/worked-examples/README.md': page({ navTitle: 'Worked examples' }),
+ 'node-red-guide/worked-examples/README.md': page({ navTitle: 'Worked examples' }),
+ })
+
+ try {
+ assert.deepEqual(findDuplicateSiblingNavTitles(root), [])
+ } finally {
+ rmSync(root, { recursive: true, force: true })
+ }
+})
+
+test('a short nav label beside a long title needs a metaTitle, an identical one does not', () => {
+ const root = scratch({
+ 'node-red/database/mysql.md': page({ title: 'Using MySQL with Node-RED (2026 Updated)', navTitle: 'MySQL' }),
+ 'node-red/database/redis.md': page({ title: 'Using Redis with Node-RED', navTitle: 'Redis', metaTitle: 'Using Redis with Node-RED' }),
+ 'application-guide/data-plane.md': page({ title: 'Data plane', navTitle: 'Data plane' }),
+ })
+
+ try {
+ assert.deepEqual(findPagesWithUnreachableTitle(root), [{
+ file: 'node-red/database/mysql.md',
+ title: 'Using MySQL with Node-RED (2026 Updated)',
+ navTitle: 'MySQL',
+ }])
+ } finally {
+ rmSync(root, { recursive: true, force: true })
+ }
+})
diff --git a/nuxt/lib/guides-sync.mjs b/nuxt/lib/guides-sync.mjs
index 012476681e..be5faeab5e 100644
--- a/nuxt/lib/guides-sync.mjs
+++ b/nuxt/lib/guides-sync.mjs
@@ -58,7 +58,14 @@ export function destinationFor (relPath, contentDocsDir, publicDocsDir) {
* repo's history rather than flowfuse's.
*/
export function injectFrontmatter (content, { editUrl, updated }) {
- const injected = `editUrl: ${editUrl}\nupdated: ${updated}\n`
+ // `updated` is omitted rather than emitted empty when git could not answer. YAML reads
+ // a valueless key as null, which the collection schema (`z.string().optional()`)
+ // accepts as absent but not as null, so an empty value turns a missing timestamp into
+ // a parse complaint on every guide page at once.
+ const injected = [
+ `editUrl: ${editUrl}`,
+ updated ? `updated: ${updated}` : null,
+ ].filter(Boolean).join('\n') + '\n'
return /^---/.test(content)
? content.replace(/^---\n/, `---\n${injected}`)
diff --git a/nuxt/lib/guides-sync.test.mjs b/nuxt/lib/guides-sync.test.mjs
index 88c006f307..b3971b90a1 100644
--- a/nuxt/lib/guides-sync.test.mjs
+++ b/nuxt/lib/guides-sync.test.mjs
@@ -30,6 +30,19 @@ function write (path, content) {
writeFileSync(path, content, 'utf8')
}
+test('a timestamp git could not supply is left out, not emitted empty', () => {
+ // `updated:` with no value is YAML null. The collection schema takes the key as
+ // optional but not nullable, so an empty value turns "git was unavailable" into a
+ // parse complaint on every guide page at once. Reachable whenever .git is absent or
+ // the commit touching the file falls outside a shallow fetch.
+ const withTimestamp = injectFrontmatter('---\ntitle: T\n---\n', { editUrl: 'u', updated: '2026-09-08' })
+ assert.match(withTimestamp, /^---\neditUrl: u\nupdated: 2026-09-08\ntitle: T\n/)
+
+ const without = injectFrontmatter('---\ntitle: T\n---\n', { editUrl: 'u', updated: '' })
+ assert.match(without, /^---\neditUrl: u\ntitle: T\n/)
+ assert.ok(!/updated:/.test(without), 'an empty timestamp must not leave a valueless key')
+})
+
test('a README becomes its section index, so a directory of guides nests like a directory of docs', () => {
assert.equal(
destinationFor('application-guide/README.md', '/content/docs', '/public/docs'),
diff --git a/nuxt/lib/mdc-bindings.mjs b/nuxt/lib/mdc-bindings.mjs
new file mode 100644
index 0000000000..01cb08e78e
--- /dev/null
+++ b/nuxt/lib/mdc-bindings.mjs
@@ -0,0 +1,107 @@
+// Finding markdown that MDC will read as a Vue binding rather than as text.
+//
+// @nuxt/content compiles a content file with MDC, and MDC treats `{{ ... }}` in prose the
+// way a Vue template does: it becomes a binding node against a scope that holds the page,
+// not the words that were typed. Nothing errors. `{{ msg.payload }}` in a paragraph simply
+// renders as nothing, and a page can lose a sentence with no sign anywhere that it did.
+//
+// The Node-RED pages are full of mustache examples - it is the Template node's own
+// templating syntax - so this is not a theoretical risk on this tree.
+//
+// The scan is deliberately over-broad: it reports every `{{` that is not inside code,
+// whether or not a `}}` closes it, because the failure modes are not all the same shape.
+//
+// `{{ msg.payload }}` one line, closed -> binds, renders empty
+// `{{{triple}}}` triple brace -> binds (value `{triple`), renders empty
+// `{{` .. newline .. `}}` spanning lines -> crashes the markdown parser outright
+// `{{` with no `}}` unclosed -> crashes the markdown parser outright
+//
+// A scan that only looked for a closed, single-line pair would miss the last two, which are
+// the ones that break a build rather than quietly emptying a sentence, and would miss the
+// triple-brace form too (the inner `{` is not what a `[^{}]*` body matches).
+//
+// Where a mustache is safe, and why this scan skips exactly those places:
+//
+// fenced code blocks, indented code blocks, inline code spans
+// MDC leaves the text alone. This is how every Node-RED page shows mustache syntax,
+// and it is the fix for anything this scan reports.
+//
+// Block-level raw HTML is NOT skipped. MDC does leave `{{ }}` alone inside a raw HTML
+// *block*, but not inside *inline* HTML: `{{ msg.payload }}` in a paragraph
+// binds exactly like bare prose does. Telling those two apart needs the parser, so this
+// reports both and the writer moves the example into a code span.
+
+/** Strips fenced code blocks, leaving line count intact so reported lines stay right. */
+function blankFencedBlocks (lines) {
+ const out = [...lines]
+ let fence = null
+ for (let i = 0; i < out.length; i++) {
+ const opening = out[i].match(/^\s{0,3}(`{3,}|~{3,})/)
+ if (!fence && opening) {
+ fence = opening[1][0].repeat(opening[1].length)
+ out[i] = ''
+ continue
+ }
+ if (fence) {
+ const closing = out[i].match(/^\s{0,3}(`{3,}|~{3,})\s*$/)
+ out[i] = ''
+ if (closing && closing[1][0] === fence[0] && closing[1].length >= fence.length) fence = null
+ }
+ }
+ return out
+}
+
+/** Strips inline code spans and indented code blocks from one line. */
+function blankCode (line) {
+ if (/^(\s{4,}|\t)/.test(line)) return ''
+ return line.replace(/(`+)(?:(?!\1)[\s\S])*?\1/g, '')
+}
+
+/**
+ * Every place in `markdown` where MDC could read a mustache as a binding.
+ *
+ * Returns `{ line, text }` per hit, one-based lines, so a failure message can point at the
+ * file and line rather than just naming the file.
+ */
+export function bindableMustaches (markdown) {
+ const lines = blankFencedBlocks(String(markdown).split('\n'))
+ const hits = []
+ lines.forEach((line, i) => {
+ if (blankCode(line).includes('{{')) hits.push({ line: i + 1, text: line.trim() })
+ })
+ return hits
+}
+
+/**
+ * MDC component blocks that are opened and never closed.
+ *
+ * `::component{...}` opens a container, and its closing `::` is not optional: without it
+ * the container swallows the rest of the file, so every heading after it stops being a
+ * heading. Nothing errors and the component still renders, which is why this is worth a
+ * check. It shipped once: three guides had a raw `` CTA replaced with
+ * `::cta-image{...}` and no closing `::`, and the only symptom was 23 anchors in those
+ * pages' own tables of contents pointing at headings that no longer existed.
+ *
+ * Counts openers against closers rather than parsing: a `::` on its own line closes the
+ * innermost open block, so the two must balance over a file.
+ *
+ * @param {string} markdown
+ * @returns {Array<{line: number, component: string}>} unclosed openers, outermost first
+ */
+export function unclosedMdcBlocks (markdown) {
+ const lines = blankFencedBlocks(String(markdown).split('\n'))
+ const open = []
+
+ lines.forEach((line, index) => {
+ // An opener names a component; a bare `::` closes one. A single-colon
+ // `:component{...}` is the inline form and needs no close.
+ const opener = line.match(/^\s*::([a-z][a-z0-9-]*)/i)
+ if (opener) {
+ open.push({ line: index + 1, component: opener[1] })
+ return
+ }
+ if (/^\s*::\s*$/.test(line)) open.pop()
+ })
+
+ return open
+}
diff --git a/nuxt/lib/mdc-bindings.test.mjs b/nuxt/lib/mdc-bindings.test.mjs
new file mode 100644
index 0000000000..4492d40a77
--- /dev/null
+++ b/nuxt/lib/mdc-bindings.test.mjs
@@ -0,0 +1,126 @@
+import { test } from 'node:test'
+import assert from 'node:assert/strict'
+import { readFileSync } from 'node:fs'
+import { dirname, join, relative } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+import { findFiles } from './find-files.mjs'
+import { GUIDES_SOURCE } from './guides-sync.mjs'
+import { isDirectory } from './meta-title-length.mjs'
+import { bindableMustaches, unclosedMdcBlocks } from './mdc-bindings.mjs'
+
+const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '../..')
+
+// The trees this repository owns and always has in a checkout. FlowFuse/flowfuse's own
+// docs go through the same MDC pipeline and the same function checks them, but they are
+// only on disk after a docs sync (nuxt/content/docs is build-generated and gitignored), and
+// whether that has run by the time `npm test` does is decided in another repository's
+// workflow - so requiring them here would make this test's coverage depend on something
+// this repository cannot see. They are scanned below if they happen to be present.
+const REQUIRED_TREES = [GUIDES_SOURCE, 'nuxt/content/handbook']
+const OPTIONAL_TREES = ['nuxt/content/docs']
+
+test('a mustache in prose is reported', () => {
+ // MDC compiles `{{ ... }}` in prose into a Vue binding against the page scope, so the
+ // text renders as nothing at all. Confirmed against this branch's dev server: the
+ // parsed AST holds `{ type: 'element', tag: 'binding', props: { value: 'msg.payload' } }`
+ // and the served HTML has an empty gap where the words were.
+ assert.deepEqual(bindableMustaches('P {{ msg.payload }} Q'), [{ line: 1, text: 'P {{ msg.payload }} Q' }])
+ assert.equal(bindableMustaches('tight {{payload.name}} here').length, 1)
+})
+
+test('a triple-brace mustache is reported, which a {{ ... }} pattern misses', () => {
+ // `{{{triple}}}` binds too - MDC reads it as the expression `{triple` - but a pattern
+ // whose body is `[^{}]*` cannot match it, because the body starts with a brace. This is
+ // the Template node's own escape hatch for unescaped substitution, so it appears in
+ // exactly the prose most at risk of carrying it.
+ assert.equal(bindableMustaches('P {{{triple}}} Q').length, 1)
+})
+
+test('a mustache spanning two lines is reported, and it does not merely render empty', () => {
+ // A `{{` with its `}}` on a later line, and a `{{` with no `}}` at all, both crash the
+ // markdown parser outright rather than binding: micromark throws
+ // "Cannot access index N in a splice buffer of size N". So the shapes a single-line,
+ // must-be-closed pattern misses are the ones that break a build, not just a sentence.
+ assert.deepEqual(bindableMustaches('P {{\nmsg.payload\n}} Q').map(h => h.line), [1])
+ assert.deepEqual(bindableMustaches('P {{ msg.payload with no close').map(h => h.line), [1])
+})
+
+test('a mustache inside code is not reported, because that is the fix', () => {
+ // Inline code spans, fenced blocks and indented blocks all reach the page as typed.
+ // Every Node-RED page that shows mustache syntax does it this way.
+ assert.deepEqual(bindableMustaches('P `{{ msg.payload }}` Q'), [])
+ assert.deepEqual(bindableMustaches('```\n{{ msg.payload }}\n```'), [])
+ assert.deepEqual(bindableMustaches('```json\n{"a": "{{ b }}"}\n```'), [])
+ assert.deepEqual(bindableMustaches('~~~\n{{ msg.payload }}\n~~~'), [])
+ assert.deepEqual(bindableMustaches(' {{ msg.payload }}'), [])
+ // A fence inside an MDC component block still counts as a fence.
+ assert.deepEqual(bindableMustaches('::render-flow\n```json\n{{ x }}\n```\n::'), [])
+})
+
+test('a mustache in inline HTML is reported, unlike one in an HTML block', () => {
+ // MDC leaves `{{ }}` alone inside a raw HTML *block* but binds it inside *inline* HTML:
+ // `{{ msg.payload }}` in a paragraph binds exactly like bare prose. Both
+ // are reported, deliberately - telling them apart needs the parser, and the fix for
+ // either is the same.
+ assert.equal(bindableMustaches('P {{ msg.payload }} Q').length, 1)
+ assert.equal(bindableMustaches('
'), //)
+
+ const link = sanitiseHelp('mustache')
+ assert.match(link, /target="_blank"/)
+ // `rel` has to be in the allowlist as well as produced by the transform: sanitize-html
+ // filters the transform's output afterwards, so an attribute added there and missing
+ // here is added and then dropped again, with nothing said.
+ assert.match(link, /rel="noreferrer noopener"/)
+})
+
+test('the sanitiser still drops what can execute', () => {
+ assert.doesNotMatch(sanitiseHelp('
'), /alert/)
+ assert.doesNotMatch(sanitiseHelp('x'), /javascript:/)
+ // Deliberately not allowed, even though upstream has one (malformed) use of it on the
+ // Range node's table: no text depends on it, and it is third-party CSS.
+ assert.doesNotMatch(sanitiseHelp('
'), /style=/)
+})
diff --git a/nuxt/lib/redirects-node-red.test.mjs b/nuxt/lib/redirects-node-red.test.mjs
new file mode 100644
index 0000000000..3ab42580e5
--- /dev/null
+++ b/nuxt/lib/redirects-node-red.test.mjs
@@ -0,0 +1,112 @@
+// The /node-red/** -> /docs/** map is 126 hand-written lines whose correctness nothing
+// else checks. Every entry is a promise that an indexed URL still lands somewhere, and
+// every way of breaking one is silent: a 301 into a 404 is a normal-looking response, and
+// the build has no idea a redirect target does not exist.
+//
+// The core-node half maps an old flat URL onto a page that now sits under its palette
+// category, so it goes stale the moment a page moves between categories: the map keeps
+// pointing at the old path and nothing fails.
+
+import { test } from 'node:test'
+import assert from 'node:assert/strict'
+import { readFileSync } from 'node:fs'
+import { dirname, join } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+import { GUIDES_SOURCE, listGuideFiles } from './guides-sync.mjs'
+
+const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../..')
+const read = rel => readFileSync(join(repoRoot, rel), 'utf8')
+
+const withSlashes = path => '/' + path.split('/').filter(Boolean).join('/') + '/'
+
+/** The `from: to` pairs out of nuxt/redirects-node-red.ts. */
+function nodeRedRedirects () {
+ return Object.fromEntries(
+ [...read('nuxt/redirects-node-red.ts').matchAll(/'(\/[^']+)':\s*'(\/[^']+)'/g)]
+ .map(([, from, to]) => [from, to])
+ )
+}
+
+/** The `from` keys of the site-wide map, which the node-red targets must not land on. */
+function siteRedirectSources () {
+ return [...read('nuxt/redirects.ts').matchAll(/'(\/[^']+)':\s*\{\s*redirect:/g)].map(([, from]) => from)
+}
+
+/** Every /docs/ URL the authored guides produce. */
+function docsUrlsThatWillExist () {
+ const urls = new Set()
+
+ for (const relPath of listGuideFiles(join(repoRoot, GUIDES_SOURCE))) {
+ if (!relPath.endsWith('.md')) continue
+ urls.add(withSlashes('/docs/' + relPath.replace(/(README|index)?\.md$/, '')))
+ }
+
+ return urls
+}
+
+/** slug -> category, read off the core-node pages themselves. */
+function coreNodeCategories () {
+ const prefix = 'node-red/core-nodes/'
+ const bySlug = new Map()
+
+ for (const relPath of listGuideFiles(join(repoRoot, GUIDES_SOURCE))) {
+ if (!relPath.startsWith(prefix) || !relPath.endsWith('.md')) continue
+ const rest = relPath.slice(prefix.length)
+ const [category, file] = rest.split('/')
+ if (!file || file === 'index.md') continue
+ bySlug.set(file.replace(/\.md$/, ''), category)
+ }
+
+ return bySlug
+}
+
+test('every redirect lands on a page that will exist', () => {
+ const existing = docsUrlsThatWillExist()
+ // Pages from FlowFuse/flowfuse are not on disk at test time, so only this repo's own
+ // prefixes can be checked. Those are the ones this map actually moves.
+ const ours = /^\/docs\/(node-red|flowfuse-nodes|application-guide|node-red-guide)\//
+
+ const dangling = Object.entries(nodeRedRedirects())
+ .filter(([, to]) => ours.test(to) && !existing.has(to))
+ .map(([from, to]) => `${from} -> ${to}`)
+
+ assert.deepEqual(dangling, [], dangling.join('\n'))
+})
+
+test('no redirect target is itself a redirect source', () => {
+ const map = nodeRedRedirects()
+ const sources = new Set([...Object.keys(map), ...siteRedirectSources()])
+
+ const hops = Object.entries(map)
+ .filter(([, to]) => sources.has(to))
+ .map(([from, to]) => `${from} -> ${to} -> (redirects again)`)
+
+ assert.deepEqual(hops, [], hops.join('\n'))
+})
+
+test('the core-node entries point at where the pages actually are', () => {
+ // The one half of the map that is a function of something else: a node page's URL is
+ // its category directory plus its filename, so moving a page between categories
+ // strands the redirect on a path nothing serves.
+ const categories = coreNodeCategories()
+ const expected = { '/node-red/core-nodes/': '/docs/node-red/core-nodes/' }
+
+ for (const [slug, category] of categories) {
+ expected[`/node-red/core-nodes/${slug}/`] = `/docs/node-red/core-nodes/${category}/${slug}/`
+ }
+
+ // A bare category path was never a page under Eleventy, but it is one now, so it is
+ // mapped too - except where a node already owns that URL. /node-red/core-nodes/function/
+ // was the Function NODE's own URL and keeps pointing at the node, one level down.
+ for (const category of new Set(categories.values())) {
+ if (categories.has(category)) continue
+ expected[`/node-red/core-nodes/${category}/`] = `/docs/node-red/core-nodes/${category}/`
+ }
+
+ const actual = Object.fromEntries(
+ Object.entries(nodeRedRedirects()).filter(([from]) => from.startsWith('/node-red/core-nodes/'))
+ )
+
+ assert.deepEqual(actual, expected)
+})
diff --git a/nuxt/modules/docs-source.ts b/nuxt/modules/docs-source.ts
index c70e2b82df..6dc322d003 100644
--- a/nuxt/modules/docs-source.ts
+++ b/nuxt/modules/docs-source.ts
@@ -8,6 +8,7 @@ import { join, basename, dirname } from 'node:path'
import { syncDocs } from '../lib/docs-sync.mjs'
// @ts-ignore same
import { syncGuides } from '../lib/guides-sync.mjs'
+// @ts-ignore same
const logger = useLogger('docs-source')
@@ -33,8 +34,8 @@ export default defineNuxtModule({
const repoRoot = dirname(nuxtRoot)
- // Order matters: syncDocs wipes content/docs before writing, so the guides
- // authored in this repo have to be overlaid after it, not before.
+ // Order matters: syncDocs wipes content/docs before writing, so the guides overlaid
+ // from this repo have to land after it, not before.
await syncDocs({ repoRoot, nuxtRoot, logger })
syncGuides({ repoRoot, nuxtRoot, logger })
@@ -43,6 +44,15 @@ export default defineNuxtModule({
// Collected after the overlay, so the guide pages get prerendered with the rest
// of /docs and need no route list of their own in nuxt.config.
const docsRoutes = collectRoutes(contentDocsDir, '/docs')
+ // A floor rather than a log line, following the same call in nuxt.config.ts for the
+ // integrations. Collecting nothing means the tree above did not land, and on the
+ // netlify preset unprerendered routes still SSR, so the only symptom would be a
+ // thinner static site and slow cold pages - nothing that looks like a failure.
+ if (docsRoutes.length === 0) {
+ throw new Error(
+ '[docs-source] collected 0 docs routes to prerender - refusing to build /docs with no pages'
+ )
+ }
nuxt.options.nitro.prerender ??= {}
const existing = (nuxt.options.nitro.prerender.routes as string[] | undefined) ?? []
nuxt.options.nitro.prerender.routes = [...existing, ...docsRoutes]
diff --git a/nuxt/pages/ai/index.vue b/nuxt/pages/ai/index.vue
index ef64f8d9c2..d669c09e2f 100644
--- a/nuxt/pages/ai/index.vue
+++ b/nuxt/pages/ai/index.vue
@@ -98,8 +98,8 @@ const CAPABILITY_GROUPS = [
items: [
{ name: 'Governed autonomous operations', diagram: 'governed-operations', externalNote: 'For external agents, approval cards do not apply. The access you granted is the control, enforced on every call.', description: 'Platform Automations let AI act on live systems, with every write behind an approval card, session-scoped and fully audited. A person approves, edits or rejects each proposed change before it reaches a machine. Nothing runs outside the permissions and RBAC that already govern your teams.' },
{ name: 'Ask your plant anything', diagram: 'ask-your-plant', externalNote: 'For external agents, whether they can reach the MCP servers you build in your own flows depends on the agent.', description: 'In Insights mode, ask questions in natural language and get answers grounded in live machine state, alarms and logs. Operators and engineers can check what is happening on the floor without building a report or querying a database by hand. Table and MQTT-broker reading are coming soon.' },
- { name: 'Automated visual inspection', diagram: 'visual-inspection', description: `Run ONNX vision models inside flows next to the machine, with camera ingest over RTSP, for inference that works offline and keeps data on your network. Detection results flow into the same logic as any other signal, so you can trigger alerts or actions from what the model sees. Running at the edge means no round trip to the cloud and no image data leaving the plant.` },
- { name: 'Use any model within flows', diagram: 'any-model', description: `Certified LLM nodes bring OpenAI, Anthropic, Gemini or local models via Ollama into any flow with your own keys. Choose the provider that fits each task, or keep everything on local models when data cannot leave your network. Because you supply the keys, model access and spend stay under your control.` },
+ { name: 'Automated visual inspection', diagram: 'visual-inspection', description: `Run ONNX vision models inside flows next to the machine, with camera ingest over RTSP, for inference that works offline and keeps data on your network. Detection results flow into the same logic as any other signal, so you can trigger alerts or actions from what the model sees. Running at the edge means no round trip to the cloud and no image data leaving the plant.` },
+ { name: 'Use any model within flows', diagram: 'any-model', description: `Certified LLM nodes bring OpenAI, Anthropic, Gemini or local models via Ollama into any flow with your own keys. Choose the provider that fits each task, or keep everything on local models when data cannot leave your network. Because you supply the keys, model access and spend stay under your control.` },
],
},
{
@@ -118,7 +118,7 @@ const CAPABILITY_GROUPS = [
eyebrow: 'Expose',
subtitle: 'The other direction. Your flows become tools that an agent can call as part of its work.',
items: [
- { name: 'AI that uses your tools', diagram: 'your-tools', externalNote: 'Anyone can build them. For external agents, whether they can call them depends on the agent.', description: `Build your own MCP servers and let Insights-mode agents call your tools and services as part of a workflow. Wrap an internal API or system as a tool once, then let agents use it wherever it fits. The agent stays inside the workflow you designed, calling only the tools you register.` },
+ { name: 'AI that uses your tools', diagram: 'your-tools', externalNote: 'Anyone can build them. For external agents, whether they can call them depends on the agent.', description: `Build your own MCP servers and let Insights-mode agents call your tools and services as part of a workflow. Wrap an internal API or system as a tool once, then let agents use it wherever it fits. The agent stays inside the workflow you designed, calling only the tools you register.` },
],
},
]
diff --git a/nuxt/pages/docs/[...slug].vue b/nuxt/pages/docs/[...slug].vue
index a7bb180beb..18f13a2747 100644
--- a/nuxt/pages/docs/[...slug].vue
+++ b/nuxt/pages/docs/[...slug].vue
@@ -1,5 +1,6 @@
\ No newline at end of file
diff --git a/src/_includes/layouts/learning-resources-nav.njk b/src/_includes/layouts/learning-resources-nav.njk
deleted file mode 100644
index a0ffac394d..0000000000
--- a/src/_includes/layouts/learning-resources-nav.njk
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
- {% set navPages = collections.learningResources | eleventyNavigation %}
- {% macro renderNavListItem(entry) -%}
- {% set isChildUrl = false %}
- {% for child in entry.children %}
- {% if child.url == page.url %}
- {% set isChildUrl = true %}
- {% endif %}
- {% endfor %}
-
-
- {%- if entry.children.length -%}
-
- {{ entry.title }}
- {% include "components/icons/chevron-down.svg" %}
-
-
- {%- for child in entry.children %}
- {{ renderNavListItem(child) }}
- {%- endfor -%}
-
\ No newline at end of file
diff --git a/src/blog/2023/06/community-news-06.md b/src/blog/2023/06/community-news-06.md
index 0a3a1c47ed..a5bdaee0c3 100644
--- a/src/blog/2023/06/community-news-06.md
+++ b/src/blog/2023/06/community-news-06.md
@@ -37,7 +37,7 @@ On June 27, FlowFuse is doing a webinar with our friends at InfluxDB. A great op
- [Bringing High Availability to Node-RED](/blog/2023/05/bringing-high-availability-to-node-red/) - FlowFuse CTO discusses the strategy for delivering high availability in the FlowFuse platform.
- Two articles featuring how to connect Modbus data with Node-RED:
- - [Using Node-RED to Visualize Industrial Production Data via Modbus](/node-red/protocol/modbus/)
+ - [Using Node-RED to Visualize Industrial Production Data via Modbus](/docs/node-red/protocol/modbus/)
- [Best Practices Integrating a Modbus Device With Node-RED](/blog/2023/05/integrating modbus with node-red/)
- [Node-RED Tips - Dashboard Edition](/blog/2023/06/3-quick-node-red-tips-7/) - A new set of Node-RED quick tips that are focused on using Node-RED Dashboard.
diff --git a/src/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter.md b/src/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter.md
index 9749dbe1f3..45ad0ca59f 100644
--- a/src/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter.md
+++ b/src/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter.md
@@ -197,7 +197,7 @@ Depending on how noisy the REAL data is, which is common with unfiltered 4-20mA

-In the example above, we arbitrarily applied a 3% [deadband](/node-red/core-nodes/filter/)
+In the example above, we arbitrarily applied a 3% [deadband](/docs/node-red/core-nodes/function/filter/)
to the `Robot_Position` value, which means that the value must change by greater than or equal to 3% compared to the last input value, or else the data will be discarded before being sent to the stacklight PLC.
You can adjust the deadband to find the right balance for your particular application.
diff --git a/src/blog/2023/07/community-news-07.md b/src/blog/2023/07/community-news-07.md
index d50bff5d4a..df7c08971f 100644
--- a/src/blog/2023/07/community-news-07.md
+++ b/src/blog/2023/07/community-news-07.md
@@ -35,11 +35,11 @@ Our next webinar will be focused on the device management capabilities in the Fl
- [Node-RED as a No-Code Ethernet/IP to S7 Protocol Converter](/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/) - A guide to using Node-RED for converting ethernet IP data to Siemens S7. Also a [video version](https://youtu.be/dteXgcBXUnk) of the same content.
-- [MQTT and its Role in IoT and Industrial IoT](/node-red/protocol/mqtt/) - A practical explainer on the role of MQTT in IoT use cases and how to connect with an MQTT broker in Node-RED.
+- [MQTT and its Role in IoT and Industrial IoT](/docs/node-red/protocol/mqtt/) - A practical explainer on the role of MQTT in IoT use cases and how to connect with an MQTT broker in Node-RED.
- Two new Node-RED Nodes Explained articles
- - [Nodes explained: Split](/node-red/core-nodes/split/)
- - [Nodes explained: Filter](/node-red/core-nodes/filter/)
+ - [Nodes explained: Split](/docs/node-red/core-nodes/sequence/split/)
+ - [Nodes explained: Filter](/docs/node-red/core-nodes/function/filter/)
## From the Community
diff --git a/src/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red.md b/src/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red.md
index f48fca5552..ed8f90cf8a 100644
--- a/src/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red.md
+++ b/src/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red.md
@@ -67,7 +67,7 @@ meta:
answer: "The complete flow source code for all four objectives, browsing, reading, writing, and events, is included inline within the article, ready to import directly into Node-RED."
tldr: "This part of the OPC UA series shows how to build an interactive Node-RED dashboard that connects to a third-party OPC UA server to browse the address space, read and write values, and display alarms and events. Complete flow source code is provided, making it a practical starting point for production OPC UA client applications."
---
-This article is the third and final part of our OPC UA content series. In the [first article](/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/), we cover some OPC UA fundamentals and walk through an example OPC UA Server flow. In the [second article](/node-red/protocol/opc-ua/), we built a SSL-secured OPC UA server using data from an Allen Bradley PLC as a source.
+This article is the third and final part of our OPC UA content series. In the [first article](/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/), we cover some OPC UA fundamentals and walk through an example OPC UA Server flow. In the [second article](/docs/node-red/protocol/opc-ua/), we built a SSL-secured OPC UA server using data from an Allen Bradley PLC as a source.
In this article, we show how to build an OPC Client in Node-RED that communicates with a 3rd party OPC UA Server and utilizes an interactive dashboard.
@@ -288,7 +288,7 @@ So, you've successfully built your Node-RED application, congratulations! But no
Enter [FlowFuse](/), a cloud-based platform designed to add production-grade features to your Node-RED applications. With FlowFuse, you can seamlessly integrate advanced security measures, scale your application as needed, and collaborate effortlessly with your team. It simplifies management and deployment, turning your Node-RED project into a robust, scalable solution.
-If you're interested in learning how to use Node-RED for professional use cases, check out our eBook: [Ultimate Beginner's Guide to Professionals](/ebooks/beginner-guide-to-a-professional-nodered/). For additional resources, visit our [Node-RED Learning Resources section](/node-red/core-nodes/), where you can explore integrations with different protocols, messaging services, databases, hardware, and much more.
+If you're interested in learning how to use Node-RED for professional use cases, check out our eBook: [Ultimate Beginner's Guide to Professionals](/ebooks/beginner-guide-to-a-professional-nodered/). For additional resources, visit our [Node-RED Learning Resources section](/docs/node-red/core-nodes/), where you can explore integrations with different protocols, messaging services, databases, hardware, and much more.
## Conclusion
diff --git a/src/blog/2023/08/community-news-08.md b/src/blog/2023/08/community-news-08.md
index 726de76302..72866c6051 100644
--- a/src/blog/2023/08/community-news-08.md
+++ b/src/blog/2023/08/community-news-08.md
@@ -31,7 +31,7 @@ OPC-UA is a popular communication protocol used to communicate industrial data b
- Our developer advocate, Richard Meyer, published a series of articles on OPC-UA:
- Part 1: [How to Deploy a Basic OPC-UA Server in Node-RED](/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/)
- - Part 2: [How to Build a Secure OPC-UA Server for PLCs in Node-RED](/node-red/protocol/opc-ua/)
+ - Part 2: [How to Build a Secure OPC-UA Server for PLCs in Node-RED](/docs/node-red/protocol/opc-ua/)
- Part 3: [How to Build an OPC UA Client Dashboard in Node-RED](/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/)
diff --git a/src/blog/2023/10/community-news-10.md b/src/blog/2023/10/community-news-10.md
index d1fad8e9eb..7485b3aeb7 100644
--- a/src/blog/2023/10/community-news-10.md
+++ b/src/blog/2023/10/community-news-10.md
@@ -49,7 +49,7 @@ The next generation of the Node-RED dashboard is starting to mature. Development
* [Share & Preview Flows on flows.nodered.org](/blog/2023/09/flow-viewer/) - A new way to visualize flows in web pages.
-* [Charting REST API Data in a Dashboard](/node-red/integration-technologies/rest/) - A short tutorial on how to gather data from a REST API for a dashboard.
+* [Charting REST API Data in a Dashboard](/docs/node-red/integration-technologies/rest/) - A short tutorial on how to gather data from a REST API for a dashboard.
* Modernize your legacy industrial data - Two part series on making sense of your industrial data.
- [Part 1](/blog/2023/09/modernize-your-legacy-industrial-data/)
diff --git a/src/blog/2023/10/custom-vuetify-components-dashboard.md b/src/blog/2023/10/custom-vuetify-components-dashboard.md
index ba1039f0b0..0b014771d6 100644
--- a/src/blog/2023/10/custom-vuetify-components-dashboard.md
+++ b/src/blog/2023/10/custom-vuetify-components-dashboard.md
@@ -40,7 +40,7 @@ generated for you, in my case it's:
### Using the template node
-Like the [template core node](/node-red/core-nodes/template), the dashboard package
+Like the [template core node](/docs/node-red/core-nodes/function/template/), the dashboard package
comes with [a template node of its own](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html).
If we take the HTML from the Vuetify docs pages and copy it in a template node
the spinner will show up on the dashboard.
@@ -52,7 +52,7 @@ the spinner will show up on the dashboard.
While a custom element on a page is cool, and shows you can inject arbitrary HTML
on a Dashboard, it's even better if we could make the element dynamic. So let's
start with a first dynamic element. The quickest way to get that done is have
-an [`Inject`](/node-red/core-nodes/inject) node output a random number every second.
+an [`Inject`](/docs/node-red/core-nodes/common/inject/) node output a random number every second.
So let's hook up an Inject, with `msg.payload`'s output being a JSONata expression
`$round($random() * 100)` to generate a random number. And let's make sure it
@@ -82,7 +82,7 @@ This is mostly a programmers job, but it's not hard, so let's get to it. A butto
would be great to reset the timer, and for the sake of this post we can hardcode
the deadline to 1m from the button press.
-When dragging in a button node, connect it to a [change](/node-red/core-nodes/change)
+When dragging in a button node, connect it to a [change](/docs/node-red/core-nodes/function/change/)
node. In the change node set the flow variable `flow.deadline` to the timestamp. The
Inject node from earlier needs updating to inject the `flow.deadline`. All that's
left is calculating how many seconds passed, and normalizing 60 seconds to the
diff --git a/src/blog/2023/11/community-news-11.md b/src/blog/2023/11/community-news-11.md
index e06ced8fe3..830502cc54 100644
--- a/src/blog/2023/11/community-news-11.md
+++ b/src/blog/2023/11/community-news-11.md
@@ -59,7 +59,7 @@ Explore building manufacturing applications with FlowFuse Blueprints in our upco
* [Meet FlowFuse at SPS Nuremberg](/blog/2023/11/meet-us-at-sps-nuremberg/) - Talk about Node-RED and how FlowFuse can help you operationalize your flows!
-* [Install the FlowFuse Edge Agent on the Raspberry Pi 5](/node-red/hardware/raspberry-pi-5) - Managing your Raspberry Pi 5 with Node-RED through FlowFuse is easy to set up
+* [Install the FlowFuse Edge Agent on the Raspberry Pi 5](/docs/node-red/hardware/raspberry-pi-5) - Managing your Raspberry Pi 5 with Node-RED through FlowFuse is easy to set up
* [Innovate from within - Why manufacturing must embrace Citizen Developers](/blog/2023/10/citizen-development/) - Empower your Operational Technology teams as Citizen Developers
diff --git a/src/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud.md b/src/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud.md
index 2d43a66f50..0fa5b2a1da 100644
--- a/src/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud.md
+++ b/src/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud.md
@@ -59,7 +59,7 @@ Integrating InfluxDB enables effective data storage and management:
### Data Generation and Management
For testing, we have created a flow to get you started. Follow this [link](https://flows.nodered.org/flow/66f37bb739b6cdb0c7ad3a4e2edd68ef) and import it. There are four sets of flows for you to begin with. The first is for data generation. The second is a manual data generation flow. The third is key as it initiates the creation of a database, in this case, **mydb**. The last flow is a simple query that pulls data from InfluxDB.
-1. Import the flows into your FlowFuse instance of Node-RED and deploy. Follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#2.-import-helpful-example-flows-provided-with-custom-nodes) for importing and exporting.
+1. Import the flows into your FlowFuse instance of Node-RED and deploy. Follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#_2-import-helpful-example-flows-provided-with-custom-nodes) for importing and exporting.
2. Return to Flowfuse, go to your instance, and create another [snapshot](/docs/user/snapshots/#create-a-snapshot).
3. Ensure that you **Set Target Snapshot**.
diff --git a/src/blog/2024/01/import-a-file.md b/src/blog/2024/01/import-a-file.md
index 6567e8a124..edba5b1a08 100644
--- a/src/blog/2024/01/import-a-file.md
+++ b/src/blog/2024/01/import-a-file.md
@@ -30,7 +30,7 @@ This simple flow allows the user to visualize data from a CSV in the [Node-RED D
### Instructions ###
1. Install Node-RED Dashboard 2.0. Follow these [instructions](/blog/2024/03/dashboard-getting-started/) to install.
-2. Import Flow - to import the flow into your Node-RED instance follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#1.-copy-and-share-your-flows-using-export-and-import).
+2. Import Flow - to import the flow into your Node-RED instance follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#_1-copy-and-share-your-flows-using-export-and-import).
3. Access Dashboard - To access the dashboard, navigate to the `https://.flowfuse.cloud/dashboard`.
This dashboard is currently configured to take in CSV files and transform them into a single message that is sent to the table for visualization. Simultaneously the data from the import is stored locally in the flow context. From there, the button can be used to trigger the sending of the data from the flow context to the next destination. In this case, it is a simple debug node.
diff --git a/src/blog/2024/01/send-a-file.md b/src/blog/2024/01/send-a-file.md
index d1bb878604..56e17c5beb 100644
--- a/src/blog/2024/01/send-a-file.md
+++ b/src/blog/2024/01/send-a-file.md
@@ -132,7 +132,7 @@ Once we have a file ready to be sent, we now need to configure the receiving sid
A link to the flow can be found [here](https://flows.nodered.org/flow/effb53752e5d6f767b3c7e5d41a4a6e8).
-To import the flow, follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#1.-copy-and-share-your-flows-using-export-and-import).
+To import the flow, follow these [instructions](/blog/2023/03/3-quick-node-red-tips-5/#_1-copy-and-share-your-flows-using-export-and-import).
A Simple HTTP In node can be used in the form of a Post, ensuring the configuration allows for a file.
diff --git a/src/blog/2024/01/unified-namespace-what-broker.md b/src/blog/2024/01/unified-namespace-what-broker.md
index 0970214521..141e3608ec 100644
--- a/src/blog/2024/01/unified-namespace-what-broker.md
+++ b/src/blog/2024/01/unified-namespace-what-broker.md
@@ -39,13 +39,13 @@ In addition to vendor lock-in, cloud message queue brokers also introduce relian
### Exotic options
-RabbitMQ is a widely used open-source message broker that’s mostly used as an event message bus for web applications. It can also function as a hub in a unified namespace. The broker primarily supports the [AMQP](/node-red/protocol/amqp/) (Advanced Message Queuing Protocol), considered the industry standard for high-performance messaging systems. It also supports STOMP (Streaming Text Oriented Messaging Protocol) and MQTT (MQ Telemetry Transport), catering to various messaging needs.
+RabbitMQ is a widely used open-source message broker that’s mostly used as an event message bus for web applications. It can also function as a hub in a unified namespace. The broker primarily supports the [AMQP](/docs/node-red/protocol/amqp/) (Advanced Message Queuing Protocol), considered the industry standard for high-performance messaging systems. It also supports STOMP (Streaming Text Oriented Messaging Protocol) and MQTT (MQ Telemetry Transport), catering to various messaging needs.
NATS, short for Network Agnostic Messaging System, is another open-source message broker that is designed for simplicity and reliability. NATS implements its own protocols, making it harder to be interoperable with hardware and software previously purchased. NATS has requirements on message structure too, which creates another barrier to adoption for IoT use cases.
## How Node-RED Helps
-Node-RED provides a powerful and flexible way to integrate with various brokers, supporting protocols such as [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), [Kafka](/blog/2024/03/using-kafka-with-node-red/), and [AMQP](/node-red/protocol/amqp/). It allows you to build and manage workflows that interact with your chosen broker, seamlessly connecting different data sources and systems.
+Node-RED provides a powerful and flexible way to integrate with various brokers, supporting protocols such as [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), [Kafka](/blog/2024/03/using-kafka-with-node-red/), and [AMQP](/docs/node-red/protocol/amqp/). It allows you to build and manage workflows that interact with your chosen broker, seamlessly connecting different data sources and systems.
However, using Node-RED alone in production environments requires additional considerations, such as server deployment, instance management, security implementation, and scalability. This is where FlowFuse enhances Node-RED's capabilities by adding production-ready features. FlowFuse simplifies managing and deploying Node-RED applications, providing essential functionalities like scalability, robust security, and efficient collaboration tools.
diff --git a/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md b/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md
index 47c859b511..ec7e69d7a2 100644
--- a/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md
+++ b/src/blog/2024/05/exploring-node-red-dashboard-2-widgets.md
@@ -148,7 +148,7 @@ _Screenshot displaying the change node retrieving expense data from global conte
{data-zoomable}
_Screenshot displaying the change node converting amount to number_
-5. Drag a **Join** node onto the canvas, select mode as **reduced expression**, and set the **Reduce exp** to `$A + payload.amount`. Set Initial value to `0`, and **Fix-up exp** to `$A`. Give this **join** node the name "Calculate total". This function operates similarly to using the javascript reduce method on an array to calculate the sum of its values. `$A` stores the accumulated value, and with every incoming message payload, it adds the `payload.amount` value to it, for more details on this refer to the [core node docs on join node](/node-red/core-nodes/join/).
+5. Drag a **Join** node onto the canvas, select mode as **reduced expression**, and set the **Reduce exp** to `$A + payload.amount`. Set Initial value to `0`, and **Fix-up exp** to `$A`. Give this **join** node the name "Calculate total". This function operates similarly to using the javascript reduce method on an array to calculate the sum of its values. `$A` stores the accumulated value, and with every incoming message payload, it adds the `payload.amount` value to it, for more details on this refer to the [core node docs on join node](/docs/node-red/core-nodes/sequence/join/).
{data-zoomable}
_Screenshot displaying the join node calculating the total income and expense data_
diff --git a/src/blog/2024/05/understanding-node-flow-global-environment-variables-in-node-red.md b/src/blog/2024/05/understanding-node-flow-global-environment-variables-in-node-red.md
index 381c12ac4c..39e726a23d 100644
--- a/src/blog/2024/05/understanding-node-flow-global-environment-variables-in-node-red.md
+++ b/src/blog/2024/05/understanding-node-flow-global-environment-variables-in-node-red.md
@@ -49,7 +49,7 @@ Variables in Node-RED serve as containers for storing and managing data througho
Node-RED offers three primary variable categories:
-**Message variables** travel with the message object as it flows through your nodes. The most common example is `msg.payload`, which carries the primary data between nodes. For a deeper dive into message handling, see the [Understanding Node-RED Messages](/node-red/getting-started/node-red-messages/) guide.
+**Message variables** travel with the message object as it flows through your nodes. The most common example is `msg.payload`, which carries the primary data between nodes. For a deeper dive into message handling, see the [Understanding Node-RED Messages](/docs/node-red/getting-started/node-red-messages/) guide.
**Context variables** store application state at different levels, node, flow, or global scope. They persist data that needs to be accessed across multiple message events, making them ideal for tracking counters, storing configuration, or maintaining state.
diff --git a/src/blog/2024/06/how-to-use-mqtt-in-node-red.md b/src/blog/2024/06/how-to-use-mqtt-in-node-red.md
index af62446b49..721b9f2784 100644
--- a/src/blog/2024/06/how-to-use-mqtt-in-node-red.md
+++ b/src/blog/2024/06/how-to-use-mqtt-in-node-red.md
@@ -77,7 +77,7 @@ Before you start, make sure you have:
Node-RED ships with MQTT nodes already installed. Open your Node-RED editor and look in the palette, you'll find **mqtt-in** and **mqtt-out** under the network section.
-> If you're using FlowFuse's managed MQTT broker, this is straightforward. Use the [ff-mqtt-in](/node-red/flowfuse/mqtt/mqtt-in/) and [ff-mqtt-out](/node-red/flowfuse/mqtt/mqtt-out/) nodes instead of the standard MQTT nodes. Simply drag one onto the canvas, and the connection to FlowFuse's broker will be configured automatically.
+> If you're using FlowFuse's managed MQTT broker, this is straightforward. Use the [ff-mqtt-in](/docs/flowfuse-nodes/mqtt/mqtt-in/) and [ff-mqtt-out](/docs/flowfuse-nodes/mqtt/mqtt-out/) nodes instead of the standard MQTT nodes. Simply drag one onto the canvas, and the connection to FlowFuse's broker will be configured automatically.
For any other broker, drag an **mqtt-in** or **mqtt-out** node onto your workspace. Double-click it to open the configuration panel.
diff --git a/src/blog/2024/07/calling-python-script-from-node-red.md b/src/blog/2024/07/calling-python-script-from-node-red.md
index c9759b6843..540bbb2b2e 100644
--- a/src/blog/2024/07/calling-python-script-from-node-red.md
+++ b/src/blog/2024/07/calling-python-script-from-node-red.md
@@ -103,7 +103,7 @@ Let's now see how to call a Python script from Node-RED. First, we'll create a b
```
::
-Now, let's execute this Python script from Node-RED. To do that, we will use Node-RED's [Exec](/node-red/core-nodes/exec/) node, which allows running commands on your system.
+Now, let's execute this Python script from Node-RED. To do that, we will use Node-RED's [Exec](/docs/node-red/core-nodes/function/exec/) node, which allows running commands on your system.
1. Drag an Inject node onto the canvas.
2. Drag an Exec node onto the canvas and Configure the command to `python ./example.py -u`. The -u flag prevents potential output buffering issues when executing Python scripts via exec.
@@ -125,7 +125,7 @@ Now, when you deploy this flow and click on the inject node to execute the file,
Having explored how to run a Python script within Node-RED with the basic practical example, let's move to a real-world scenario. We'll demonstrate how to read sensor data using Python, despite Node-RED providing numerous community-built nodes for this purpose. This approach provides deeper insights into integrating external scripts, showcasing the flexibility of Node-RED for custom solutions.
-Before proceeding, ensure that Node-RED is running on a device connected to a temperature sensor. For detailed instructions, refer to [Setting Up Node-RED on Different Hardware](/node-red/hardware/), In this case, we are running Node-RED on a Raspberry Pi 5 with a DHT11 sensor connected to it.
+Before proceeding, ensure that Node-RED is running on a device connected to a temperature sensor. For detailed instructions, refer to [Setting Up Node-RED on Different Hardware](/docs/node-red/hardware/), In this case, we are running Node-RED on a Raspberry Pi 5 with a DHT11 sensor connected to it.
1. Drag an Inject node onto the canvas, and set repeat to 1 seconds of interval.
2. Drag an Exec node and set the path to `python .py`, replace the filename with the name of the file which reads the sensor data, and make sure the python file doesn't contain the loop.
diff --git a/src/blog/2024/08/opc-ua-to-mqtt-with-node-red.md b/src/blog/2024/08/opc-ua-to-mqtt-with-node-red.md
index a4e166badd..b8509e2063 100644
--- a/src/blog/2024/08/opc-ua-to-mqtt-with-node-red.md
+++ b/src/blog/2024/08/opc-ua-to-mqtt-with-node-red.md
@@ -190,13 +190,13 @@ _Video showing the successful bridging of OPC UA data to MQTT_
- [OPC UA Client and Server on FlowFuse](/integrations/opcua/)
See FlowFuse's full OPC UA client and server capabilities, certified node, and security model in one place.
-- [Using MQTT with Node-RED](/node-red/protocol/mqtt/)
+- [Using MQTT with Node-RED](/docs/node-red/protocol/mqtt/)
Learn how to integrate MQTT with Node-RED to enhance your IoT solutions with real-time data messaging.
- [How to Build an OPC UA Client Dashboard in Node-RED](/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/)
Follow a step-by-step guide to create a comprehensive OPC UA client dashboard in Node-RED for effective monitoring and control.
-- [Building a Secure OPC UA Server in Node-RED](/node-red/protocol/opc-ua/)
+- [Building a Secure OPC UA Server in Node-RED](/docs/node-red/protocol/opc-ua/)
Explore best practices for configuring a secure OPC UA server in Node-RED to ensure safe and reliable data exchange.
- [How to Deploy a Basic OPC UA Server in Node-RED](/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/)
diff --git a/src/blog/2024/10/exploring-flowfuse-project-nodes.md b/src/blog/2024/10/exploring-flowfuse-project-nodes.md
index a8df1675f5..491151b560 100644
--- a/src/blog/2024/10/exploring-flowfuse-project-nodes.md
+++ b/src/blog/2024/10/exploring-flowfuse-project-nodes.md
@@ -137,7 +137,7 @@ This example showcases one of many powerful use cases for FlowFuse project nodes
## Using Project Call Nodes
-**Project Call** nodes are ideal for triggering flows deployed on another Node-RED instance and retrieving the final result as a response. While they function similarly to [webhooks](/node-red/integration-technologies/webhook/), they utilize [MQTT](/node-red/protocol/mqtt/) as their underlying mechanism instead of HTTP. In this section, we will demonstrate the use of a **Project Call** node through an example of making an on-demand temperature request.
+**Project Call** nodes are ideal for triggering flows deployed on another Node-RED instance and retrieving the final result as a response. While they function similarly to [webhooks](/docs/node-red/integration-technologies/webhook/), they utilize [MQTT](/docs/node-red/protocol/mqtt/) as their underlying mechanism instead of HTTP. In this section, we will demonstrate the use of a **Project Call** node through an example of making an on-demand temperature request.
### How Project Call Nodes Work
@@ -175,7 +175,7 @@ Throughout this section, we will explore how to utilize the **Project Call** nod
```
::
-1. Copy/download the flow above and import/upload it into your Raspberry Pi Node-RED instance. Ensure you have correctly interfaced the DHT11 sensor with your Raspberry Pi. For more information, refer to our guide on [Setting Up Node-RED on Raspberry Pi 4](/node-red/hardware/raspberry-pi-4/), which explains how to install the device agent on the Raspberry Pi and read temperature data from the DHT11 sensor.
+1. Copy/download the flow above and import/upload it into your Raspberry Pi Node-RED instance. Ensure you have correctly interfaced the DHT11 sensor with your Raspberry Pi. For more information, refer to our guide on [Setting Up Node-RED on Raspberry Pi 4](/docs/node-red/hardware/raspberry-pi-4/), which explains how to install the device agent on the Raspberry Pi and read temperature data from the DHT11 sensor.
2. Deploy the flow.
Once you deploy the flow, you will see the temperature data displayed on the Debug panel if everything was done correctly. Now, let’s add the project nodes to trigger the temperature reading flow on demand and retrieve the data accordingly.
diff --git a/src/blog/2024/10/quick-ways-to-write-functions-in-node-red.md b/src/blog/2024/10/quick-ways-to-write-functions-in-node-red.md
index ac0b722c85..6fa7ad4e99 100644
--- a/src/blog/2024/10/quick-ways-to-write-functions-in-node-red.md
+++ b/src/blog/2024/10/quick-ways-to-write-functions-in-node-red.md
@@ -28,7 +28,7 @@ _Image showing the function node_
## What Are Function Nodes and Common Challenges?
-[Function Nodes](/node-red/core-nodes/function/) in Node-RED allow you to write custom JavaScript for processing messages. While they provide flexibility, many users find it challenging to turn complex business rules into code and manage variables. For more details on the benefits and drawbacks of using Function Nodes, refer to this [Article](/blog/2023/03/why-should-you-use-node-red-function-nodes/).
+[Function Nodes](/docs/node-red/core-nodes/function/) in Node-RED allow you to write custom JavaScript for processing messages. While they provide flexibility, many users find it challenging to turn complex business rules into code and manage variables. For more details on the benefits and drawbacks of using Function Nodes, refer to this [Article](/blog/2023/03/why-should-you-use-node-red-function-nodes/).
Before using Function Nodes, consider if existing low-code nodes can fulfill your needs. Using standard low-code nodes can simplify your approach and enhance collaboration and clarity. If you still feel the need to use Function Nodes, don’t worry, In the following section, we’ll explore straightforward strategies to make working with Function Nodes easier.
diff --git a/src/blog/2024/11/building-uns-with-flowfuse.md b/src/blog/2024/11/building-uns-with-flowfuse.md
index 1ca9810104..54d5278414 100644
--- a/src/blog/2024/11/building-uns-with-flowfuse.md
+++ b/src/blog/2024/11/building-uns-with-flowfuse.md
@@ -40,7 +40,7 @@ Fortunately, Node-RED provides support for a wide range of industrial protocols,
By leveraging Node-RED, you can collect data from these legacy systems, process and transform the data using low-code workflows, and then seamlessly send it to the cloud via modern protocols such as MQTT, Kafka, AMQP, and more.
-In our example, Node-RED can directly collect metrics from sensor using [I2C](https://flows.nodered.org/node/node-red-contrib-i2c) on the Raspberry Pi. This approach simplifies the process by eliminating the need for additional communication layers. To run Node-RED on the Raspberry Pi, we use [FlowFuse Device Agent](/platform/device-agent/), This agent enables you to remotely monitor, manage, and build Node-RED flows securely through the FlowFuse platform remotely. [See here](/node-red/hardware/) for more details on how to set up and run FlowFuse Device Agent on different devices.
+In our example, Node-RED can directly collect metrics from sensor using [I2C](https://flows.nodered.org/node/node-red-contrib-i2c) on the Raspberry Pi. This approach simplifies the process by eliminating the need for additional communication layers. To run Node-RED on the Raspberry Pi, we use [FlowFuse Device Agent](/platform/device-agent/), This agent enables you to remotely monitor, manage, and build Node-RED flows securely through the FlowFuse platform remotely. [See here](/docs/node-red/hardware/) for more details on how to set up and run FlowFuse Device Agent on different devices.
### Step 2: Transform and Process the Collected metrics
@@ -60,7 +60,7 @@ Raw data from the ADXL345 sensor might look like this:
[26,0,244,255,37,255]
```
-Using a [Function node](/node-red/core-nodes/function/) in Node-RED, we can convert this into a human-readable format.
+Using a [Function node](/docs/node-red/core-nodes/function/) in Node-RED, we can convert this into a human-readable format.
{data-zoomable}
_Function node: Transforming Raw Data into Readable Format_
@@ -80,7 +80,7 @@ While this is more readable, it can still be challenging to monitor changes in v
{data-zoomable}
_Change node: Calculating Magnitude_
-After calculating the Magnitude using a [Change node](/node-red/core-nodes/change/), the data might look like this:
+After calculating the Magnitude using a [Change node](/docs/node-red/core-nodes/function/change/), the data might look like this:
```json
{
@@ -160,7 +160,7 @@ While Sparkplug B provides a standardized topic model, its hierarchy may not alw
### Step 5: Sending Collected metrics to UNS
-With your topic naming convention chosen, it’s time to send the data to the UNS. In Node-RED, we will use the [MQTT Out](/node-red/core-nodes/mqtt-in/) node to send the transformed data to the broker.
+With your topic naming convention chosen, it’s time to send the data to the UNS. In Node-RED, we will use the [MQTT Out](/docs/node-red/core-nodes/network/mqtt-in/) node to send the transformed data to the broker.
1. Drag an MQTT out node into your flow.
2. Configure the node to connect to the FlowFuse MQTT Broker using the client credentials generated earlier.
diff --git a/src/blog/2024/11/why-pub-sub-in-uns.md b/src/blog/2024/11/why-pub-sub-in-uns.md
index 817e63e04d..c189f8f6f6 100644
--- a/src/blog/2024/11/why-pub-sub-in-uns.md
+++ b/src/blog/2024/11/why-pub-sub-in-uns.md
@@ -32,7 +32,7 @@ Before discussing why Publish/Subscribe (Pub/Sub) is essential for a UNS, let's
{data-zoomable}
_Publish Subscribe Model_
-The Pub/Sub model is a way for systems to communicate where one component, called the publisher, sends messages to a central system ( Broker such as [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), [RabitMQ](/node-red/protocol/amqp/), and [Kafka](/blog/2024/03/using-kafka-with-node-red/) ), and other components, called subscribers, receive those messages. The publisher doesn’t need to know who the subscribers are, and the subscribers don’t know who the publishers are. The central system, or broker, ensures the right messages go to the right subscribers based on their interests.
+The Pub/Sub model is a way for systems to communicate where one component, called the publisher, sends messages to a central system ( Broker such as [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), [RabitMQ](/docs/node-red/protocol/amqp/), and [Kafka](/blog/2024/03/using-kafka-with-node-red/) ), and other components, called subscribers, receive those messages. The publisher doesn’t need to know who the subscribers are, and the subscribers don’t know who the publishers are. The central system, or broker, ensures the right messages go to the right subscribers based on their interests.
Additionally, it’s important to note that the roles of publisher and subscriber are not mutually exclusive. A component can act as a publisher in one context, sending messages to the broker, and as a subscriber in another, receiving messages from the broker.
diff --git a/src/blog/2024/12/publishing-modbus-data-to-uns.md b/src/blog/2024/12/publishing-modbus-data-to-uns.md
index a471bba9d5..c794c8e14a 100644
--- a/src/blog/2024/12/publishing-modbus-data-to-uns.md
+++ b/src/blog/2024/12/publishing-modbus-data-to-uns.md
@@ -130,7 +130,7 @@ After configuring the connection, it's time to test the data collection.
If no data appears, check the connection settings (IP address, Unit ID, port, etc.) and ensure your Modbus device is correctly configured and accessible. If you use a simulator like ModSim, ensure it’s running and properly configured to send data.
-For more information on using Modbus with Node-RED, please read our tutorial on [Using Modbus with Node-RED](/node-red/protocol/modbus/).
+For more information on using Modbus with Node-RED, please read our tutorial on [Using Modbus with Node-RED](/docs/node-red/protocol/modbus/).
If you prefer a video explanation, [Kurt Braun](https://www.linkedin.com/in/wago-kurt-braun/) from WAGO demonstrates how to collect Modbus data using Node-RED in FlowFuse:
@@ -161,7 +161,7 @@ We must convert these raw register values into human-readable formats for cloud
To determine how to process raw Modbus data, such as dividing by a specific value, concatenating, or applying other transformation formulas, refer to the manual of the sensor you use for specific instructions.
-In Node-RED, you can use various nodes for transformation. You can choose the [Function node](/node-red/core-nodes/function/) for advanced processing, the [Change node](/node-red/core-nodes/change/) for simpler operations, or the [Template node](/node-red/core-nodes/template/) for defining schemas. For more complex data parsing scenarios, such as handling multiple data types (floats, 32-bit integers, strings), dealing with big-endian/little-endian conversions, or performing byte swapping, consider using the `node-red-contrib-buffer-parser` node. This specialized node simplifies parsing Modbus buffers into various data formats without writing custom code. Learn more in our guide on [using Buffer Parser for industrial data](/blog/2025/12/node-red-buffer-parser-industrial-data/). In this article, I will demonstrate a low-code approach using the Change node to process the data cleanly.
+In Node-RED, you can use various nodes for transformation. You can choose the [Function node](/docs/node-red/core-nodes/function/) for advanced processing, the [Change node](/docs/node-red/core-nodes/function/change/) for simpler operations, or the [Template node](/docs/node-red/core-nodes/function/template/) for defining schemas. For more complex data parsing scenarios, such as handling multiple data types (floats, 32-bit integers, strings), dealing with big-endian/little-endian conversions, or performing byte swapping, consider using the `node-red-contrib-buffer-parser` node. This specialized node simplifies parsing Modbus buffers into various data formats without writing custom code. Learn more in our guide on [using Buffer Parser for industrial data](/blog/2025/12/node-red-buffer-parser-industrial-data/). In this article, I will demonstrate a low-code approach using the Change node to process the data cleanly.
Additionally, for better organization and accessibility, I will send each metric separately and include additional metadata such as the `timestamp` and `unit`.
@@ -288,7 +288,7 @@ _MQTT Out node configuration for temperature data_
**Using FlowFuse MQTT Nodes**
-If you're using the FlowFuse MQTT broker, FlowFuse provides specialized MQTT nodes that simplify configuration. These nodes automatically configure the broker connection details when you drop them onto the canvas, no manual setup of server address, Client ID, username, or password required. You also won't need to manually create clients in the broker; they're automatically created when you use these nodes. This streamlines the development process and reduces configuration errors. Learn more about [FlowFuse MQTT nodes](/node-red/flowfuse/mqtt/).
+If you're using the FlowFuse MQTT broker, FlowFuse provides specialized MQTT nodes that simplify configuration. These nodes automatically configure the broker connection details when you drop them onto the canvas, no manual setup of server address, Client ID, username, or password required. You also won't need to manually create clients in the broker; they're automatically created when you use these nodes. This streamlines the development process and reduces configuration errors. Learn more about [FlowFuse MQTT nodes](/docs/flowfuse-nodes/mqtt/).
**Step 3.3: Configure MQTT Nodes for Remaining Metrics**
diff --git a/src/blog/2025/01/mqtt-frontrunner-for-uns.md b/src/blog/2025/01/mqtt-frontrunner-for-uns.md
index 538c790ca0..32755595e4 100644
--- a/src/blog/2025/01/mqtt-frontrunner-for-uns.md
+++ b/src/blog/2025/01/mqtt-frontrunner-for-uns.md
@@ -21,7 +21,7 @@ In this first part of our series, we’ll explain why MQTT is the standout choic
The [Unified Namespace (UNS)](/use-cases/uns/) is a data architecture (not just a tool or new technology) that centralizes and organizes data from various sources into a single, unified structure. It eliminates data silos by providing a standardized way to represent, access, and share information across different devices, systems, and services. For more information on what is UNS, read our article: [Introduction to the Unified Namespace](/blog/2023/12/introduction-to-unified-namespace/).
-When choosing a broker for your UNS, it's crucial to consider how well the selected broker fits the specific requirements of your IIoT environment, including the types of devices and systems involved, as well as factors like scalability, reliability, and ease of integration. Several options are available alongside MQTT, including [AMQP](/node-red/protocol/amqp/), [Kafka](/blog/2024/03/using-kafka-with-node-red/), and cloud message brokers like AWS Kinesis and GCP Pub/Sub. While these alternatives offer unique features, MQTT stands out, and we’ll explain why later in this article. But If you’re interested in a brief overview of why these alternatives are not the best fit for UNS, check out our article: [Unified Namespace: What Broker to Use?](/blog/2024/01/unified-namespace-what-broker/)
+When choosing a broker for your UNS, it's crucial to consider how well the selected broker fits the specific requirements of your IIoT environment, including the types of devices and systems involved, as well as factors like scalability, reliability, and ease of integration. Several options are available alongside MQTT, including [AMQP](/docs/node-red/protocol/amqp/), [Kafka](/blog/2024/03/using-kafka-with-node-red/), and cloud message brokers like AWS Kinesis and GCP Pub/Sub. While these alternatives offer unique features, MQTT stands out, and we’ll explain why later in this article. But If you’re interested in a brief overview of why these alternatives are not the best fit for UNS, check out our article: [Unified Namespace: What Broker to Use?](/blog/2024/01/unified-namespace-what-broker/)
There is also an ongoing debate regarding the use of OPC-UA and other protocols for implementing UNS. While I won’t dive into this in detail here as i havent explored it much yet, I encourage you to start with the approach we call reverse engineering. First, understand why MQTT is the preferred choice for implementing UNS, and then explore how its features align with UNS needs. From there, you can evaluate whether other protocols offer similar capabilities. By following this process, you will find the right answer of your questions.
@@ -32,7 +32,7 @@ There is also an ongoing debate regarding the use of OPC-UA and other protocols
Before diving into its specific advantages for UNS, let’s take a brief look at the history of **MQTT** and how it became the backbone of modern IoT communication.
-[MQTT](/node-red/protocol/mqtt/) was developed in the late 1990s by Andy Stanford-Clark at IBM and Arlen Nipper at Eurotech to address communication challenges in low-bandwidth, unreliable networks. This early focus on lightweight messaging paved the way for MQTT to become a pioneering solution for the rapidly expanding IoT space.
+[MQTT](/docs/node-red/protocol/mqtt/) was developed in the late 1990s by Andy Stanford-Clark at IBM and Arlen Nipper at Eurotech to address communication challenges in low-bandwidth, unreliable networks. This early focus on lightweight messaging paved the way for MQTT to become a pioneering solution for the rapidly expanding IoT space.
Since then, MQTT has evolved significantly. The protocol has gone through several iterations, from MQTT 3.1.1 to the more feature-rich MQTT 5.0, each version enhancing the protocol's capabilities to meet the demands of an increasingly connected world. Today, more than 25 years later, MQTT remains the **de facto protocol** for IoT applications, and its simplicity, scalability, and reliability continue to make it an ideal choice for industrial systems.
diff --git a/src/blog/2025/04/build-manufacturing-oee-dashboard.md b/src/blog/2025/04/build-manufacturing-oee-dashboard.md
index 853b068407..f071104869 100644
--- a/src/blog/2025/04/build-manufacturing-oee-dashboard.md
+++ b/src/blog/2025/04/build-manufacturing-oee-dashboard.md
@@ -79,7 +79,7 @@ Before you begin building the OEE Dashboard with FlowFuse, make sure you have th
- **Running FlowFuse Instance:** Make sure you have a FlowFuse instance set up and running. If you don't have an account, check out our [free trial](https://app.flowfuse.com/account/create) and learn how to create an instance in FlowFuse.
- **FlowFuse Dashboard:** Ensure you have [FlowFuse Dashboard](https://flows.nodered.org/node/@flowfuse/node-red-dashboard) (also known as Node-RED Dashboard 2.0 in the community) installed and properly configured on your instance.
-- **SQLite Contrib Node:** Ensure you have [node-red-contrib-sqlite](https://flows.nodered.org/node/node-red-node-sqlite) installed. We use SQLite here because it needs no setup, but the flow works against any database - [FlowFuse Tables](/docs/user/ff-tables/) gives you managed PostgreSQL if you want something production-grade from the start, and our [Database](/node-red/database/) guides cover MongoDB, InfluxDB, TimescaleDB, and DynamoDB.
+- **SQLite Contrib Node:** Ensure you have [node-red-contrib-sqlite](https://flows.nodered.org/node/node-red-node-sqlite) installed. We use SQLite here because it needs no setup, but the flow works against any database - [FlowFuse Tables](/docs/user/ff-tables/) gives you managed PostgreSQL if you want something production-grade from the start, and our [Database](/docs/node-red/database/) guides cover MongoDB, InfluxDB, TimescaleDB, and DynamoDB.
### Preparing Simulated Data
diff --git a/src/blog/2025/04/design-and-scale-oee-dashboard.md b/src/blog/2025/04/design-and-scale-oee-dashboard.md
index 25311c0600..c87815ff59 100644
--- a/src/blog/2025/04/design-and-scale-oee-dashboard.md
+++ b/src/blog/2025/04/design-and-scale-oee-dashboard.md
@@ -271,7 +271,7 @@ To make the dashboard truly useful in a live setting, you must understand how to
2. Replace the existing `sqlite` nodes in your flow with the nodes for the database you are using.
3. If using SQL based database, queries may remain unchanged. For NoSQL or time-series DBs, rewrite the queries as needed.
-For help, refer to our [Database](/node-red/database/) section, which includes guides for MongoDB, PostgreSQL, InfluxDB, TimescaleDB, and DynamoDB. If you do not already have a database to point at, [FlowFuse Tables](/docs/user/ff-tables/) gives you a managed PostgreSQL instance inside the platform - we walk through that pattern end to end in [Building a historical data dashboard with FlowFuse Tables](/blog/2025/08/time-series-dashboard-flowfuse-postgresql/).
+For help, refer to our [Database](/docs/node-red/database/) section, which includes guides for MongoDB, PostgreSQL, InfluxDB, TimescaleDB, and DynamoDB. If you do not already have a database to point at, [FlowFuse Tables](/docs/user/ff-tables/) gives you a managed PostgreSQL instance inside the platform - we walk through that pattern end to end in [Building a historical data dashboard with FlowFuse Tables](/blog/2025/08/time-series-dashboard-flowfuse-postgresql/).
When connecting to your real data source, you may notice that the field names used in your database differ from those used in the our oee dashboard sqlite node queries. While this seems like a lot of manual work, the dashboard is designed with flexibility in mind. You only need to make two changes to adapt the queries to your schema.
diff --git a/src/blog/2025/06/data-acquisition-for-mes.md b/src/blog/2025/06/data-acquisition-for-mes.md
index dba90e0af7..07b70b7c0e 100644
--- a/src/blog/2025/06/data-acquisition-for-mes.md
+++ b/src/blog/2025/06/data-acquisition-for-mes.md
@@ -64,14 +64,14 @@ Following are some of the most commonly used protocol nodes:
- **Modbus:**
- **OPC UA:**
- **OPC DA:**
-- **MQTT:** [/node-red/core-nodes/mqtt-in/](/node-red/core-nodes/mqtt-in/)
+- **MQTT:** [/docs/node-red/core-nodes/network/mqtt-in/](/docs/node-red/core-nodes/network/mqtt-in/)
- **Ethernet/IP:**
- **Siemens S7:**
- **MITSUBISHI MC:**
- **OMRON FINS:**
-- **HTTP:** [/node-red/core-nodes/http-in/](/node-red/core-nodes/http-in/)
+- **HTTP:** [/docs/node-red/core-nodes/network/http-in/](/docs/node-red/core-nodes/network/http-in/)
- **LwM2M:**
-- **AMQP:** [/node-red/protocol/amqp/](/node-red/protocol/amqp/)
+- **AMQP:** [/docs/node-red/protocol/amqp/](/docs/node-red/protocol/amqp/)
- **Serialport:**
- **GPIO:**
- **Lorawan:**
diff --git a/src/blog/2025/06/structuring-storing-data-mes-integration.md b/src/blog/2025/06/structuring-storing-data-mes-integration.md
index 64a97c6431..32a817a2dc 100644
--- a/src/blog/2025/06/structuring-storing-data-mes-integration.md
+++ b/src/blog/2025/06/structuring-storing-data-mes-integration.md
@@ -162,7 +162,7 @@ It has tons of nodes for almost every database and cloud storage system you'll f
This includes direct **connections** to normal databases like [MySQL](https://flows.nodered.org/node/node-red-node-mysql) and [PostgreSQL](https://flows.nodered.org/node/node-red-contrib-postgresql) for your organized production data.
-It also has special nodes for time-series databases like [InfluxDB](https://flows.nodered.org/node/node-red-contrib-influxdb) and [TimescaleDB](/node-red/database/timescaledb/) to handle fast sensor and machine data.
+It also has special nodes for time-series databases like [InfluxDB](https://flows.nodered.org/node/node-red-contrib-influxdb) and [TimescaleDB](/docs/node-red/database/timescaledb/) to handle fast sensor and machine data.
Plus, FlowFuse **connects** to big Data Lakes and Cloud Storage services like [Amazon S3](https://flows.nodered.org/node/node-red-node-aws), [Google Cloud Storage](https://flows.nodered.org/node/node-red-contrib-google-cloud), and [Microsoft Azure](https://flows.nodered.org/node/node-red-contrib-azure-storage).
diff --git a/src/blog/2025/06/what-is-mes.md b/src/blog/2025/06/what-is-mes.md
index a84c785d80..7230e10d94 100644
--- a/src/blog/2025/06/what-is-mes.md
+++ b/src/blog/2025/06/what-is-mes.md
@@ -50,7 +50,7 @@ A Manufacturing Execution System (MES) connects live shop-floor activity with th
An MES pulls live data from machines, sensors, and operators, then uses it to guide and confirm each step of production. As a work order runs, it can track which machine is handling it, how much material is used, and whether output is meeting specification in real time.
-The hard part is rarely the concept. It is [getting data out of equipment that was never built to share it](/blog/2025/06/data-acquisition-for-mes/). A decade-old PLC may expose raw, uncontextualized tags over a vendor-specific protocol, while the SCADA system reading that data was designed to present it to an operator, not publish it upward. [Modbus](/node-red/protocol/modbus/), EtherNet/IP, Profinet, [S7comm](/blog/2025/01/integrating-siemens-s7-plcs-with-node-red-guide/), and [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) can coexist on the same floor, and none inherently carry the order context an ERP system needs.
+The hard part is rarely the concept. It is [getting data out of equipment that was never built to share it](/blog/2025/06/data-acquisition-for-mes/). A decade-old PLC may expose raw, uncontextualized tags over a vendor-specific protocol, while the SCADA system reading that data was designed to present it to an operator, not publish it upward. [Modbus](/docs/node-red/protocol/modbus/), EtherNet/IP, Profinet, [S7comm](/blog/2025/01/integrating-siemens-s7-plcs-with-node-red-guide/), and [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) can coexist on the same floor, and none inherently carry the order context an ERP system needs.
In a brownfield environment spanning several sites, that becomes a standing integration problem rather than a one-time project. [IT/OT connectivity](/use-cases/it-ot-middleware/) moves production events and quality checks between [PLCs](/landing/plc/), [SCADA](/use-cases/scada/), and [enterprise systems](/landing/enterprise-integration/) without relying on brittle point-to-point integrations.
diff --git a/src/blog/2025/07/quality-control-automation-spc-charts.md b/src/blog/2025/07/quality-control-automation-spc-charts.md
index a456af3d9b..10cc4b542b 100644
--- a/src/blog/2025/07/quality-control-automation-spc-charts.md
+++ b/src/blog/2025/07/quality-control-automation-spc-charts.md
@@ -314,7 +314,7 @@ Time to connect your actual machines. The approach depends on what equipment you
For modern PLCs - anything from the last decade like Siemens S7-1200/1500, Allen-Bradley ControlLogix, or Omron NX - you'll use OPC UA. It's already built into these PLCs. Enable it in the configuration, install `node-red-contrib-opcua` from the FlowFuse palette, and point it at your PLC. The endpoint looks like `opc.tcp://192.168.1.100:4840`. Browse for your measurement tags and connect them to your SPC flow. [Full OPC UA guide here](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/).
-Older equipment speaks Modbus TCP. Check your manual's appendix for the register map. Install `node-red-contrib-modbus`, configure it with your device's IP address and the register holding your measurement (like 40001 for holding registers). Almost every industrial device from the last 30 years supports this. [Modbus tutorial here](/node-red/protocol/modbus/).
+Older equipment speaks Modbus TCP. Check your manual's appendix for the register map. Install `node-red-contrib-modbus`, configure it with your device's IP address and the register holding your measurement (like 40001 for holding registers). Almost every industrial device from the last 30 years supports this. [Modbus tutorial here](/docs/node-red/protocol/modbus/).
For everything else, get creative. Old gauges with RS-232 ports work fine with a USB adapter and the serial node - [see our serial port guide](/blog/2025/07/connect-legacy-equipment-serial-flowfuse/). Machines that dump CSV files can be monitored with the watch node. Manual measurements need just a simple dashboard form, one input field, one submit button. Don't overcomplicate it.
diff --git a/src/blog/2025/09/creating-pareto-chart.md b/src/blog/2025/09/creating-pareto-chart.md
index df3aaf8a15..62ec4bd46c 100644
--- a/src/blog/2025/09/creating-pareto-chart.md
+++ b/src/blog/2025/09/creating-pareto-chart.md
@@ -27,7 +27,7 @@ To create a Pareto Chart for manufacturing data, you'll need access to industria
### Step 1: Connect to Your Data Source
-The first step to create a Pareto Chart is accessing the data you want to analyze. In industrial environments, machine or process data is commonly collected via [industrial protocols](/node-red/protocol/) such as [OPC-UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), or direct [database](/node-red/database/) queries. Modern industrial platforms support nearly all industrial protocols and databases, making it easy to connect to your existing systems.
+The first step to create a Pareto Chart is accessing the data you want to analyze. In industrial environments, machine or process data is commonly collected via [industrial protocols](/docs/node-red/protocol/) such as [OPC-UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), or direct [database](/docs/node-red/database/) queries. Modern industrial platforms support nearly all industrial protocols and databases, making it easy to connect to your existing systems.
To connect your data:
diff --git a/src/blog/2025/09/it-vs-ot-difference-between-information-technology-and-operational-technology.md b/src/blog/2025/09/it-vs-ot-difference-between-information-technology-and-operational-technology.md
index 313e745081..d7f5f49d64 100644
--- a/src/blog/2025/09/it-vs-ot-difference-between-information-technology-and-operational-technology.md
+++ b/src/blog/2025/09/it-vs-ot-difference-between-information-technology-and-operational-technology.md
@@ -64,11 +64,11 @@ Connecting the two (IT/OT convergence) is central to Industry 4.0, but it only w
OT is the umbrella term for the systems that directly run production: [Programmable Logic Controllers (PLCs)](/blog/2025/10/plc-to-mqtt-using-flowfuse/) that execute real-time control logic, [SCADA](/use-cases/scada/) systems that provide centralized monitoring across distributed sites, Distributed Control Systems (DCS) for complex continuous processes, and [Human-Machine Interfaces (HMI)](/blog/2025/11/building-hmi-for-equipment-control/) that give operators visualization and control. Safety Instrumented Systems, Building Management Systems, and [Manufacturing Execution Systems (MES)](/use-cases/mes/) round out the OT landscape. Collectively, these are known as Industrial Control Systems (ICS).
-OT prioritizes safety, availability, and reliability above everything else. These systems were historically air-gapped, receive updates rarely (often only during planned shutdowns), and communicate over industrial protocols like [Modbus](/node-red/protocol/modbus/), Profibus, [OPC-UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/) rather than standard internet protocols. Equipment stays in service for 15-25+ years, runs on millisecond timing, and has essentially zero tolerance for downtime: every stopped minute costs money.
+OT prioritizes safety, availability, and reliability above everything else. These systems were historically air-gapped, receive updates rarely (often only during planned shutdowns), and communicate over industrial protocols like [Modbus](/docs/node-red/protocol/modbus/), Profibus, [OPC-UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/) rather than standard internet protocols. Equipment stays in service for 15-25+ years, runs on millisecond timing, and has essentially zero tolerance for downtime: every stopped minute costs money.
## What is IT (Information Technology)?
-IT covers the systems, software, and infrastructure that manage business data and enable enterprise operations: [email](/node-red/notification/email/) and [databases](/node-red/database/), ERP and CRM platforms, business intelligence, and increasingly cloud and SaaS applications.
+IT covers the systems, software, and infrastructure that manage business data and enable enterprise operations: [email](/docs/node-red/notification/email/) and [databases](/docs/node-red/database/), ERP and CRM platforms, business intelligence, and increasingly cloud and SaaS applications.
IT prioritizes data confidentiality and integrity, stays connected to the internet by default, and receives patches on monthly or quarterly cycles over standardized protocols like TCP/IP, HTTP, and HTTPS. Equipment typically cycles out every 3-5 years, and businesses can usually tolerate minutes-to-hours of downtime for maintenance.
diff --git a/src/blog/2025/09/what-is-takt-time.md b/src/blog/2025/09/what-is-takt-time.md
index 5c54b4f9b2..ed159a0279 100644
--- a/src/blog/2025/09/what-is-takt-time.md
+++ b/src/blog/2025/09/what-is-takt-time.md
@@ -140,11 +140,11 @@ In an ideal lean environment: **Cycle Time should sit at roughly 90–95% of Tak
## Implementing Takt Time Monitoring with FlowFuse
-Understanding takt time in theory is one thing; putting it into practice requires the right tools. [FlowFuse](/) connects to your existing systems, whether [PLCs](/blog/2025/10/plc-to-mqtt-using-flowfuse/), [databases](/node-red/database/), or ERP software, to calculate takt time automatically in real time instead of on static spreadsheets. Before starting, [create a FlowFuse account](https://app.flowfuse.com/account/create) if you don't already have one.
+Understanding takt time in theory is one thing; putting it into practice requires the right tools. [FlowFuse](/) connects to your existing systems, whether [PLCs](/blog/2025/10/plc-to-mqtt-using-flowfuse/), [databases](/docs/node-red/database/), or ERP software, to calculate takt time automatically in real time instead of on static spreadsheets. Before starting, [create a FlowFuse account](https://app.flowfuse.com/account/create) if you don't already have one.
### Step 1: Connect to Your Data Sources
-FlowFuse supports connections to industrial systems through its library of [protocol](/node-red/protocol/) and [database](/node-red/database/) nodes, pulling customer orders from your [ERP system](/blog/2025/06/connect-shop-floor-to-odoo-erp-flowfuse/), production schedules from MES, and real-time counts from PLCs.
+FlowFuse supports connections to industrial systems through its library of [protocol](/docs/node-red/protocol/) and [database](/docs/node-red/database/) nodes, pulling customer orders from your [ERP system](/blog/2025/06/connect-shop-floor-to-odoo-erp-flowfuse/), production schedules from MES, and real-time counts from PLCs.
For this demo, simulate customer orders with an Inject node:
diff --git a/src/blog/2025/10/building-mcp-server-using-flowfuse.md b/src/blog/2025/10/building-mcp-server-using-flowfuse.md
index dc294b3e27..b8aef0c872 100644
--- a/src/blog/2025/10/building-mcp-server-using-flowfuse.md
+++ b/src/blog/2025/10/building-mcp-server-using-flowfuse.md
@@ -41,7 +41,7 @@ Before you begin, ensure you have the following:
* **A running FlowFuse Enterprise instance.** If you do not have one, [contact us](/contact-us/) to discuss Enterprise options and get started.
-* **Ensure the `@flowfuse-nodes/nr-mcp-server-nodes` package is installed**. This will add the [MCP nodes](/node-red/flowfuse/mcp/) to your Node palette in your instance editor.
+* **Ensure the `@flowfuse-nodes/nr-mcp-server-nodes` package is installed**. This will add the [MCP nodes](/docs/flowfuse-nodes/mcp/) to your Node palette in your instance editor.
> **Note:** The MCP nodes (@flowfuse-nodes/nr-mcp-server-nodes) are only available on the Enterprise tier.
diff --git a/src/blog/2025/10/how-to-log-plc-data-csv-files.md b/src/blog/2025/10/how-to-log-plc-data-csv-files.md
index db7b69fa3d..f2d8823245 100644
--- a/src/blog/2025/10/how-to-log-plc-data-csv-files.md
+++ b/src/blog/2025/10/how-to-log-plc-data-csv-files.md
@@ -197,7 +197,7 @@ try {
}
```
-3. Connect it to your notification system to alert when space is critical, for notification you can use [email](/node-red/notification/email/), [telegram](/node-red/notification/telegram/), discord with [FlowFuse](/node-red/notification/discord/).
+3. Connect it to your notification system to alert when space is critical, for notification you can use [email](/docs/node-red/notification/email/), [telegram](/docs/node-red/notification/telegram/), discord with [FlowFuse](/docs/node-red/notification/discord/).
4. Deploy the flow
Now you'll get warnings before disk space becomes critical, giving you time to archive old data or expand storage.
diff --git a/src/blog/2025/11/building-hmi-for-equipment-control.md b/src/blog/2025/11/building-hmi-for-equipment-control.md
index 6f1e4a91a5..9c0a37e049 100644
--- a/src/blog/2025/11/building-hmi-for-equipment-control.md
+++ b/src/blog/2025/11/building-hmi-for-equipment-control.md
@@ -101,7 +101,7 @@ Your HMI needs to talk to your PLC to read equipment status and send control com
Choose the node that matches your PLC:
-- **[node-red-contrib-modbus](/node-red/protocol/modbus/)** – Modbus RTU/TCP PLCs and devices
+- **[node-red-contrib-modbus](/docs/node-red/protocol/modbus/)** – Modbus RTU/TCP PLCs and devices
- **[node-red-contrib-s7](/blog/2025/01/integrating-siemens-s7-plcs-with-node-red-guide/)** – Siemens S7-300/400/1200/1500
- **[node-red-contrib-opcua](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/)** – OPC UA servers (universal industrial standard)
- **[node-red-contrib-cip-ethernet-ip](/blog/2025/10/using-ethernet-ip-with-flowfuse/)** – Allen-Bradley/Rockwell PLCs
diff --git a/src/blog/2025/11/flowfuse+llm+mcp-equals-text-driven-operations.md b/src/blog/2025/11/flowfuse+llm+mcp-equals-text-driven-operations.md
index 40ddfd2ba7..efc47596be 100644
--- a/src/blog/2025/11/flowfuse+llm+mcp-equals-text-driven-operations.md
+++ b/src/blog/2025/11/flowfuse+llm+mcp-equals-text-driven-operations.md
@@ -31,7 +31,7 @@ the right questions.
## The Context Challenge
Data capture involves integrating various machine protocols (like
-[OPC-UA](/node-red/protocol/opc-ua/) or [Modbus](/node-red/protocol/modbus/)),
+[OPC-UA](/docs/node-red/protocol/opc-ua/) or [Modbus](/docs/node-red/protocol/modbus/)),
transporting, combining, and visualizing the information. While low-code tools
like Node-RED have decreased the implementation time to mere hours, the full
problem isn't solved: what happens *after* the data is collected?
@@ -66,7 +66,7 @@ functionality (tools) they want to expose to the LLM.
* **Resources** are read-only, like sensor readings, employee staff lists, vacation calendars, or specification sheets (e.g., upper and lower temperature limits).
* **Tools** are functions that allow the LLM to perform an action or change a state in the physical world.
-By feeding this context into an MCP server (such as the official [FlowFuse MCP node](/node-red/flowfuse/mcp/)),
+By feeding this context into an MCP server (such as the official [FlowFuse MCP node](/docs/flowfuse-nodes/mcp/)),
the LLM transforms into a powerful operational partner.
For example, an operator can ask: "Can you show me the last five temp sensor readings recorded?".
diff --git a/src/blog/2025/11/industrial-data-validation-guide.md b/src/blog/2025/11/industrial-data-validation-guide.md
index 61daea7295..d52de5adfa 100644
--- a/src/blog/2025/11/industrial-data-validation-guide.md
+++ b/src/blog/2025/11/industrial-data-validation-guide.md
@@ -306,7 +306,7 @@ Once installed, you'll find the "telegram sender" and "telegram receiver" nodes
### Creating Your Telegram Bot and Getting Your Chat ID
-Before you can send alerts, you need to create a Telegram bot and get your Chat ID. We have a detailed guide that walks you through the entire process: [How to Create a Telegram Bot and Find Your Chat ID](/node-red/notification/telegram/#creating-a-bot-in-telegram)
+Before you can send alerts, you need to create a Telegram bot and get your Chat ID. We have a detailed guide that walks you through the entire process: [How to Create a Telegram Bot and Find Your Chat ID](/docs/node-red/notification/telegram/#creating-a-bot-in-telegram)
Once you have your **bot token** and **Chat ID**, come back here to continue with the alert setup.
diff --git a/src/blog/2025/12/flowfuse-release-2-25.md b/src/blog/2025/12/flowfuse-release-2-25.md
index 2d6cfdba98..7782afd729 100644
--- a/src/blog/2025/12/flowfuse-release-2-25.md
+++ b/src/blog/2025/12/flowfuse-release-2-25.md
@@ -21,7 +21,7 @@ This release comes with some big updates for the FlowFuse Expert.

_[FlowFuse Expert Interface]_
-Our [MCP nodes](/node-red/flowfuse/mcp/) make is super easy to extend AI Agents with tools and resources in your environment. With this release, we're introducing the ability to interact your MCP servers directly within the FlowFuse Expert.
+Our [MCP nodes](/docs/flowfuse-nodes/mcp/) make is super easy to extend AI Agents with tools and resources in your environment. With this release, we're introducing the ability to interact your MCP servers directly within the FlowFuse Expert.
Previously, when setting up an MCP server in FlowFuse, you would first designate your tools, resources, and servers in side of Node-RED using the MCP nodes. Then, to interact with them, you needed a separate tool like VSCode to query and perform operations.
diff --git a/src/blog/2025/12/mttf-vs-mtbf-vs-mttr.md b/src/blog/2025/12/mttf-vs-mtbf-vs-mttr.md
index 8d7de3cd8f..155c726826 100644
--- a/src/blog/2025/12/mttf-vs-mtbf-vs-mttr.md
+++ b/src/blog/2025/12/mttf-vs-mtbf-vs-mttr.md
@@ -187,4 +187,4 @@ Stop guessing when parts will fail. Track installation dates and failure times,
Use that data to schedule replacements during planned downtime instead of waiting for a 2am breakdown. Unplanned failures typically cost 3-5x more than scheduled replacements once overtime labor, rush shipping, and lost production are factored in, so the only MTTF numbers that really matter are the ones you measure yourself.
-As your equipment base grows, manual tracking becomes cumbersome. [FlowFuse](/) automates this by connecting to [PLCs](/blog/2025/12/what-is-plc/), [SCADA](/use-cases/scada/) systems, [MES](/use-cases/mes/) platforms, and your CMMS, pulling operating hours directly from equipment through industrial protocols like [Modbus](/node-red/protocol/modbus/), [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/), then capturing failure events to recalculate MTTF in real-time across your entire facility.
+As your equipment base grows, manual tracking becomes cumbersome. [FlowFuse](/) automates this by connecting to [PLCs](/blog/2025/12/what-is-plc/), [SCADA](/use-cases/scada/) systems, [MES](/use-cases/mes/) platforms, and your CMMS, pulling operating hours directly from equipment through industrial protocols like [Modbus](/docs/node-red/protocol/modbus/), [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/), then capturing failure events to recalculate MTTF in real-time across your entire facility.
diff --git a/src/blog/2026/01/why-modbus-still-exist.md b/src/blog/2026/01/why-modbus-still-exist.md
index b20c089fcc..4f1f43a9b6 100644
--- a/src/blog/2026/01/why-modbus-still-exist.md
+++ b/src/blog/2026/01/why-modbus-still-exist.md
@@ -120,7 +120,7 @@ For decades, industrial networks lived behind air gaps and Modbus's lack of auth
The moment you connect to external networks, Modbus's plaintext communication and zero authentication become indefensible. An attacker with network access can send arbitrary commands to any Modbus device. No password, no certificate, no audit trail.
-[OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) provides TLS encryption, certificate-based authentication, role-based access control, and detailed audit logging. [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/) with [Sparkplug B](/blog/2024/08/using-mqtt-sparkplugb-with-node-red/) adds lightweight security for IIoT deployments. These aren't nice-to-have features when you're connecting critical infrastructure to the internet: they're requirements. Companies implementing Industry 4.0 initiatives, remote operations, or cloud-based analytics cannot build on [Modbus](/node-red/protocol/modbus/). The protocol has no security model to extend.
+[OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) provides TLS encryption, certificate-based authentication, role-based access control, and detailed audit logging. [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/) with [Sparkplug B](/blog/2024/08/using-mqtt-sparkplugb-with-node-red/) adds lightweight security for IIoT deployments. These aren't nice-to-have features when you're connecting critical infrastructure to the internet: they're requirements. Companies implementing Industry 4.0 initiatives, remote operations, or cloud-based analytics cannot build on [Modbus](/docs/node-red/protocol/modbus/). The protocol has no security model to extend.
Modbus RTU at 115.2 kbaud can theoretically handle around 80-100 transactions per second under ideal conditions, but real-world installations see more like 40-60 due to device processing time and network overhead. That's fine for a few dozen devices with slow-changing process variables.
diff --git a/src/blog/2026/02/edge-ai-is-80-percent-pipeline-and-20-percent-ai.md b/src/blog/2026/02/edge-ai-is-80-percent-pipeline-and-20-percent-ai.md
index 7460503941..cdf2302c5f 100644
--- a/src/blog/2026/02/edge-ai-is-80-percent-pipeline-and-20-percent-ai.md
+++ b/src/blog/2026/02/edge-ai-is-80-percent-pipeline-and-20-percent-ai.md
@@ -54,7 +54,7 @@ Take what happens when you want to put a model in production. You have a data sc
In most deployments, nobody has a good answer to any of those questions. The model ends up in a container somewhere that only the data scientist understands, connected to the plant by a fragile handshake that no one wants to touch. The OT team treats it like a black box because it is a black box.
-[FlowFuse's ONNX nodes](/node-red/flowfuse/ai/onxx/) change that by putting the model where OT engineers already work. You train, you export, you deploy it as a node in a flow, alongside the Modbus reads, the historian writes, the MQTT publishes. The inference runs locally, on the edge device, no cloud round trip, no latency the line cannot afford. When we [deployed a motor anomaly detector this way](/blog/2026/02/motor-anomaly-detector-ai/), the thing that changed was not the model's accuracy. It was that the people running the line could see what the model was looking at, wire its output to the control logic themselves, and update it through the same pipeline they use for everything else. That is not a convenience improvement. That is the difference between a model that gets maintained and a model that gets abandoned.
+[FlowFuse's ONNX nodes](/docs/flowfuse-nodes/ai/onxx/) change that by putting the model where OT engineers already work. You train, you export, you deploy it as a node in a flow, alongside the Modbus reads, the historian writes, the MQTT publishes. The inference runs locally, on the edge device, no cloud round trip, no latency the line cannot afford. When we [deployed a motor anomaly detector this way](/blog/2026/02/motor-anomaly-detector-ai/), the thing that changed was not the model's accuracy. It was that the people running the line could see what the model was looking at, wire its output to the control logic themselves, and update it through the same pipeline they use for everything else. That is not a convenience improvement. That is the difference between a model that gets maintained and a model that gets abandoned.
The same logic applies to the [FlowFuse Expert](/docs/user/expert/). OT engineers are not waiting for JavaScript fluency. They know the equipment; they know what they need the flow to do; they just get slowed down in the translation between that knowledge and working code. The Expert handles the boilerplate, autocompletes flows, generates function node logic from a plain-language description, explains what a set of nodes does in terms that make sense. It is not a general-purpose chatbot bolted onto an IDE. It was trained on Node-RED and FlowFuse specifically, which means it gives answers that work in industrial contexts rather than answers that look plausible until you try to run them. For teams where the backlog of integration work is longer than the list of people who can do it, that matters.
diff --git a/src/blog/2026/02/mapping-mtconnect-streams.md b/src/blog/2026/02/mapping-mtconnect-streams.md
index 6ae476c224..f2089f7377 100644
--- a/src/blog/2026/02/mapping-mtconnect-streams.md
+++ b/src/blog/2026/02/mapping-mtconnect-streams.md
@@ -75,7 +75,7 @@ Bringing MTConnect data into FlowFuse is the first step toward a live dashboard.
The Solution Engine node (`node-red-contrib-solution-engine`) makes this straightforward because it lets you access any data point directly by its dataItemId, without having to worry about parsing XML or navigating nested structures.
-You can install the node by following the instructions in the FlowFuse documentation: [Using the Palette Manager](/node-red/getting-started/library/#using-the-palette-manager).
+You can install the node by following the instructions in the FlowFuse documentation: [Using the Palette Manager](/docs/node-red/getting-started/library/#using-the-palette-manager).
Once installed, follow these steps to start collecting data:
diff --git a/src/blog/2026/02/motor-anomaly-detector-ai.md b/src/blog/2026/02/motor-anomaly-detector-ai.md
index 09fe3ecc34..85cb178f2f 100644
--- a/src/blog/2026/02/motor-anomaly-detector-ai.md
+++ b/src/blog/2026/02/motor-anomaly-detector-ai.md
@@ -429,7 +429,7 @@ The flow has five stages: receive the payload, extract features, scale and prepa
Add an **mqtt-in** node and configure it to connect to the same broker and topic used during training. Set the output to auto-detect so the JSON payload is parsed automatically.
-If you are using the built-in FlowFuse MQTT broker, use the [FlowFuse MQTT nodes](/node-red/flowfuse/mqtt/) , these connect automatically when dragged into the flow.
+If you are using the built-in FlowFuse MQTT broker, use the [FlowFuse MQTT nodes](/docs/flowfuse-nodes/mqtt/) , these connect automatically when dragged into the flow.
**2. Extract Features**
@@ -548,7 +548,7 @@ Once deployed, the flow should look like this:
**5. Act on the Result**
-Connect the scoring output to whatever suits your operation. For testing, a debug node shows results in real time. For production, an mqtt-out node can publish anomaly alerts downstream, the [FlowFuse Dashboard](/platform/dashboard/) package can visualise the anomaly score over time with a clear motor state indicator, and alerting nodes can notify your team directly, via [Telegram](/node-red/notification/email/), [email](/node-red/notification/telegram/), or [SIGNL4](/blueprints/other/mobile-alerting/) for structured mobile alerts with on-call scheduling and acknowledgement tracking.
+Connect the scoring output to whatever suits your operation. For testing, a debug node shows results in real time. For production, an mqtt-out node can publish anomaly alerts downstream, the [FlowFuse Dashboard](/platform/dashboard/) package can visualise the anomaly score over time with a clear motor state indicator, and alerting nodes can notify your team directly, via [Telegram](/docs/node-red/notification/email/), [email](/docs/node-red/notification/telegram/), or [SIGNL4](/blueprints/other/mobile-alerting/) for structured mobile alerts with on-call scheduling and acknowledgement tracking.
### What the Output Looks Like
diff --git a/src/blog/2026/02/mqtt-influxdb-tutorial.md b/src/blog/2026/02/mqtt-influxdb-tutorial.md
index 0278fe6d08..2c2de67ab8 100644
--- a/src/blog/2026/02/mqtt-influxdb-tutorial.md
+++ b/src/blog/2026/02/mqtt-influxdb-tutorial.md
@@ -80,7 +80,7 @@ This article takes a different approach. Using FlowFuse (the enterprise platform
Before you start, make sure you have the following in place.
- A running FlowFuse instance. If you don't have one yet, [sign up](https://app.flowfuse.com/account/create) to get started.
-- An MQTT broker. FlowFuse Pro and Enterprise include a [built-in broker](/docs/user/teambroker/), and the [MQTT nodes](/node-red/flowfuse/mqtt/) configure themselves automatically. If you are using an external broker, keep your host, port, and credentials handy.
+- An MQTT broker. FlowFuse Pro and Enterprise include a [built-in broker](/docs/user/teambroker/), and the [MQTT nodes](/docs/flowfuse-nodes/mqtt/) configure themselves automatically. If you are using an external broker, keep your host, port, and credentials handy.
- A running InfluxDB instance, either local or on InfluxDB Cloud. Keep your URL, token, organization, and bucket name handy.
## Building the Pipeline
diff --git a/src/blog/2026/02/shop-floor-to-ai-signals-context-decisions.md b/src/blog/2026/02/shop-floor-to-ai-signals-context-decisions.md
index de02b91fc9..948bdf92f0 100644
--- a/src/blog/2026/02/shop-floor-to-ai-signals-context-decisions.md
+++ b/src/blog/2026/02/shop-floor-to-ai-signals-context-decisions.md
@@ -129,7 +129,7 @@ Crucially, in a Unified Namespace, context is added at the moment data enters th
That enriched information is then published into a shared MQTT-based Namespace. One location. One structure. One source of truth. Dashboards, analytics, and AI systems all subscribe to the same contextualized view of reality.
-Through [FlowFuse MCP nodes](/node-red/flowfuse/mcp/), AI systems connect directly to the namespace, querying live operational context instead of pulling raw time-series data from isolated historians and attempting to reconstruct meaning after the fact.
+Through [FlowFuse MCP nodes](/docs/flowfuse-nodes/mcp/), AI systems connect directly to the namespace, querying live operational context instead of pulling raw time-series data from isolated historians and attempting to reconstruct meaning after the fact.
[FlowFuse AI Expert](/ai/) operates on the same MCP-backed context layer. Operators and engineers can ask questions in natural language (*"Is Line 3 behaving normally?"*, *"Have we seen this vibration pattern before?"*, *"What changed before the last failure?"*) and receive answers grounded in the live Unified Namespace.
diff --git a/src/blog/2026/04/diagnosing-modbus-degradation.md b/src/blog/2026/04/diagnosing-modbus-degradation.md
index dddbd9319e..a444834930 100644
--- a/src/blog/2026/04/diagnosing-modbus-degradation.md
+++ b/src/blog/2026/04/diagnosing-modbus-degradation.md
@@ -144,7 +144,7 @@ The four metrics worth tracking continuously are transaction success rate, respo
### Putting it into practice
-Instrument your polling layer to write a timestamped record on every transaction: device address, function code, success or failure, response time in milliseconds, exception code on failures, and error type (timeout vs. CRC vs. exception response). Write those records to a [time-series store](/node-red/database/). [InfluxDB](/node-red/database/influxdb/) is a common choice for industrial deployments; a [PostgreSQL](/blog/2025/08/getting-started-with-flowfuse-tables/) table with a timestamp index works fine too.
+Instrument your polling layer to write a timestamped record on every transaction: device address, function code, success or failure, response time in milliseconds, exception code on failures, and error type (timeout vs. CRC vs. exception response). Write those records to a [time-series store](/docs/node-red/database/). [InfluxDB](/docs/node-red/database/influxdb/) is a common choice for industrial deployments; a [PostgreSQL](/blog/2025/08/getting-started-with-flowfuse-tables/) table with a timestamp index works fine too.
A reasonable retention strategy is to keep raw transaction records for 7 days and roll up to hourly aggregates (per-device success rate, median response time, CRC error count) for 90 days of trend data.
diff --git a/src/blog/2026/06/event-driven-downtime-escalation-workflow.md b/src/blog/2026/06/event-driven-downtime-escalation-workflow.md
index f5a4ac0a0b..10df193f88 100644
--- a/src/blog/2026/06/event-driven-downtime-escalation-workflow.md
+++ b/src/blog/2026/06/event-driven-downtime-escalation-workflow.md
@@ -81,11 +81,11 @@ flowchart TD
Here's what that looks like built in [FlowFuse](/):
-- **Catch the stop signal:** Most PLCs expose machine state through [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) or [Modbus](/node-red/protocol/modbus/), and FlowFuse has nodes for both. Point one at the right tag, and the moment the state flips to stopped, it lands in your flow as a timestamped message.
+- **Catch the stop signal:** Most PLCs expose machine state through [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua/) or [Modbus](/docs/node-red/protocol/modbus/), and FlowFuse has nodes for both. Point one at the right tag, and the moment the state flips to stopped, it lands in your flow as a timestamped message.
- **Track how long it's been down:** A couple of [timer nodes](/blog/2025/12/node-red-timer/) mark the passage of time: past two minutes, past ten, whatever windows fit your line.
-- **Branch by severity:** A switch node routes the message: short stops go straight to a [database](/blog/2025/08/getting-started-with-flowfuse-tables/); longer ones also notify the supervisor over [email](/node-red/notification/email/) or [Telegram](/node-red/notification/telegram/); and if it's still unresolved at the next threshold, maintenance gets the same message, escalating further up if needed.
+- **Branch by severity:** A switch node routes the message: short stops go straight to a [database](/blog/2025/08/getting-started-with-flowfuse-tables/); longer ones also notify the supervisor over [email](/docs/node-red/notification/email/) or [Telegram](/docs/node-red/notification/telegram/); and if it's still unresolved at the next threshold, maintenance gets the same message, escalating further up if needed.
- **Close the record:** When the "running" message comes through, a final node writes the resolution time back into that record: start, every escalation, and end, all filled in by the flow itself.
diff --git a/src/blog/2026/06/flowfuse-release-2-31.md b/src/blog/2026/06/flowfuse-release-2-31.md
index c253ba0e4c..5d164686af 100644
--- a/src/blog/2026/06/flowfuse-release-2-31.md
+++ b/src/blog/2026/06/flowfuse-release-2-31.md
@@ -51,7 +51,7 @@ FlowFuse now offers certified nodes: vetted, FlowFuse-supported nodes you can ad
- Gemini
- Ollama, for models you run yourself
- These first LLM nodes handle single-shot, text-in/text-out calls; see the [LLM nodes documentation](/node-red/flowfuse/ai/llm-nodes/) for details. Multimodal input, conversation history, and tool calling are planned for follow-up iterations. They join the FlowFuse AI Nodes package we [shipped in 2.23](/changelog/2025/10/onnx-nodes/), which already includes the ONNX Inference, Image Classification, Object Detection, and Image Depth Estimation nodes for running vision and custom models on-device, with no external API calls.
+ These first LLM nodes handle single-shot, text-in/text-out calls; see the [LLM nodes documentation](/docs/flowfuse-nodes/ai/llm-nodes/) for details. Multimodal input, conversation history, and tool calling are planned for follow-up iterations. They join the FlowFuse AI Nodes package we [shipped in 2.23](/changelog/2025/10/onnx-nodes/), which already includes the ONNX Inference, Image Classification, Object Detection, and Image Depth Estimation nodes for running vision and custom models on-device, with no external API calls.
Certified Nodes are available to FlowFuse Cloud customers as of this release, with Self-Hosted Enterprise support arriving in the next release (2.32). [Get in touch with sales](/contact-us/?subject=Certified%20Nodes) or your customer success manager, and we'll enable the ones your team needs.
diff --git a/src/blog/2026/06/opcua-to-influxdb.md b/src/blog/2026/06/opcua-to-influxdb.md
index 94db9b0f6d..fd23281160 100644
--- a/src/blog/2026/06/opcua-to-influxdb.md
+++ b/src/blog/2026/06/opcua-to-influxdb.md
@@ -90,7 +90,7 @@ You'll install two packages: the InfluxDB nodes and the FlowFuse Edge Certified
2. From the menu (top right), select **Manage palette**, then switch to the **Install** tab.
3. Search for **`node-red-contrib-influxdb`** and click **Install**. These nodes write to and query InfluxDB.
4. Switch the catalog using the top dropdown to **FlowFuse Edge Certified Nodes**. Once sales enables FlowFuse Edge Certified Nodes for your team, this catalog shows up here; restart any existing instance so it picks up the updated catalogue.
-5. Search for **`@flowfuse-certified-nodes/opcua`** and click **Install**. See the [OPC UA node documentation](/node-red/flowfuse/edge/opcua/) for the full node set and configuration options.
+5. Search for **`@flowfuse-certified-nodes/opcua`** and click **Install**. See the [OPC UA node documentation](/docs/flowfuse-nodes/edge/opcua/) for the full node set and configuration options.

_Install the OPC UA certified package from the FlowFuse Edge Certified Nodes catalog._
diff --git a/src/blog/2026/06/process-rtsp-camera-feeds-at-the-edge.md b/src/blog/2026/06/process-rtsp-camera-feeds-at-the-edge.md
index cb779b559d..0f0e668d5d 100644
--- a/src/blog/2026/06/process-rtsp-camera-feeds-at-the-edge.md
+++ b/src/blog/2026/06/process-rtsp-camera-feeds-at-the-edge.md
@@ -155,7 +155,7 @@ That's a live line view anyone can pull up in a browser, with no NVR login and n
A live view is a real win, but notice what you have now: the camera's output is a PNG buffer moving through your flow, one message per frame. Once a frame is just another message, you can do more than display it. You can ask what's in it.
-That's what the [**FlowFuse AI** nodes](/node-red/flowfuse/ai/) are for. They run vision models locally, inside your flow, with nothing sent to an outside service. The **Object Detection** node takes a PNG buffer as its input, which is exactly what the camera node outputs, so you wire the camera straight into it, no conversion step in between. From there the flow stops watching and starts acting: counting material on the conveyor, flagging a person near the flotation cells, or catching a stopped belt before the line backs up. Each detection comes back as structured data, a label, a confidence score, and a position, which you handle like any other signal in FlowFuse.
+That's what the [**FlowFuse AI** nodes](/docs/flowfuse-nodes/ai/) are for. They run vision models locally, inside your flow, with nothing sent to an outside service. The **Object Detection** node takes a PNG buffer as its input, which is exactly what the camera node outputs, so you wire the camera straight into it, no conversion step in between. From there the flow stops watching and starts acting: counting material on the conveyor, flagging a person near the flotation cells, or catching a stopped belt before the line backs up. Each detection comes back as structured data, a label, a confidence score, and a position, which you handle like any other signal in FlowFuse.
## Recording frames to disk
diff --git a/src/blog/2026/07/calibration-management-dashboard.md b/src/blog/2026/07/calibration-management-dashboard.md
index 08ace58802..0b3a2a9c4c 100644
--- a/src/blog/2026/07/calibration-management-dashboard.md
+++ b/src/blog/2026/07/calibration-management-dashboard.md
@@ -380,7 +380,7 @@ A dashboard in the quality office doesn't reach the person about to pick up a to
4. Add a `simple-ocr` node, then a `link out` / `link in` pair to carry the result down to the next row of the canvas.
-> **Tip:** OCR keeps this tutorial hardware-free, but if your labels have a barcode or QR code, scanning one is faster and far more reliable than reading printed text. Swap the camera and OCR nodes for a [barcode scanner](/node-red/peripheral/barcodescanner/) and feed the decoded ID straight into "Set Tool ID," and everything downstream will keep working. You can also drop "Extract Tool ID" and "Scan Valid?", since a scanner either returns an ID or nothing.
+> **Tip:** OCR keeps this tutorial hardware-free, but if your labels have a barcode or QR code, scanning one is faster and far more reliable than reading printed text. Swap the camera and OCR nodes for a [barcode scanner](/docs/node-red/peripheral/barcodescanner/) and feed the decoded ID straight into "Set Tool ID," and everything downstream will keep working. You can also drop "Extract Tool ID" and "Scan Valid?", since a scanner either returns an ID or nothing.
5. Add a `function` node named "Extract Tool ID":
@@ -547,4 +547,4 @@ Deploy and open `/tool-check` on a device with a camera. Hold a label reading `T
You've built a calibration application that answers two different questions from the same data. The office screen tells a quality engineer how the plant stands and what needs collecting this week. The station screen tells an operator whether the tool in their hand is fit to use. Both read the due date, so neither can drift from the other.
-Right now it runs on generated data. To go live, remove the simulator flow and point the queries at your own register. Just alias your column names in the `SELECT` lists, and everything downstream keeps working. If your records sit in a CMMS or ERP behind an API, swap the query nodes for `http request` nodes and nothing else changes. From there, the obvious next steps are ones the register already supports: email the overdue list to the calibration lab each Monday, or [notify](/node-red/notification/) someone the moment a critical gauge goes overdue instead of waiting for a screen to be looked at. The same approach works for [defect tracking](/blog/2026/07/defect-and-quality-monitoring/) and [downtime](/blog/2026/07/build-downtime-logger/) too, and for the other [manufacturing dashboards](/blog/2026/08/manufacturing-dashboard-examples/) teams build on the same data. It also pairs with floor-level checks such as a [layered process audit](/blog/2026/08/layered-process-audit/), where a tool's calibration status is exactly the kind of item this dashboard can hand the auditor an answer for instead of a lookup. See how manufacturers are using it on our [automotive solutions page](/industries/automotive/).
+Right now it runs on generated data. To go live, remove the simulator flow and point the queries at your own register. Just alias your column names in the `SELECT` lists, and everything downstream keeps working. If your records sit in a CMMS or ERP behind an API, swap the query nodes for `http request` nodes and nothing else changes. From there, the obvious next steps are ones the register already supports: email the overdue list to the calibration lab each Monday, or [notify](/docs/node-red/notification/) someone the moment a critical gauge goes overdue instead of waiting for a screen to be looked at. The same approach works for [defect tracking](/blog/2026/07/defect-and-quality-monitoring/) and [downtime](/blog/2026/07/build-downtime-logger/) too, and for the other [manufacturing dashboards](/blog/2026/08/manufacturing-dashboard-examples/) teams build on the same data. It also pairs with floor-level checks such as a [layered process audit](/blog/2026/08/layered-process-audit/), where a tool's calibration status is exactly the kind of item this dashboard can hand the auditor an answer for instead of a lookup. See how manufacturers are using it on our [automotive solutions page](/industries/automotive/).
diff --git a/src/blog/2026/07/defect-and-quality-monitoring.md b/src/blog/2026/07/defect-and-quality-monitoring.md
index 7d41229ba2..c62799eb98 100644
--- a/src/blog/2026/07/defect-and-quality-monitoring.md
+++ b/src/blog/2026/07/defect-and-quality-monitoring.md
@@ -409,6 +409,6 @@ Deploy and open the dashboard. Every widget populates from the seeded data at on
You've built a working quality dashboard: a `defects` table, a single query that computes every KPI in one pass, and a page of stat cards, a Pareto chart, trend and breakdown charts, an SLA table, and a status funnel, all filtering live by line, shift, and date.
-Right now it runs on the simulator, but that was only ever a stand-in for your real data. To go live, remove the simulator flow and point the query at your own `defects` table. Everything downstream keeps working, because the dashboard only ever reads from that one query. Your defects don't live in PostgreSQL? That's fine too. FlowFuse connects to MySQL, MongoDB, InfluxDB, and more, as our [database integration guides](/node-red/database/) show.
+Right now it runs on the simulator, but that was only ever a stand-in for your real data. To go live, remove the simulator flow and point the query at your own `defects` table. Everything downstream keeps working, because the dashboard only ever reads from that one query. Your defects don't live in PostgreSQL? That's fine too. FlowFuse connects to MySQL, MongoDB, InfluxDB, and more, as our [database integration guides](/docs/node-red/database/) show.
That's the real point. FlowFuse lets you build the exact application your floor needs quickly, without deep engineering knowledge or writing code, wired to the systems you already run instead of forcing your process to fit a fixed tool. This tutorial happened to build defect tracking, but the same approach covers the full range of [manufacturing dashboards](/blog/2026/08/manufacturing-dashboard-examples/), production monitoring, OEE, and the wider quality picture. See how manufacturers are already putting it to work on our [automotive solutions page](/industries/automotive/).
diff --git a/src/blog/2026/08/layered-process-audit.md b/src/blog/2026/08/layered-process-audit.md
index 51b2dae741..f3ed643d23 100644
--- a/src/blog/2026/08/layered-process-audit.md
+++ b/src/blog/2026/08/layered-process-audit.md
@@ -141,7 +141,7 @@ Manufacturers can start an LPA program with paper forms or spreadsheets, but man
A digital LPA can help schedule audits, record findings, notify responsible people, and track actions through closure.
-Connecting the audit with production data provides another benefit. With FlowFuse, manufacturers can connect an LPA application to machines, [PLCs](/landing/plc/), sensors, [databases](/node-red/database/), and other industrial systems.
+Connecting the audit with production data provides another benefit. With FlowFuse, manufacturers can connect an LPA application to machines, [PLCs](/landing/plc/), sensors, [databases](/docs/node-red/database/), and other industrial systems.
This allows audit results to be viewed alongside production information such as downtime, machine states, or process parameters. Instead of only recording that a process failed, teams can investigate what was happening around the failure.
diff --git a/src/blog/2026/08/what-is-scada.md b/src/blog/2026/08/what-is-scada.md
index 3afa47f34d..4d3112adff 100644
--- a/src/blog/2026/08/what-is-scada.md
+++ b/src/blog/2026/08/what-is-scada.md
@@ -62,7 +62,7 @@ Programmable Logic Controllers and Remote Terminal Units take the raw signals fr
### Communication Networks
-Communication networks carry data between field devices, controllers, and the central SCADA software, using protocols like [Modbus](/node-red/protocol/modbus/), [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua), [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), or [Ethernet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/) depending on the equipment and environment. This layer determines how reliably and securely data moves across a facility, and it becomes especially important when connecting older equipment to newer IT/OT platforms.
+Communication networks carry data between field devices, controllers, and the central SCADA software, using protocols like [Modbus](/docs/node-red/protocol/modbus/), [OPC UA](/blog/2025/07/reading-and-writing-plc-data-using-opc-ua), [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/), or [Ethernet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/) depending on the equipment and environment. This layer determines how reliably and securely data moves across a facility, and it becomes especially important when connecting older equipment to newer IT/OT platforms.
### HMI And Central Monitoring Software
diff --git a/src/blog/2026/09/industrial-ai-agent.md b/src/blog/2026/09/industrial-ai-agent.md
index 495a79aedd..2005ea3f49 100644
--- a/src/blog/2026/09/industrial-ai-agent.md
+++ b/src/blog/2026/09/industrial-ai-agent.md
@@ -73,7 +73,7 @@ Ask why they don't use the FlowFuse Expert built into the platform, and the answ
FlowFuse now acts as an MCP server. Your own AI agent connects to it as a client and because the AI agent is yours, so is the choice of model it uses.
-That means the AI agent your company already approved can work the platform directly: look at your teams and applications, check what your instances are doing, read runtime logs, query your [FlowFuse Tables](/node-red/flowfuse/flowfuse-tables/) data, create applications and instances, and build and edit the flows inside your instances.
+That means the AI agent your company already approved can work the platform directly: look at your teams and applications, check what your instances are doing, read runtime logs, query your [FlowFuse Tables](/docs/flowfuse-nodes/flowfuse-tables/) data, create applications and instances, and build and edit the flows inside your instances.
## How an AI agent connects to FlowFuse
diff --git a/src/changelog/2026/01/mcp-rbacs.md b/src/changelog/2026/01/mcp-rbacs.md
index f19a69a4c8..236cecf0af 100644
--- a/src/changelog/2026/01/mcp-rbacs.md
+++ b/src/changelog/2026/01/mcp-rbacs.md
@@ -1,34 +1,34 @@
----
-title: "FlowFuse Expert: MCP-Powered Insights with RBACs"
-description: "You can now limit which user roles see which Model Context Protocol (MCP) tools when querying your MCP servers with the FlowFuse Expert."
+---
+title: "FlowFuse Expert: MCP-Powered Insights with RBACs"
+description: "You can now limit which user roles see which Model Context Protocol (MCP) tools when querying your MCP servers with the FlowFuse Expert."
date: 2026-01-14 13:00:00.0
-release: "2.26"
-authors: ['steve-mclaughlin']
-tags:
- - changelog
----
-
-Following on the the introduction of [FlowFuse Expert MCP-Powered Insights](/changelog/2025/12/ff-expert-mcp-insights/) we have added annotations to the FlowFuse MCP nodes and linked them up with the FlowFuse roles.
-This permits a level of control over who can access what. This is just a first step, we will be working in the area over the next few iterations.
-
-### MCP Tools Node
-
-To facilitate a level of role based access control in the Expert, we have leveraged the new Granular RBACs and MCP annotations to introduce 2 means of filtering and control:
-1. By [application](/docs/user/concepts/#application) - as introduced in FlowFuse 1.5
-2. By pre-defined role level mapping to the annotation hints. For instance, users with a 'Viewer' role will only be exposed to tools marked with the Read Only hint, while Destructive tools are reserved for 'Owners'. The screenshot below indicates more clearly what this mapping is.
-
-To facilitate this, we have the next version of our [MCP Server Nodes](/node-red/flowfuse/mcp/) will introduce the 4 MCP standard annotations:
-
-- **Read Only Hint**: Lets the MCP Client know that the tool is read-only and does not modify any data or state. This hint can be used by LLMs to understand that invoking this tool will not have side effects, making it safe for exploratory queries or information retrieval.
-- **Destructive Hint**: Lets the MCP Client know that the tool performs destructive actions that may modify or delete data. This hint can be used by LLMs to exercise caution when invoking this tool, as it may have irreversible effects.
-- **Idempotent Hint**: Lets the MCP Client know that the tool is idempotent, meaning that multiple invocations with the same parameters will have the same effect as a single invocation. This hint can be used by LLMs to understand that it is safe to retry or repeat calls to this tool without causing unintended side effects.
-- **Open World Hint**: Lets the MCP Client know that the tool operates in an open-world context, meaning it may interact with external systems or data sources beyond the immediate environment. This hint can be used by LLMs to understand that invoking this tool may involve uncertainties or dependencies on external factors.
-
-These annotations are not exclusive to FlowFuse or FlowFuse Roles, they also are useful for your own Agents and LLMs.
-
-_Note: Hints do not enforce behavior. The actual behavior of the tool depends on how it is used in your flows_
-
-{data-zoomable}
-_MCP Server Tool Node with new annotations_
-
-_Note: This feature is currently in Beta. We are actively expanding these capabilities and would love to hear how you are using MCP to extend your systems._
+release: "2.26"
+authors: ['steve-mclaughlin']
+tags:
+ - changelog
+---
+
+Following on the the introduction of [FlowFuse Expert MCP-Powered Insights](/changelog/2025/12/ff-expert-mcp-insights/) we have added annotations to the FlowFuse MCP nodes and linked them up with the FlowFuse roles.
+This permits a level of control over who can access what. This is just a first step, we will be working in the area over the next few iterations.
+
+### MCP Tools Node
+
+To facilitate a level of role based access control in the Expert, we have leveraged the new Granular RBACs and MCP annotations to introduce 2 means of filtering and control:
+1. By [application](/docs/user/concepts/#application) - as introduced in FlowFuse 1.5
+2. By pre-defined role level mapping to the annotation hints. For instance, users with a 'Viewer' role will only be exposed to tools marked with the Read Only hint, while Destructive tools are reserved for 'Owners'. The screenshot below indicates more clearly what this mapping is.
+
+To facilitate this, we have the next version of our [MCP Server Nodes](/docs/flowfuse-nodes/mcp/) will introduce the 4 MCP standard annotations:
+
+- **Read Only Hint**: Lets the MCP Client know that the tool is read-only and does not modify any data or state. This hint can be used by LLMs to understand that invoking this tool will not have side effects, making it safe for exploratory queries or information retrieval.
+- **Destructive Hint**: Lets the MCP Client know that the tool performs destructive actions that may modify or delete data. This hint can be used by LLMs to exercise caution when invoking this tool, as it may have irreversible effects.
+- **Idempotent Hint**: Lets the MCP Client know that the tool is idempotent, meaning that multiple invocations with the same parameters will have the same effect as a single invocation. This hint can be used by LLMs to understand that it is safe to retry or repeat calls to this tool without causing unintended side effects.
+- **Open World Hint**: Lets the MCP Client know that the tool operates in an open-world context, meaning it may interact with external systems or data sources beyond the immediate environment. This hint can be used by LLMs to understand that invoking this tool may involve uncertainties or dependencies on external factors.
+
+These annotations are not exclusive to FlowFuse or FlowFuse Roles, they also are useful for your own Agents and LLMs.
+
+_Note: Hints do not enforce behavior. The actual behavior of the tool depends on how it is used in your flows_
+
+{data-zoomable}
+_MCP Server Tool Node with new annotations_
+
+_Note: This feature is currently in Beta. We are actively expanding these capabilities and would love to hear how you are using MCP to extend your systems._
diff --git a/src/customer-stories/aperia-technologies-plc-replacement.md b/src/customer-stories/aperia-technologies-plc-replacement.md
index 00ea20c094..e3e27c01b9 100644
--- a/src/customer-stories/aperia-technologies-plc-replacement.md
+++ b/src/customer-stories/aperia-technologies-plc-replacement.md
@@ -54,7 +54,7 @@ This manual overhead was limiting Aperia's ability to scale manufacturing operat
## The FlowFuse Solution
-Aperia's answer was to remove the proprietary PLC from the center of the architecture entirely. Instead, smart fixtures run Node-RED on an edge Windows instance, managed by FlowFuse. At the hardware layer, Node-RED talks directly to sensors, actuators, scanners, and motors using standard industrial protocols: [Modbus TCP](/node-red/protocol/modbus/)/[RTU](/blog/2025/09/using-modbus-with-flowfuse/), [RS232](/blog/2025/07/connect-legacy-equipment-serial-flowfuse/), [raw TCP](/node-red/core-nodes/tcp-in/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/). At the software layer, it triggers label printing, logs serialized telemetry to [MongoDB](/node-red/database/mongodb/), syncs maintenance events to Limble, and pulls data from NetSuite ERP. [FlowFuse functions as the orchestration layer](/use-cases/it-ot-middleware/) that ties hardware protocols and enterprise APIs into one canvas, through two strategic implementations:
+Aperia's answer was to remove the proprietary PLC from the center of the architecture entirely. Instead, smart fixtures run Node-RED on an edge Windows instance, managed by FlowFuse. At the hardware layer, Node-RED talks directly to sensors, actuators, scanners, and motors using standard industrial protocols: [Modbus TCP](/docs/node-red/protocol/modbus/)/[RTU](/blog/2025/09/using-modbus-with-flowfuse/), [RS232](/blog/2025/07/connect-legacy-equipment-serial-flowfuse/), [raw TCP](/docs/node-red/core-nodes/network/tcp-in/), and [EtherNet/IP](/blog/2025/10/using-ethernet-ip-with-flowfuse/). At the software layer, it triggers label printing, logs serialized telemetry to [MongoDB](/docs/node-red/database/mongodb/), syncs maintenance events to Limble, and pulls data from NetSuite ERP. [FlowFuse functions as the orchestration layer](/use-cases/it-ot-middleware/) that ties hardware protocols and enterprise APIs into one canvas, through two strategic implementations:
### Turning Idle Test Equipment into R&D Capacity
@@ -88,7 +88,7 @@ Aperia's solution was a vision-integrated screw assembly station connected to th
The solution architecture includes:
- **Edge Control Layer:** Node-RED running on edge Windows instances, managed by FlowFuse, in place of proprietary PLC logic
- - [**Industrial Protocol Support**](/node-red/protocol/)**:** Modbus TCP/RTU, RS232, raw TCP, and EtherNet/IP for direct communication with sensors, actuators, scanners, and motors
+ - [**Industrial Protocol Support**](/docs/node-red/protocol/)**:** Modbus TCP/RTU, RS232, raw TCP, and EtherNet/IP for direct communication with sensors, actuators, scanners, and motors
- **Enterprise System Integration:** MongoDB for serialized telemetry, DronaHQ for dashboards, NetSuite for ERP data, and Limble for maintenance event syncing
- **Alerting:** Slack API integration for instant anomaly and downtime alerts
- **Deployment Management:** FlowFuse pipelines for pushing device configuration updates to full device groups across the factory floor
diff --git a/src/customer-stories/energinet-streamlining-critical-infrastructure-data-management.md b/src/customer-stories/energinet-streamlining-critical-infrastructure-data-management.md
index 87d967918e..0451c57ee2 100644
--- a/src/customer-stories/energinet-streamlining-critical-infrastructure-data-management.md
+++ b/src/customer-stories/energinet-streamlining-critical-infrastructure-data-management.md
@@ -70,8 +70,8 @@ FlowFuse serves as a production infrastructure connecting Energinet's operationa
### Operational System Delivery:
-- Time-Series Analytics: Governed delivery to [InfluxDB](/node-red/database/influxdb/) databases supporting trend analysis, predictive maintenance, and renewable integration planning
-- Operational Databases: Structured routing to [MySQL](/node-red/database/mysql/) systems for compliance reporting and operational record-keeping
+- Time-Series Analytics: Governed delivery to [InfluxDB](/docs/node-red/database/influxdb/) databases supporting trend analysis, predictive maintenance, and renewable integration planning
+- Operational Databases: Structured routing to [MySQL](/docs/node-red/database/mysql/) systems for compliance reporting and operational record-keeping
- Real-Time Monitoring: Live data feeds to Grafana visualization platforms enabling 24/7 grid surveillance and incident response
### Enterprise Governance Meeting TSO Standards
diff --git a/src/customer-stories/leveraging-node-red-and-flowfuse-to-automate-precision-manufacturing.md b/src/customer-stories/leveraging-node-red-and-flowfuse-to-automate-precision-manufacturing.md
index 72cd575098..f015853e96 100644
--- a/src/customer-stories/leveraging-node-red-and-flowfuse-to-automate-precision-manufacturing.md
+++ b/src/customer-stories/leveraging-node-red-and-flowfuse-to-automate-precision-manufacturing.md
@@ -50,7 +50,7 @@ Manufacturing environments, particularly those involving electro-coating process
#### Hardware Challenges and Solutions
-Abrasive Technology initially utilized [Raspberry Pis](/node-red/hardware/raspberry-pi-4/) for hosting Node-RED instances, linking them to industrialized touch screens for [Human-Machine Interfaces (HMIs)](/blog/2025/11/building-hmi-for-equipment-control/). While Raspberry Pis proved reliable for many applications, certain projects pushed hardware capabilities. Dudley highlights: "I have found them to be very reliable, but on the current project, I'm absolutely bumping up against its hardware capabilities." The anticipation of the [Pi5](/node-red/hardware/raspberry-pi-5/), with enhanced capabilities, holds promise, and Dudley is eagerly awaiting its arrival.
+Abrasive Technology initially utilized [Raspberry Pis](/docs/node-red/hardware/raspberry-pi-4/) for hosting Node-RED instances, linking them to industrialized touch screens for [Human-Machine Interfaces (HMIs)](/blog/2025/11/building-hmi-for-equipment-control/). While Raspberry Pis proved reliable for many applications, certain projects pushed hardware capabilities. Dudley highlights: "I have found them to be very reliable, but on the current project, I'm absolutely bumping up against its hardware capabilities." The anticipation of the [Pi5](/docs/node-red/hardware/raspberry-pi-5/), with enhanced capabilities, holds promise, and Dudley is eagerly awaiting its arrival.
In addition to Raspberry Pis, Abrasive Technology currently operates a server running Node-RED locally alongside instances on FlowFuse. The company is actively transitioning its Node-RED instances from locally maintained servers to FlowFuse Cloud to make it easier to manage them. Dudley notes, "We also currently have a server Running Node-RED locally as well as instances on FlowFuse. Our search for a better way to host and manage our Node-RED instances is what started our transition to using FlowFuse."
diff --git a/src/customer-stories/leveraging-node-red-and-flowfuse-to-revolutionize-irrigation.md b/src/customer-stories/leveraging-node-red-and-flowfuse-to-revolutionize-irrigation.md
index 88898788d2..6f18882080 100644
--- a/src/customer-stories/leveraging-node-red-and-flowfuse-to-revolutionize-irrigation.md
+++ b/src/customer-stories/leveraging-node-red-and-flowfuse-to-revolutionize-irrigation.md
@@ -55,7 +55,7 @@ Recognizing the need for a technological overhaul, PIDD embraced Node-RED, a flo
#### Evolving Hardware Landscape
-Initially relying on [Raspberry Pi](/node-red/hardware/raspberry-pi-4/) devices, PIDD faced challenges related to heat, especially in Arizona's high-temperature environment. To address this, they decided to transition to [PLCs](/blog/2025/12/what-is-plc/), with the Groov EPIC system being the preferred choice for improved stability in industrial use.
+Initially relying on [Raspberry Pi](/docs/node-red/hardware/raspberry-pi-4/) devices, PIDD faced challenges related to heat, especially in Arizona's high-temperature environment. To address this, they decided to transition to [PLCs](/blog/2025/12/what-is-plc/), with the Groov EPIC system being the preferred choice for improved stability in industrial use.
#### Impact on Operations
@@ -69,7 +69,7 @@ The adoption of Node-RED and FlowFuse had a profound impact on PIDD's operations
PIDD's forward-thinking approach extends to their future plans:
- Transition to PLCs: The organization is moving towards PLCs, specifically the Groov EPIC system used by [Opto 22](/customer-stories/opto22-embraces-node-red/), for enhanced stability in challenging environmental conditions.
- Command and Control with Ignition: Consideration is given to using [Ignition](/vs/ignition/) for command and control, complemented by [MQTT](/blog/2024/06/how-to-use-mqtt-in-node-red/) for data communication.
-- Data Retention Strategy: PIDD aims to implement a robust data retention strategy, possibly involving relational databases like [MySQL](/node-red/database/mysql/) or [Postgres](/node-red/database/postgresql/), to store and retrieve historical data.
+- Data Retention Strategy: PIDD aims to implement a robust data retention strategy, possibly involving relational databases like [MySQL](/docs/node-red/database/mysql/) or [Postgres](/docs/node-red/database/postgresql/), to store and retrieve historical data.
#### Conclusion
diff --git a/src/customer-stories/opto22-embraces-node-red.md b/src/customer-stories/opto22-embraces-node-red.md
index 5c1f86d36a..355c7dc384 100644
--- a/src/customer-stories/opto22-embraces-node-red.md
+++ b/src/customer-stories/opto22-embraces-node-red.md
@@ -30,7 +30,7 @@ Opto 22 is a US-based industrial automation hardware and software manufacturer b
-Opto 22 has a history of innovation in the industrial hardware industry, being the first vendor to standardize on Ethernet and TCP/IP connections, being one of the original vendors behind the [OPC standard](/node-red/flowfuse/edge/opcua/), and participating in the steering committee of the more recent [Sparkplug standard](/blog/2024/08/using-mqtt-sparkplugb-with-node-red/).
+Opto 22 has a history of innovation in the industrial hardware industry, being the first vendor to standardize on Ethernet and TCP/IP connections, being one of the original vendors behind the [OPC standard](/docs/flowfuse-nodes/edge/opcua/), and participating in the steering committee of the more recent [Sparkplug standard](/blog/2024/08/using-mqtt-sparkplugb-with-node-red/).
In 2014, Opto 22 was introducing its first Linux-based hardware called the Opto groov Appliance. At this time, Benson Hougland, VP of Marketing and Product Strategy at Opto 22, and Ben Orchard, Application Engineer at Opto 22 saw a need to make it easier to connect Opto 22 hardware with other devices, sensors, and actuators, in addition to connecting with emerging data services in the cloud. Through lots of research and experimentation, they discovered Node-RED and found it a natural fit for process control engineers who were used to ‘programming’ with flowcharts and diagrams. When Opto 22 introduced its groov EPIC edge programmable industrial controller platform to market in 2018, Node-RED came pre-installed on the device.
@@ -42,9 +42,9 @@ Node-RED is being used by Opto 22 customers in a range of use cases. Some of the
1. **Collecting operational data and storing this data in a [SQL database](/use-cases/data-integration/)**. According to Hougland, ‘The ability to collect sensor data, control variables, etc., and store this data in a SQL database is very easy with Node-RED. There are other middleware solutions available but Node-RED makes it dead simple.’
2. **Accessing external data from the control system to make control decisions**. It is often the case that industrial equipment needs access to external data to make control system decisions. For example, weather data is used in lots of applications to determine the efficiency of machinery. Opto 22 has a customer that manages wind turbines in California. The electrical utility will charge a negative tariff if the turbines generate power for the grid when the grid is over-saturated. Therefore, the Opto 22 customer has deployed Opto groov hardware at each turbine that uses Node-RED to access, every 5 minutes, the spot price for the grid, to determine if the turbine should be generating power or not. The customer realized immediate ROI by reducing their negative tariff charges.
-3. **Creating alerts and notifications for industrial events**. Manufacturers often need to send alerts or notifications when a piece of equipment fails or needs servicing. Node-RED makes it very easy to send an alert or notification to any communication channel. Node-RED nodes are available for sending notifications via [email](/node-red/notification/email/), text, text-to-speech, Slack, changing stack lights, etc.
-4. **Reading [Modbus](/node-red/flowfuse/edge/modbus/) data.** Modbus is a widely used protocol for industrial devices that is supported on groov EPIC. Opto 22 customers are using Node-RED to transform Modbus registry data into human-readable, contextual data that can be used by other applications on the EPIC or sent to the [cloud for processing](/use-cases/data-integration/).
-5. **Bridging new equipment with legacy equipment.** Manufacturing plants have significant investments in legacy equipment that sometimes isn’t easy to access. This makes it difficult to introduce new technologies, like vision analytics, into a [manufacturing line](/use-cases/shop-floor-communication/). Opto 22 customer, [Intrinsics](https://opto22.com/products/groov-case-studies/case-study-intrinsics) wanted to improve their quality control using cameras and vision analytics. They added a [camera](/node-red/flowfuse/edge/rtsp/) to the manufacturing line that sent images directly to a cloud vision analytics service that evaluates a pass or fail. However, the [PLC](/blog/2025/12/what-is-plc/) controlling the line could not receive the pass/fall notification. Therefore, they added a groov Rio, running Node-RED that received the pass/fail message from the analytics service and was able to connect with the legacy PLC to forward the control decision.
+3. **Creating alerts and notifications for industrial events**. Manufacturers often need to send alerts or notifications when a piece of equipment fails or needs servicing. Node-RED makes it very easy to send an alert or notification to any communication channel. Node-RED nodes are available for sending notifications via [email](/docs/node-red/notification/email/), text, text-to-speech, Slack, changing stack lights, etc.
+4. **Reading [Modbus](/docs/flowfuse-nodes/edge/modbus/) data.** Modbus is a widely used protocol for industrial devices that is supported on groov EPIC. Opto 22 customers are using Node-RED to transform Modbus registry data into human-readable, contextual data that can be used by other applications on the EPIC or sent to the [cloud for processing](/use-cases/data-integration/).
+5. **Bridging new equipment with legacy equipment.** Manufacturing plants have significant investments in legacy equipment that sometimes isn’t easy to access. This makes it difficult to introduce new technologies, like vision analytics, into a [manufacturing line](/use-cases/shop-floor-communication/). Opto 22 customer, [Intrinsics](https://opto22.com/products/groov-case-studies/case-study-intrinsics) wanted to improve their quality control using cameras and vision analytics. They added a [camera](/docs/flowfuse-nodes/edge/rtsp/) to the manufacturing line that sent images directly to a cloud vision analytics service that evaluates a pass or fail. However, the [PLC](/blog/2025/12/what-is-plc/) controlling the line could not receive the pass/fall notification. Therefore, they added a groov Rio, running Node-RED that received the pass/fail message from the analytics service and was able to connect with the legacy PLC to forward the control decision.
‘Node-RED makes it so easy to extend and innovate on a hardware platform,’ comments Ben Orchard. ‘The industrial automation industry has a history of offering proprietary drivers to add functionality to a hardware platform. People are tired of this approach. Using Node-RED only requires that you have a web browser to get access to your data and put the data anywhere. It really promotes a lot of freedom and innovation. Node-RED’s open approach is definitely the present and the future for our industry.’
diff --git a/src/customer-stories/scaling-industrial-iot-operations-while-maintaining-competitive-edge.md b/src/customer-stories/scaling-industrial-iot-operations-while-maintaining-competitive-edge.md
index aa1db81743..bb83ce6205 100644
--- a/src/customer-stories/scaling-industrial-iot-operations-while-maintaining-competitive-edge.md
+++ b/src/customer-stories/scaling-industrial-iot-operations-while-maintaining-competitive-edge.md
@@ -55,7 +55,7 @@ FlowFuse processes and routes production data to multiple systems including:
- **[MES](/use-cases/mes/) Integration:** Providing real-time machine status, runtime data, and downtime analysis
- **SAP Connectivity:** Enabling bidirectional [data integration](/use-cases/data-integration/) for production planning and resource management
-- **[InfluxDB](/node-red/database/influxdb/) Storage:** Long-term historical data storage for trend analysis and optimization
+- **[InfluxDB](/docs/node-red/database/influxdb/) Storage:** Long-term historical data storage for trend analysis and optimization
- **Live Dashboards:** Real-time production visualization and monitoring for operators and management
- **Custom HMI Systems:** User interfaces for machine operators to input process parameters and quality data
- **SaaS Energy Management System:** Optenda collects power consumption of some machines directly from the FlowFuse Broker
@@ -91,7 +91,7 @@ FlowFuse processes and routes production data to multiple systems including:
The solution architecture includes:
-- **Device Agent Deployment:** Shop floor-level agents connecting directly to manufacturing equipment via [OPC-UA](/node-red/flowfuse/edge/opcua/) and other industrial protocols
+- **Device Agent Deployment:** Shop floor-level agents connecting directly to manufacturing equipment via [OPC-UA](/docs/flowfuse-nodes/edge/opcua/) and other industrial protocols
- **Encrypted Cloud Connectivity:** Secure communication between edge devices and FlowFuse cloud platform
- **Data Processing Pipelines:** Node-RED flows handling data transformation, validation, and routing to multiple downstream systems
- **Multi-System Integration:** Connections to MES, SAP, InfluxDB, custom dashboards, and HMI systems
diff --git a/src/customer-stories/stfi-future-of-textile-powered-by-node-red.md b/src/customer-stories/stfi-future-of-textile-powered-by-node-red.md
index dbacba60fd..d80648278f 100644
--- a/src/customer-stories/stfi-future-of-textile-powered-by-node-red.md
+++ b/src/customer-stories/stfi-future-of-textile-powered-by-node-red.md
@@ -32,7 +32,7 @@ The Model Factory consists of a number of different manufacturing applications,
{data-zoomable}
_Figure 2: [Job Control](https://youtu.be/cgtHO1OVkV8?si=oTpLigbmfqlZ-8Bi&t=98) with State-Machine and OPC-UA-Connection to the machines like a [laser cutter](https://youtu.be/eUkZ8R1tNM4?si=uOwL-XGf0uKkXdVL) (ⒸSTFI)_
-The [job control system](https://youtu.be/cgtHO1OVkV8?si=oTpLigbmfqlZ-8Bi&t=98) is a set of state machines built in Node-RED, see figure 2. Each state machine represents a different machine like a [mobile robot](https://youtu.be/Z_e6EcT2mQs?si=DfxQS0K16bcrpixi) and includes different communication nodes to the different pieces of equipment on the [factory floor](/use-cases/shop-floor-communication/). Node-RED was well suited for developing these state machines since state machines are well represented in flow based programming and also Node-RED provides support for the different communication protocols like [OPC UA](/node-red/flowfuse/edge/opcua/). Node-RED was also used to control the automated guided vehicle and the collaborative robot UR10e within the mobile robot, see figure 3.
+The [job control system](https://youtu.be/cgtHO1OVkV8?si=oTpLigbmfqlZ-8Bi&t=98) is a set of state machines built in Node-RED, see figure 2. Each state machine represents a different machine like a [mobile robot](https://youtu.be/Z_e6EcT2mQs?si=DfxQS0K16bcrpixi) and includes different communication nodes to the different pieces of equipment on the [factory floor](/use-cases/shop-floor-communication/). Node-RED was well suited for developing these state machines since state machines are well represented in flow based programming and also Node-RED provides support for the different communication protocols like [OPC UA](/docs/flowfuse-nodes/edge/opcua/). Node-RED was also used to control the automated guided vehicle and the collaborative robot UR10e within the mobile robot, see figure 3.
{data-zoomable}
_Figure 3: Within the [mobile Robot](https://youtu.be/Z_e6EcT2mQs?si=DfxQS0K16bcrpixi), control the Automated Guided Vehicle and the Universal Robot via OPC UA and Real-Time Data Exchange (ⒸSTFI)_
diff --git a/src/node-red/core-nodes/common.njk b/src/node-red/core-nodes/common.njk
deleted file mode 100644
index e6d2d49af4..0000000000
--- a/src/node-red/core-nodes/common.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.common
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "common"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
\ No newline at end of file
diff --git a/src/node-red/core-nodes/function.njk b/src/node-red/core-nodes/function.njk
deleted file mode 100644
index 228d7cc2ef..0000000000
--- a/src/node-red/core-nodes/function.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.function
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "function"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
diff --git a/src/node-red/core-nodes/index.njk b/src/node-red/core-nodes/index.njk
deleted file mode 100644
index dae5f835ba..0000000000
--- a/src/node-red/core-nodes/index.njk
+++ /dev/null
@@ -1,25 +0,0 @@
----
-eleventyNavigation:
- key: Core Nodes
- order: 4
----
-
Node-RED Core Nodes
-
-
In Node-RED, the core nodes are the set of nodes that are included with the
-Node-RED runtime by default without the node install procedure. These nodes are
-maintained and supported by the Node-RED development team and are intended to
-provide the basic building blocks for creating Node-RED flows.
-
-
Core nodes include nodes for basic functionality like input/output, processing,
-and control flow. They are the foundation upon which more complex workflows can
-be built, and they are essential to the operation of Node-RED.
-
-
The nodes are grouped in a few sections in the nodes sidebar:
-
-
common - miscellaneous nodes
-
function - Control flow, blocking or sending additional messages.
-
network - Receive and send messages over the network on different protocols.
-
sequence - Working with collections of messages, or creating them.
-
parser - transforming data from one format to another.
-
storage - for reading or writing files.
-
diff --git a/src/node-red/core-nodes/nav.njk b/src/node-red/core-nodes/nav.njk
deleted file mode 100644
index b0f9f74bfb..0000000000
--- a/src/node-red/core-nodes/nav.njk
+++ /dev/null
@@ -1,15 +0,0 @@
----
-pagination:
- data: coreNodesArray
- size: 1
- alias: category
- addAllPagesToCollections: true
-permalink: "node-red/core-nodes/{{ category.key | lower | replace(' ', '-') }}-nav/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ category.key }}"
- title: "{{ category.key | capitalize }}"
- parent: "Core Nodes"
- url: "/node-red/core-nodes/{{ category.nodes[0].name | lower | replace(' ', '-') }}/"
- permalink: false
----
\ No newline at end of file
diff --git a/src/node-red/core-nodes/network.njk b/src/node-red/core-nodes/network.njk
deleted file mode 100644
index f1aa4d1962..0000000000
--- a/src/node-red/core-nodes/network.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.network
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "network"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
diff --git a/src/node-red/core-nodes/parsers.njk b/src/node-red/core-nodes/parsers.njk
deleted file mode 100644
index a3d95fbada..0000000000
--- a/src/node-red/core-nodes/parsers.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.parsers
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "parsers"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
diff --git a/src/node-red/core-nodes/sequence.njk b/src/node-red/core-nodes/sequence.njk
deleted file mode 100644
index a53a0353ae..0000000000
--- a/src/node-red/core-nodes/sequence.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.sequence
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "sequence"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
diff --git a/src/node-red/core-nodes/storage.njk b/src/node-red/core-nodes/storage.njk
deleted file mode 100644
index ce6fc25b14..0000000000
--- a/src/node-red/core-nodes/storage.njk
+++ /dev/null
@@ -1,18 +0,0 @@
----
-pagination:
- data: coreNodes.storage
- size: 1
- alias: node
- addAllPagesToCollections: true
-coreNodeCategory: "storage"
-permalink: "node-red/core-nodes/{{ node.name | lower | replace(' ', '-') }}/"
-eleventyComputed:
- eleventyNavigation:
- key: "{{ node.name }}"
- parent: "{{ coreNodeCategory }}"
- title: "Node-RED - {{ node.name }} Node"
- description: "{{ node.description }}"
- keywords: "{{ node.keywords }}"
----
-
-{% include "core-node-docs.njk" %}
diff --git a/src/node-red/database/index.md b/src/node-red/database/index.md
deleted file mode 100644
index 979ff96745..0000000000
--- a/src/node-red/database/index.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-eleventyNavigation:
- key: Database
- order: 7
-meta:
- title: Node-RED Database Integration Guides
- description: Explore database integration guides for Node-RED, including PostgreSQL, MongoDB, InfluxDB, DynamoDB, and TimescaleDB
- keywords: node-red, databases, integration, PostgreSQL, MongoDB, InfluxDB, DynamoDB, TimescaleDB
-certified:
- - "@flowfuse-certified-nodes/redis"
-certifiedTitle: "A certified node for these databases"
-certifiedIntro: >
- The guides in this section use community packages. One database here is also
- covered by a FlowFuse certified node, maintained for production use:
----
-
-# {{ meta.title }}
-
-Node-RED is highly versatile and can be set up to work with a variety of databases, whether it is SQL (e.g., PostgreSQL, MySQL), NoSQL (e.g., MongoDB), or time-series databases (e.g., InfluxDB). This flexibility allows you to store and manage IoT data effectively, enabling the creation of interactive and data-driven applications for IoT environments.
-
-## Resources
-
-Here are some resources to help you get started with Node-RED on diffrent types of databases. Each guide provides step-by-step instructions to help you get started, along with advanced techniques for optimizing performance and handling complex data operations.:
-
-{% include "navigation-items-list.njk" %}
-
-{% include "components/certified-node-callout.liquid" %}
diff --git a/src/node-red/flowfuse/ai/index.md b/src/node-red/flowfuse/ai/index.md
deleted file mode 100644
index 6aaefb68d1..0000000000
--- a/src/node-red/flowfuse/ai/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-eleventyNavigation:
- key: AI
- parent: FlowFuse Nodes
- order: 1
-meta:
- title: FlowFuse AI Nodes
- description: A set of Node-RED nodes for AI and machine learning, including ONNX model inference and LLM nodes for OpenAI, Anthropic, Google Gemini, and Ollama.
----
-
-# {{ meta.title }}
-
-The **FlowFuse AI** Nodes package adds AI capabilities to Node-RED. It includes nodes for running local ONNX models for image classification, object detection, depth estimation, and custom inference, as well as LLM nodes for sending text prompts to hosted and local large language models from OpenAI, Anthropic, Google Gemini, and Ollama.
-
-## Nodes
-
-{% include "navigation-items-list.njk" %}
-
diff --git a/src/node-red/flowfuse/edge/index.md b/src/node-red/flowfuse/edge/index.md
deleted file mode 100644
index 53788dd161..0000000000
--- a/src/node-red/flowfuse/edge/index.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-eleventyNavigation:
- key: Edge
- parent: FlowFuse Nodes
- order: 4
- title: Edge
-meta:
- title: Edge Certified Nodes
- description: Documentation for FlowFuse Edge Certified Nodes, including nodes for connecting FlowFuse to industrial protocols, PLCs, SCADA systems, and factory-floor equipment.
----
-
-# {{ meta.title }}
-
-This section contains documentation for **FlowFuse Edge Certified Nodes** that connect your FlowFuse instances to industrial protocols, PLCs, SCADA systems, and factory-floor equipment.
-
-FlowFuse Certified Nodes are packages that FlowFuse has vetted for quality, security, and support, and maintains on an ongoing basis. To learn more about what certification means and how these nodes are delivered, [read the FlowFuse Certified Nodes blog post](/blog/2025/07/certified-nodes-v2/).
-
-{% note %}
-The FlowFuse Edge Certified Nodes catalogue is part of the **FlowFuse Edge** offering. [Contact us](/contact-us/) to get access or to learn more.
-{% endnote %}
-
-{% note %}
-This section is expanding. We are actively working to bring more Edge Certified Nodes to FlowFuse, and additional documentation will be added here over time.
-{% endnote %}
-
-## Nodes
-
-This section lists the **Edge Certified Nodes** documented in FlowFuse:
-
-{% include "navigation-items-list.njk" %}
-
-{% note %}
-Newly installed nodes are picked up automatically, no restart needed. Restart is only required when you update a node that's already installed: restart any remote instance or hosted instance running the previous version.
-{% endnote %}
diff --git a/src/node-red/flowfuse/index.md b/src/node-red/flowfuse/index.md
deleted file mode 100644
index f615d3bc13..0000000000
--- a/src/node-red/flowfuse/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-eleventyNavigation:
- key: FlowFuse Nodes
- order: 5
-meta:
- title: FlowFuse Nodes
- description: An overview of the Node-RED nodes provided by FlowFuse, explaining their purpose, usage, and benefits for building integrations and automations.
----
-
-# {{ meta.title }}
-
-In Node-RED on the FlowFuse platform, you have access to additional Node-RED nodes that are provided by FlowFuse. These are documented in the below sections as a reference you can use when building integrations and automations.
-
-## Nodes
-
-The following documents provide details about the FlowFuse nodes:
-
-{% include "navigation-items-list.njk" %}
diff --git a/src/node-red/getting-started/index.md b/src/node-red/getting-started/index.md
deleted file mode 100644
index c43ecd44b8..0000000000
--- a/src/node-red/getting-started/index.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-eleventyNavigation:
- key: Getting Started
- order: 1
-meta:
- title: Getting Started with Node-RED
- description: Learn the basics of Node-RED, a powerful tool for IoT integration and workflow automation.
- keywords: node-red, node-red basics, node-red foundation, node-red editor
----
-
-# {{ meta.title }}
-
-This section provides an overview of Node-RED, a robust visual tool designed for integrating IoT devices and automating workflows without needing extensive programming knowledge.
-
-{% include "navigation-items-list.njk" %}
\ No newline at end of file
diff --git a/src/node-red/getting-started/programming/index.md b/src/node-red/getting-started/programming/index.md
deleted file mode 100644
index cd2cd2be1a..0000000000
--- a/src/node-red/getting-started/programming/index.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-eleventyNavigation:
- key: Programming
- order: 7
- parent: Getting Started
-meta:
- title: Node-RED Programming
- description: Master Node-RED programming fundamentals including flows, nodes, messages, conditional logic, and data manipulation. Learn essential concepts for building sophisticated visual programming solutions.
- keywords: Node-RED programming, visual programming, Node-RED flows, Node-RED nodes, message passing, conditional logic, data manipulation, flow-based programming, Node-RED tutorial, IoT programming
----
-
-# {{ meta.title }}
-
-Learn the core programming concepts you'll use every day in Node-RED. This section covers the fundamental building blocks that will help you create more sophisticated and reliable flows.
-
-## What's Covered
-
-Programming in Node-RED means working with flows, nodes, and messages. Even though you're working visually, you'll still need to understand key programming concepts like conditional logic, loops, and data manipulation. This section teaches you how to implement these concepts using Node-RED's visual approach.
-
-{% include "navigation-items-list.njk" %}
diff --git a/src/node-red/hardware/armxy-bl340.md b/src/node-red/hardware/armxy-bl340.md
deleted file mode 100644
index 540c7b3739..0000000000
--- a/src/node-red/hardware/armxy-bl340.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-eleventyNavigation:
- key: BLIIOT ARMxy BL340
- parent: Hardware
-meta:
- title: Setting Node-RED on BLIIOT ARMxy BL340
- description: Guide to setting up Node-RED on BLIIOT ARMxy BL340, including installation and configuration steps.
- keywords: node-red, flowfuse, BLIIOT ARMxy BL340
-image: "/node-red/hardware/images/armxy-bl340.jpg"
-specifications:
- Model: BLIIoT ARMxy BL340 Series
- RAM_MB: 2048
- Processor: ARM Cortex-A53
- GPU: G31 MP2
- IO Points: Optional (GPIO, RS485,CAN,RS232,DI/DO/AI/AO etc.,)
- Connectivity: Dual-band Wi-Fi 6, Bluetooth 5.2, Gigabit Ethernet, 4x USB 3.0, 1x USB-C
- Clock Speed: Up to 1.4 GHz
- Storage: SD, SDHC and SDXC(UHS-I) card
- Display Output: HDMI 2.0, DisplayPort
- Power Supply: 9~36V DC
-layout: layouts/hardware.njk
----
-
-The BLIIOT ARMxy BL340 is a high-performance single-board computer designed for demanding applications, including edge computing, automation, and embedded systems. Featuring an octa-core ARM processor, advanced connectivity options, and support for high-speed storage, it provides a powerful platform for developers and engineers.
-
-Integrating this powerful hardware with FlowFuse not only enhances its capabilities but also simplifies the management and deployment process.
-
-{% note %}
-Exciting Update! FlowFuse is now available as three different products: [FlowFuse Edge for OT teams](/product/edge/), [FlowFuse Hub for IT teams](/product/hub/), and [FlowFuse Fleet](/product/fleet/) for managing devices at scale. Visit the [FlowFuse Product Page](/product/) to learn how the platform enables you to build and manage industrial apps at scale.
-{% endnote %}
-
-## Prerequisites
-
-Before proceeding with the installation, ensure you have the following:
-
-- **BLIIOT ARMxy BL340** – A functioning device with internet access.
-- **FlowFuse Account** - Ensure you have a FlowFuse account. If not, you can create a free account that allows you to manage up to two edge devices for free. For more information, refer to [FlowFuse Free Tier](/blog/2024/12/flowfuse-release-2-12/)
-- **Sudo Privileges** – Administrator access to install required packages.
-
-## Getting Started
-
-This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the BLIIOT ARMxy BL340, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
-
-{% include "hardware/system/debian-ff-install.md" %}
-
-{% include "hardware/device-registration.md" %}
-
-{data-zoomable}
-
-Now, when your device reboots, the FlowFuse Device Agent will automatically start, ensuring that your BLIIOT ARMxy BL340 remains connected to the FlowFuse platform.
-
-{% include "hardware/accessing-node-red-editor.md" %}
diff --git a/src/node-red/hardware/index.md b/src/node-red/hardware/index.md
deleted file mode 100644
index e0f9335c52..0000000000
--- a/src/node-red/hardware/index.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-eleventyNavigation:
- key: Hardware
- order: 6
-meta:
- title: Setting Up Node-RED on Different Hardware
- description: Learn how to set up Node-RED on various hardware platforms, such as Raspberry Pi, Arduino, and more.
- keywords: node-red, node-red hardware setup, raspberry pi, arduino, siemens iot2050,
----
-
-# {{ meta.title }}
-
-Node-RED is highly versatile and can be set up on a wide range of hardware devices, including popular choices like Raspberry Pi, Ardiuno, Siemens 2050, and more. This flexibility allows you to connect Node-RED to diverse devices and sensors, which enables the creation of interactive and automated systems.
-
-By setting up Node-RED on different hardware, you can easily integrate physical inputs with digital systems. This capability is essential for IoT (Internet of Things) applications, where data from sensors and devices can trigger actions or responses in real-time.
-
-## Resources
-
-Here are some resources to help you get started with Node-RED on diffrent hardware devices:
-
-{% include "navigation-items-list.njk" %}
diff --git a/src/node-red/hardware/raspberry-pi-4.md b/src/node-red/hardware/raspberry-pi-4.md
deleted file mode 100644
index ddebd20bfc..0000000000
--- a/src/node-red/hardware/raspberry-pi-4.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-eleventyNavigation:
- key: Raspberry Pi 4
- parent: Hardware
-meta:
- title: Setting Node-RED on Raspberry Pi 4
- description: Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 4 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
- keywords: node-red, flowfuse, raspberry pi, raspberry pi 4
-image: "/node-red/hardware/images/raspberry-pi-4-b.png"
-specifications:
- Model: Raspberry Pi 4 B 8GB
- RAM_MB: 8192
- Processor: Broadcom BCM2711, ARM Cortex-A72 (ARMv8-A), 4 (Quad-core)
- GPIO: (Fully backwar ds-compatible with previous boards), Standard 40-pin GPIO Header
- Connectivity: Dual-band Wi-Fi, Bluetooth 5.0, Gigabit Ethernet, 2x USB 3.0, 2x USB 2.0
- Clock Speed: 1.5 GHz
- Storage: microSD
-layout: layouts/hardware.njk
----
-
-## Raspberry Pi OS Installation
-
-To set up your Raspberry Pi 4 for use with Node-RED and FlowFuse, follow these steps:
-
-### Flashing Raspberry Pi OS
-
-1. Use the [official Raspberry Pi Imager](https://www.raspberrypi.com/software/) to flash the 64-bit version of Raspberry Pi OS to an SD card.
-
-
-
-2. Before writing to the SD card, configure the OS for headless mode, including Wi-Fi, SSH, and authentication settings.
-
-
-
-3. Write the OS and configuration to the SD card. This process takes about 10 minutes.
-
-4. Insert the SD card into the Raspberry Pi 4 and power it on. The device should appear on your network after a minute or so.
-
-5. Connect to the Raspberry Pi using SSH:
-
- ```sh
- ssh pi@raspberrypi.local
- ```
-
-## Getting Started
-
-This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Raspberry Pi 4, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
-
-{% include "hardware/system/debian-ff-install.md" %}
-
-{% include "hardware/device-registration.md" %}
-
-{data-zoomable}
-
-{% include "hardware/accessing-node-red-editor.md" %}
\ No newline at end of file
diff --git a/src/node-red/hardware/raspberry-pi-5.md b/src/node-red/hardware/raspberry-pi-5.md
deleted file mode 100644
index 0a532a4a0e..0000000000
--- a/src/node-red/hardware/raspberry-pi-5.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-eleventyNavigation:
- key: Raspberry Pi 5
- parent: Hardware
-meta:
- title: Setting Up Node-RED on Raspberry Pi 5
- description: Learn how to install the FlowFuse Edge Agent on the Raspberry Pi 5 effortlessly. Manage your device with Node-RED through FlowFuse with ease.
- keywords: node-red, flowfuse, raspberry pi, raspberry pi 5
-image: "/node-red/hardware/images/raspberrypi-5.png"
-specifications:
- Model: Raspberry Pi 5 Model 8GB
- RAM_MB: 8192
- Processor: Broadcom BCM2712, ARM Cortex-A76 (ARMv8.2-A), 4 (Quad-core)
- GPIO: Standard 40-pin GPIO Header
- Connectivity: 2 × USB 2.0 Ports, 2 × USB 3.0 Ports, Bluetooth 5.0, USB-C, Wi-Fi + Bluetooth® Low Energy
- Clock Speed: 2.4 GHz
- Storage: microSD
-layout: layouts/hardware.njk
----
-
-## Raspberry Pi OS Installation
-
-To set up your Raspberry Pi 5 for use with Node-RED and FlowFuse, follow these steps:
-
-### Flashing Raspberry Pi OS
-
-1. Use the [official Raspberry Pi Imager](https://www.raspberrypi.com/software/) to flash the 64-bit version of Raspberry Pi OS to an SD card.
-
-
-
-2. Before writing to the SD card, configure the OS for headless mode, including Wi-Fi, SSH, and authentication settings.
-
-
-
-3. Write the OS and configuration to the SD card. This process takes about 10 minutes.
-
-4. Insert the SD card into the Raspberry Pi 5 and power it on. The device should appear on your network after a minute or so.
-
-5. Connect to the Raspberry Pi using SSH:
-
- ```sh
- ssh pi@raspberrypi.local
- ```
-
-## Getting Started
-
-This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Raspberry Pi 5, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
-
-{% include "hardware/system/debian-ff-install.md" %}
-
-{% include "hardware/device-registration.md" %}
-
-{data-zoomable}
-
-{% include "hardware/accessing-node-red-editor.md" %}
\ No newline at end of file
diff --git a/src/node-red/hardware/robustel-eg5120.md b/src/node-red/hardware/robustel-eg5120.md
deleted file mode 100644
index 64bbb7a35c..0000000000
--- a/src/node-red/hardware/robustel-eg5120.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-eleventyNavigation:
- key: Robustel EG5120
- parent: Hardware
-meta:
- title: Setting Node-RED on Robustel EG5120
- description: In this guide, we will discuss how to install FlowFuse Device agent on Robustel EG5120.
- keywords: node-red, flowfuse, robustel eg5120
-image: "/node-red/hardware/images/robustel-eg5120.png"
-specifications:
- Model: Robustel EG5120
- RAM_MB: 2048
- Processor: Broadcom BCM2711, ARM Cortex-A72 (ARMv8-A), 4 (Quad-core)
- GPIO: Standard 40-pin GPIO Header
- Connectivity: Dual-band Wi-Fi, Bluetooth 5.0, Gigabit Ethernet, 2x USB 3.0, 2x USB 2.0
- Clock Speed: 1.5 GHz
- Storage: microSD
-layout: layouts/hardware.njk
----
-
-The [Robustel EG5120](https://www.robustel.com/product/eg5120-industrial-edge-computing-gateway/) is a versatile gateway that facilitates robust connectivity for industrial IoT applications. Integrating this powerful hardware with FlowFuse not only enhances its capabilities but also simplifies the management and deployment process. In this documentation, we’ll walk through the steps to integrate the Robustel EG5120 with FlowFuse.
-
-The [Robustel EG5120](https://www.robustel.com/product/eg5120-industrial-edge-computing-gateway/), equipped with Linux-based Debian 11 supporting a wide variety of programming languages including Node.js, offers robust connectivity options. When combined with FlowFuse, this gateway becomes even more powerful, enabling seamless device management and deployment.
-
-The Robustel EG5120 supports multiple connectivity options including Ethernet, Wi-Fi, and cellular networks, which are essential for flexible deployments in various industrial scenarios. Its built-in support for Bluetooth, cellular connectivity, RS232, RS485, and Modbus facilitates seamless integration with a wide array of IoT devices and services. This blog will guide you through using FlowFuse to effectively manage your Node-RED instance, enhancing both the security and scalability of your IoT applications.
-
-## Getting Started
-
-This guide explores how to install and run Node-RED through the FlowFuse Device Agent on the Robustel EG5120, enabling you to build, manage, and scale Node-RED flows efficiently from a remote location.
-
-{% include "hardware/system/debian-ff-install.md" %}
-
-{% include "hardware/device-registration.md" %}
-
-{% include "hardware/accessing-node-red-editor.md" %}
\ No newline at end of file
diff --git a/src/node-red/index.njk b/src/node-red/index.njk
index 431edba5dc..6c0f024e98 100644
--- a/src/node-red/index.njk
+++ b/src/node-red/index.njk
@@ -310,13 +310,13 @@ sitemapPriority: 0.8
- SEE MORE
+ SEE MOREGET IMPLEMENTATION SUPPORT
diff --git a/src/node-red/integration-technologies/index.md b/src/node-red/integration-technologies/index.md
deleted file mode 100644
index a42dba234b..0000000000
--- a/src/node-red/integration-technologies/index.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-metaTitle: "Building Applications with Node-RED"
-eleventyNavigation:
- key: "Integration Technologies"
- order: 10
-meta:
- title: Using Different Technologies for Building Applications with Node-RED.
- description: Learn how to leverage various integration technologies with Node-RED for building robust and interconnected applications.
- keywords: node-red, flowfuse, node-red integration, integration technologies, webhook, rest api
----
-
-# {{meta.title}}
-
-Developing powerful and scalable applications frequently necessitates the integration of various technologies. This integration is crucial for creating seamless and efficient systems that can handle complex tasks and large volumes of data. Whether you're working with REST APIs to enable communication between different services or implementing GraphQL for more efficient data querying, the ability to blend these technologies effectively is essential for modern application development.
-
-Node-RED offers a versatile and robust platform to meet these needs. Its intuitive flow-based interface allows developers to easily design and deploy sophisticated workflows, which makes it an invaluable tool for integrating REST APIs, GraphQL, webhooks, and more.
-
-## Resources
-
-Here are some resources to help you integrate Node-RED with various different technologies:
-
-{% include "navigation-items-list.njk" %}
\ No newline at end of file
diff --git a/src/node-red/learn.md b/src/node-red/learn.md
deleted file mode 100644
index 664ab80f21..0000000000
--- a/src/node-red/learn.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
-eleventyNavigation:
- key: Node-RED Documentation
- order: 0
-meta:
- title: "Node-RED Documentation: 100+ Tutorials (2026)"
- description: "Master Node-RED visual programming with comprehensive documentation covering core nodes, database integration, hardware setup, communication protocols, and real-world industrial IoT examples."
- keywords: node-red, node red, documentation, guide, core nodes, database integration, hardware setup, protocols, industrial iot
----
-
-# Node-RED Documentation: 100+ Tutorials (2026)
-
-[Node-RED](/node-red/), the low-code visual programming platform, is becoming increasingly popular for optimizing and automating industrial processes. Enabling the integration of different hardware devices, API services, and technologies, it's exceptionally suited for a variety of industrial IoT applications.
-
-This documentation provides comprehensive guidance for working with Node-RED, from foundational concepts to advanced implementations. You'll find detailed explanations of core nodes, terminology references, integration guides for databases and communication protocols, and platform-specific setup instructions for various hardware devices.
-
-## Common Terminology
-
-A good starting point is understanding the common terms used in Node-RED. You should be able to confidently navigate through most Node-RED-related resources and participate in Node-RED forum discussions.
-
-[Node-RED Common Terminologies](/node-red/terminology/)
-
-## Core Nodes
-
-This section includes detailed documentation for each Node-RED core node, from configuration to use in real-world applications with examples.
-
-[Core Nodes](/node-red/core-nodes/)
-
-## Hardware Devices
-
-In this section, you will find tutorials on setting up Node-RED on different hardware devices. Each tutorial covers configuration, practical demos and troubleshooting tips.
-
-[Setting Up Node-RED on Different Hardware](/node-red/hardware/)
-
-## Peripheral Devices
-
-This section includes step-by-step documentation on integrating Node-RED with various peripheral devices such as webcams, barcode scanners, printer, mic and more.
-
-[Integrating Node-RED with Peripheral Devices](/node-red/peripheral/)
-
-## Databases
-
-This section includes tutorials on how to use different databases with Node-RED. Each tutorial provides step-by-step instructions along with practical examples. We cover a variety of databases such as SQL, NoSQL, and time-series databases.
-
-[Node-RED Database Integration Guides](/node-red/database/)
-
-## Communication Protocols
-
-This section includes comprehensive tutorials on how to use different protocols with Node-RED for building applications, communicating with edge devices, and more. Each tutorial provides step-by-step instructions along with practical demos.
-
-[Using Different Protocols for Building Applications with Node-RED](/node-red/protocol/)
-
-## Integration Technologies
-
-In this section you will find tutorials on how to utilize various technologies with Node-RED, such as implementing webhooks for task automation, creating REST APIs, GraphQL integrations, and more.
-
-[Using Different Technologies for Building Applications with Node-RED](/node-red/integration-technologies/)
-
-## Notification Services
-
-In this section, we cover how to integrate various notification services with Node-RED to send real-time alerts and notifications. It includes step-by-step guides along with troubleshooting tips.
-
-[Notification Services in Node-RED](/node-red/notification/)
diff --git a/src/node-red/node-red.json b/src/node-red/node-red.json
deleted file mode 100644
index 5dfbbb1e3e..0000000000
--- a/src/node-red/node-red.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "layout": "layouts/documentation.njk",
- "hideTitle": "true",
- "nav": "node-red",
- "searchTitle": "Node-RED",
- "tags": [
- "learningResources"
- ]
-}
diff --git a/src/node-red/notification/index.md b/src/node-red/notification/index.md
deleted file mode 100644
index b54da184c0..0000000000
--- a/src/node-red/notification/index.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-eleventyNavigation:
- key: "Notification Services"
- order: 11
-meta:
- title: Notification Services in Node-RED
- description: Learn how to integrate various notification services with Node-RED for real-time alerts and messaging.
- keywords: node-red, notification services, email notifications, Telegram notifications, Slack notifications, WhatsApp notifications
----
-
-# Notification Services
-
-Real-time notifications are essential in our automation world, helping to keep us informed, responsive, and efficient. Whether it's a critical system alert, a customer inquiry, or a simple reminder, timely notifications can significantly enhance productivity and efficiency. However, managing and integrating such services can be challenging in traditional development environments. Node-RED simplifies this process by supporting a wide range of notification services, including email, Telegram, Slack, WhatsApp, and more.
-
-## Resources
-
-Here are some resources to help you get started with Node-RED on diffrent notification services:
-
-{% include "navigation-items-list.njk" %}
\ No newline at end of file
diff --git a/src/node-red/protocol/index.md b/src/node-red/protocol/index.md
deleted file mode 100644
index 592ca23281..0000000000
--- a/src/node-red/protocol/index.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-metaTitle: "Using Different Protocols with Node-RED"
-eleventyNavigation:
- key: "Communication Protocols"
- order: 9
-meta:
- title: Using Different Protocols for Building Applications with Node-RED
- description: Learn how to leverage various communication protocols with Node-RED for building robust and interconnected applications.
- keywords: node-red, iot, mqtt, http, coap, websockets, diffrent protocols with node-red
-certified:
- - "@flowfuse-certified-nodes/cip-suite"
- - "@flowfuse-certified-nodes/opcua"
-certifiedTitle: "Certified nodes for these protocols"
-certifiedIntro: >
- Two protocols are also covered by a FlowFuse certified node, maintained for
- production use. EtherNet/IP, for Rockwell and Allen-Bradley controllers, has no
- page of its own in this section, and is documented with its certified node:
----
-
-# {{meta.title}}
-
-In IoT development, effective communication between devices is essential. This communication is facilitated by various protocols like MQTT, HTTP, CoAP, and WebSockets. Each protocol brings its own set of strengths and is suited for different IoT scenarios. However, understanding which protocol is suited for what scenario and utilizing it can be quite difficult. That's why we have created this section of resources where you will find documentation on using different communication protocols with Node-RED.
-
-Node-RED, with its intuitive visual programming interface, simplifies the integration of these protocols. Whether you're publishing sensor data over MQTT, triggering HTTP requests, querying CoAP endpoints, or enabling real-time communication with WebSockets, Node-RED provides a flexible and powerful platform.
-
-## Resources
-
-Here are some resources to help you get started with integrating Node-RED with various communication protocols:
-
-{% include "navigation-items-list.njk" %}
-
-{% include "components/certified-node-callout.liquid" %}
\ No newline at end of file
diff --git a/src/webinars/2026/industrial-iot-solutions.md b/src/webinars/2026/industrial-iot-solutions.md
index fa29e2fd4a..ea5875fd05 100644
--- a/src/webinars/2026/industrial-iot-solutions.md
+++ b/src/webinars/2026/industrial-iot-solutions.md
@@ -10,7 +10,7 @@ meta:
Industrial IoT (IIoT) is the use of connected sensors and devices to collect data from industrial operations and feed it into software for monitoring and real-time action. FlowFuse is the platform that runs on top of that data: the flows that connect it, the dashboards that display it, and the governance that keeps it under control.
- question: "What's the difference between FlowFuse Hub, Edge, and Fleet?"
answer: >
- Hub integrates enterprise systems and APIs for IT teams. Edge connects PLCs and machines across sites for OT teams. Fleet manages Node-RED across thousands of distributed devices. All three run on the same platform; the difference is which deployment shape each one is built for.
+ Hub integrates enterprise systems and APIs for IT teams. Edge connects PLCs and machines across sites for OT teams. Fleet manages Node-RED across thousands of distributed devices. All three run on the same platform; the difference is which deployment shape each one is built for.
- question: "How do I know which industrial IoT solution is right for my setup?"
answer: >
It comes down to where your applications live: a data center (Hub), a plant floor (Edge), or thousands of field devices (Fleet). We'll walk through all three live in the webinar and help map your specific setup to one of them. Bring your architecture and we'll sort it live in the Q&A.
@@ -44,7 +44,7 @@ Join Kristopher Sandoval (Product Marketing), Jamie Strusz (Engineering), Drew G
## Which industrial IoT solution fits my setup?
-- FlowFuse Hub integrates [enterprise systems](/landing/enterprise-integration/) and [APIs](/node-red/core-nodes/http-request/), FlowFuse Edge connects [PLCs](/landing/plc/) and machines across sites, FlowFuse Fleet manages [Node-RED](/node-red/) across thousands of devices. We'll map your setup to one of the three, live.
+- FlowFuse Hub integrates [enterprise systems](/landing/enterprise-integration/) and [APIs](/docs/node-red/core-nodes/network/http-request/), FlowFuse Edge connects [PLCs](/landing/plc/) and machines across sites, FlowFuse Fleet manages [Node-RED](/node-red/) across thousands of devices. We'll map your setup to one of the three, live.
- Build faster with Industrial AI: [FlowFuse Expert](/docs/user/expert/) opens its [MCP server](/blog/2025/10/building-mcp-server-using-flowfuse/) to 3rd party agents, such as Cursor, Claude Code, Gemini CLI, and even in-house agents. Any MCP-speaking agent works. Point your AI agent at your FlowFuse instance and it builds, debugs, and fixes flows directly.
- See what's running, everywhere: [role-based access control](/docs/user/role-based-access-control/), [audit logging](/docs/user/logs/#audit-log), and [one place to manage every instance and device](/blog/2024/10/managing-node-red-instances-in-centralize-platfrom/), no matter which product you run.
- Read a [dashboard](/platform/dashboard/) at a glance: new [built-in themes](https://dashboard.flowfuse.com/nodes/config/ui-theme.html) with WCAG AA contrast, [charts](https://dashboard.flowfuse.com/nodes/widgets/ui-chart) that render instead of leaving empty boxes, and readable dates instead of raw timestamps.
diff --git a/src/webinars/2026/modbus-communications-modernization.md b/src/webinars/2026/modbus-communications-modernization.md
index d258127976..f9f28a80c8 100644
--- a/src/webinars/2026/modbus-communications-modernization.md
+++ b/src/webinars/2026/modbus-communications-modernization.md
@@ -44,7 +44,7 @@ This is the core of the session: a practical framework for deciding when to leav
Around the halfway mark, Kristopher switches over to a live demo in FlowFuse and Node-RED: raw Modbus registers going in one end, and a named, typed, dashboarded data stream coming out the other. If you'd rather follow along with a written walkthrough afterward, our [Using Modbus with FlowFuse](/blog/2025/09/using-modbus-with-flowfuse/) guide covers the same setup step by step.
-Also worth a look once you're in the recording: the live Q&A, where attendees bring in real issues, from Modbus TCP connections that quietly go blank to how much visibility you can actually get into what's on the bus. If any of that sounds familiar, our posts on [Modbus polling best practices](/blog/2026/04/modbus-polling-best-practices/) and [diagnosing Modbus degradation](/blog/2026/04/diagnosing-modbus-degradation/) dig further into the same failure modes. And if you're still weighing Modbus against the alternatives, [why OPC UA isn't replacing Modbus yet](/blog/2026/03/why-opcua-is-not-replacing-modbus-yet/) and [Modbus TCP vs. Modbus RTU](/blog/2026/02/modbus-tcp-vs-modbus-rtu/) are good next reads, and the [Modbus protocol page](/node-red/protocol/modbus/) has the full Node-RED node documentation whenever you're ready to build.
+Also worth a look once you're in the recording: the live Q&A, where attendees bring in real issues, from Modbus TCP connections that quietly go blank to how much visibility you can actually get into what's on the bus. If any of that sounds familiar, our posts on [Modbus polling best practices](/blog/2026/04/modbus-polling-best-practices/) and [diagnosing Modbus degradation](/blog/2026/04/diagnosing-modbus-degradation/) dig further into the same failure modes. And if you're still weighing Modbus against the alternatives, [why OPC UA isn't replacing Modbus yet](/blog/2026/03/why-opcua-is-not-replacing-modbus-yet/) and [Modbus TCP vs. Modbus RTU](/blog/2026/02/modbus-tcp-vs-modbus-rtu/) are good next reads, and the [Modbus protocol page](/docs/node-red/protocol/modbus/) has the full Node-RED node documentation whenever you're ready to build.
## Who This Session Is For
diff --git a/src/webinars/2026/the-agile-factory-on-the-connected-edge.md b/src/webinars/2026/the-agile-factory-on-the-connected-edge.md
index bee86babe4..f93dd1dd80 100644
--- a/src/webinars/2026/the-agile-factory-on-the-connected-edge.md
+++ b/src/webinars/2026/the-agile-factory-on-the-connected-edge.md
@@ -25,8 +25,8 @@ In this session, Rhythm Agarwal (Senior Manufacturing Test Engineer at Aperia) a
## How Aperia Replaced Traditional PLCs with Edge Applications
- **Extends the shop floor, doesn't replace it.** Smart fixtures run on FlowFuse instead of a PLC, so existing equipment keeps working, just connected.
-- **Speaks every protocol.** Sensors, scanners, and actuators connect over [MODBUS-TCP](/node-red/protocol/modbus/), [RS-232](/blog/2025/07/connect-legacy-equipment-serial-flowfuse/), and [raw TCP](/node-red/core-nodes/tcp-in/), all feeding into one data flow.
-- **Logs data the moment it happens.** Every station writes to a shared [MongoDB](/node-red/database/mongodb/) backend in real time, not on a delay.
+- **Speaks every protocol.** Sensors, scanners, and actuators connect over [MODBUS-TCP](/docs/node-red/protocol/modbus/), [RS-232](/blog/2025/07/connect-legacy-equipment-serial-flowfuse/), and [raw TCP](/docs/node-red/core-nodes/network/tcp-in/), all feeding into one data flow.
+- **Logs data the moment it happens.** Every station writes to a shared [MongoDB](/docs/node-red/database/mongodb/) backend in real time, not on a delay.
- **One fix, applied everywhere.** Code changes roll out to entire device groups from a single pipeline, with full version control, not machine by machine.
## Three Manufacturing Applications Built on the Edge