# Cross references to other flow nodes in documentation

**URL:** <https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504>\
**Category:** General\
**Created:** [21 July 2026 07:40 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504 "2026-07-21T07:40:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [21 July 2026 07:40 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/1 "2026-07-21T07:40:12Z")

</div>

Hi There,

Are cross references from one node to the other in documentation possible:

 ![Screenshot 2026-07-21 at 09.29.54](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/7/37aab4e3174271021416304ee1369f51d20be440.png)

If I click on "Function 2" in the documentation, ideally this should happen:

 ![Screenshot 2026-07-21 at 09.38.04](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/a/cabad9fc34c9bab4da93f609d08d4371efef7247.png)

I've tried `onclick` but that gets removed when the markdown is rendered. Instead I started using this `href="#node/01236b2a218a1740"` but that's not working ... any ideas?

What I really want to do is a `RED.search.show('function 2');` to avoid hardcoding the node id. That could be done in the `onclick` of the link. Or add the support of an extra data attribute `data-search='function 2'` on any documentional link (to avoid phishing).

```flows
[{"id":"cf62fec0c5a535cf","type":"function","z":"6a4884ae4f27e246","name":"function 1","func":"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":454.375,"y":492.5,"wires":[[]],"info":"<a href=\"#node/01236b2a218a1740\">Function 2</a> does all the work."},{"id":"01236b2a218a1740","type":"function","z":"6a4884ae4f27e246","name":"function 2","func":"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":668.125,"y":671.25,"wires":[[]]}]

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [21 July 2026 08:08 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/2 "2026-07-21T08:08:46Z")

</div>

Short answer no.

I did think about (and ask, and look into) this for comment nodes but they are rendered in SVG (so was not simple).

Now we have the popover (which is HTML) we could permit specially crafted markdown hyperlinks e.g. `[function 2](#node/01236b2a218a1740)` that when rendered attach a click handler to call the appropriate `RED` function (we do something similar in FlowFuse)

At the moment, we have deep-linking for opening (and editing) nodes in the form of `http://<ip>/#node/55820643ea60d8cd` and they CAN be rendered as hyperlinks and DO work (e.g. `[see function 2](http://<ip>/#node/55820643ea60d8cd)`) but they cause new tab to be opened due to having \_blank target.

In theory, a plugin could target the content of the popover (`.red-ui-flow-annotation-popover-body`) and specially crafted text (or anchors with a particular attribute) could be modified to have a click handler that ultimately calls `RED.view.reveal('a411ef027c9d796f', true)` (`true` means highlight the node).

The reason onclick gets removed is due to dom sanitizer.

* * *

While I suggested a plugin could do this, It would be far better to be a core feature to avoid competing ideas.

IMO, we should be able to do way more:

- A way to open the edit panel of a node (this is also supported deep link today)
- A way to initiate ANY action i.e. the search panel
  - e.g. _Search for `[all function nodes](#action/search?term=type:"function")`_

- A way to show/hide panels
  - e.g. _You will see the output in the `[debug panel](#panel/debug/open)`_

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [21 July 2026 08:36 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/3 "2026-07-21T08:36:29Z")

</div>

Thanks for the detailed answer 👍

> [@Steve-Mcl](#):
>
> It would be far better to be a core feature

Definitely.

On the other hand doing something like we did with the [groupflow](https://discourse.nodered.org/t/async-multiple-input-for-nodes/101476) plugin, i.e. having a plugin demonstrate the feature which then can be used in the meantime is probably the golden middle road.

I'm pretty sure that something like the groupflow will - eventually - make it into core. Having a plugin to test the feature and add suggestions before then is really useful.

> [@Steve-Mcl](#):
>
> we do something similar in FlowFuse

Can I ask does FlowFuse parse the url and to determine what functionality is to be called? I.e. could I add something like `[Name](#search/search%20term)` so that I can trigger the `RED.search.open("search term")` functionality?

I know that extending the markdown rendered isn't rocket science, just whether that is possible via a plugin remains a mystery to me.

> [@Steve-Mcl](#):
>
> [see function 2](http://\<ip\>/#node/55820643ea60d8cd)

I think this isn't a good idea for portability 😉 - hardcoding both the IP and node id means that importing the flow somewhere else will probably break the documentation ....

> [@Steve-Mcl](#):
>
> The reason onclick gets removed is due to dom sanitizer.

`onclick` is definitely no solution. I totally forgot to use markdown notation (because I started with onclick), so having `[..](#<function>/<arg>)` convention for markdown links would be the way to go...

Cheers!

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [21 July 2026 08:42 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/4 "2026-07-21T08:42:08Z")

</div>

> [@gregorius](#):
>
> Can I ask does FlowFuse parse the url and to determine what functionality is to be called? I.e. could I add something like `[Name](#search/search%20term)` so that I can trigger the `RED.search.open("search term")` functionality?

Yes. Specially crafted urls are intercepted and converted into actions. This is done in a `beforeSanitizeAttributes` and `afterSanitizeAttributes` hooks on `DOMPuirfy`

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [21 July 2026 11:25 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/5 "2026-07-21T11:25:55Z")

</div>

> [@Steve-Mcl](#):
>
> `[see function 2](http://<ip>/#node/55820643ea60d8cd)`)

```markdown
[link](./#node/fn_router)

```

works. The leading `.` represents the current URL route and takes into account any admin route path changes. Clicking on that link does correctly change the browser's URL but does not highlight the target node. The important point being that it isn't stripped by the sanitizer and it does not trigger a new tab to open and it is totally portable.

Incidentally, I've no idea where the node name `fn_router` came from. That is the node's ID in the flow but it isn't it's name which is "Lookup + build redirect". 🤷 Hmm, I wonder if I imported someone else's code and that code was generated by an AI originally and it set the ID to that name instead of a UID?

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [21 July 2026 15:59 UTC](https://discourse.nodered.org/t/cross-references-to-other-flow-nodes-in-documentation/101504/6 "2026-07-21T15:59:42Z")

</div>

> [@Steve-Mcl](#):
>
> `afterSanitizeAttributes`

Ok after a good deal of t&e -

![Screen Recording 2026-07-21 at 17.48.23](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/6/96cf14ea7930e3e7e43c8680e16cbb66cf529f49.gif)

What I use here is `[00-base.html.js](#/search/00-base.html.js)` - so the "action" is action and the "argument" is `00-base-html.js`. I prefer that to using `?searchTerm=....` - but each to their own!

The frontend code for this was (not my finest hour):

```auto
DOMPurify.addHook("afterSanitizeAttributes", (e, h, c) => {
    if (typeof e === "object" && Object.getPrototypeOf(e) === HTMLAnchorElement.prototype) {
        let mth = e.href.match(/#\/search\/(.+)/)
        if (mth) {
            window.handleSearch = (term) => {
                RED.search.show(term)
                $('.red-ui-flow-annotation-popover').hide()
            }
            e.href = `javascript:window.handleSearch('${mth[1]}')`
        }
    }
})

```

A couple of problems:

1. `onclick` cannot be set, DOMPurify will not include it in the final result, that is because the configuration doesn't allow it. So the only thing that becomes usable is the `href`.
2. there is no clean why of hiding the popover (at least not that I found) because there is no [`RED.popover.close()`](https://github.com/node-red/node-red/blob/85f2b71b42336657d90e6964f888f2c278ca5a8e/packages/node_modules/%40node-red/editor-client/src/js/ui/common/popover.js#L511) functionality. If that isn't done, the popover and the search interface are shown at the same time so the popover has to be closed.

This also works from the info box in the sidebar, so overall, a good solution to solving the problem!
