Conversation
Contributor
Author
|
has a lot of changes as this stacks on top of other PRs. If those get merged, this one can follow and it will have less changes. Until then this stays a draft PR |
4 of 5 tasks
✅ Deploy Preview for flowfuse-website ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
dimitrieh
changed the base branch from
main
to
docs/node-red-library-into-docs
September 8, 2026 08:47
dimitrieh
force-pushed
the
docs/node-red-library-into-docs
branch
from
September 8, 2026 09:04
02d2826 to
35d1a80
Compare
dimitrieh
force-pushed
the
docs/content-collections-instead-of-sync
branch
10 times, most recently
from
September 8, 2026 11:41
b17b8c5 to
68a3cb7
Compare
dimitrieh
marked this pull request as ready for review
September 8, 2026 15:23
Contributor
Author
|
@ZJvandeWeg can you have a look here? This essentially fixes your request at #5495 (comment) |
dimitrieh
force-pushed
the
docs/content-collections-instead-of-sync
branch
from
September 15, 2026 11:38
51dbb2e to
2063535
Compare
dimitrieh
force-pushed
the
docs/content-collections-instead-of-sync
branch
from
September 25, 2026 19:56
2063535 to
fbd5d63
Compare
Contributor
Author
|
FYI: the failing build here isn't caused by this PR. Tracked in https://github.com/FlowFuse/engineering/issues/460. It's resolved now, re-running the checks. |
dimitrieh
force-pushed
the
docs/content-collections-instead-of-sync
branch
from
September 25, 2026 20:06
fbd5d63 to
ddb9c47
Compare
Contributor
Author
|
Preview affected pages:
Every guide page under these four sections is now read from |
The group name rendered at caption size, the same weight as the pages under it, so the grouping had to be read rather than seen. It now takes body size and the links sit indented from it. Shared component, so this applies to the handbook and the guides too.
…op the lone crumb The sidebar started 1.5rem above the page body, so nothing lined up across the top. Its items sit indented further from their group header. A breadcrumb trail of one item names the page you are already on. It now renders only when there is somewhere to go back to.
FfExpertAsk carries the markup of the old /ai/ page's chat interface and modal and runs the same src/js/ai-expert-modal.js. The script now starts through a named init that runs whether or not DOMContentLoaded has fired, can run again after client-side navigation, and replaces its page-wide click listeners instead of stacking them. Answers come from the Expert service for the hosted site; in a local preview the request fails, as the script itself notes.
…home box The Expert conversation modal now lives once in the layout for all docs pages. The home page box carries the FlowFuse Expert branding above the text box, an Ask Docs button and support questions instead of workflow ideas. Elsewhere, and on the home page once that box scrolls away, an Ask FlowFuse Expert button at the top of the right-hand column opens the same conversation. ai-expert-modal.js: the entry button is handled by delegation so a box mounted after start-up works, the morph from the box only runs when the box opened the modal, a page can set the greeting, and window.ffExpertOpen() opens it from any button.
Below lg the docs sidebar and right-hand column are folded away, so docs pages get a search button and the FlowFuse Expert button in the header, styled like the Expert button in the FlowFuse app. To keep Book a demo on one line, the Expert button shows the FlowFuse mark alone below 600px and on tablets, and the square logo holds until 520px on docs pages. Measured from 360 to 1000px: no overflow beyond what the header already allows.
…r back on the button The dialog header now reads like a plain search bar: the input sits flat above the header's divider with no box or focus ring, the search icon is grey, and Cancel is an X (still named Close for screen readers). The input's own clear button is hidden so the X is the only one. The dialog carries an ff-search-dialog class, so the blog, changelog and handbook phone dialogs are unchanged. The sidebar button lost its border to algolia-theme.css, whose #algolia-search rule outranked the component's classes; the component's rule now includes the id.
…ents /docs now shows its single Docs crumb, so every docs page opens the same way. The right-hand Expert button moves below the table of contents and reads Ask Expert with the FlowFuse mark, like the compact header button, instead of the FlowFuse wordmark. On wide screens the column is capped to the window and a long table of contents scrolls inside itself, so the button under it stays in view.
The question box and the conversation modal now render FlowFuse Expert from one DocsExpertBrand component at the modal's size; the box's was larger. When the box morphs into the modal, its brand gets its own view transition and moves up into the modal header while the rest of the box morphs into the input area as before, and back again on close. Pages without a branded box (the Eleventy /ai/ page) are unaffected.
FlowFuse Expert now has one entry point on docs pages: a round Ask Docs button in the bottom-right corner at every screen width, which steps aside while a page's own question box is on screen. The Expert buttons in the right-hand column and in the phone and tablet header are gone, so the header keeps only the docs search there. DocsExpertButton is removed with them.
The right-hand column started 22px lower than the other two because the table of contents pads its own container. It now starts where the sidebar's search field does and centres its first line the same way, so the three columns share one top line. The column also no longer reserves room for the Expert button that moved to Ask Docs.
A 1px gray-200 line separates the sticky header from the page on every page, Nuxt and Eleventy alike, since both link this stylesheet. It is a shadow rather than a border, so the header height that --ff-header-height tracks does not change.
The floating button is now white with the FlowFuse mark and a slowly turning brand-red to indigo border, as the Expert button in the FlowFuse app is. Its box matches the header's Book a demo button (40px tall, 16px text, the same padding), keeping the pill shape.
A docs page whose frontmatter sets landing: true gets the full page width: no sidebar, no table of contents, no previous and next cards, and its body is not wrapped in .prose, because every block on it styles itself. The breadcrumb stays. Three content components build such a page from markdown, next to Nuxt UI's own cards, tabs and steps: - docs-hero: heading and line, the docs search (the page's Cmd+K search, since there is no sidebar), a row of buttons from a markdown list, and an aside slot beside them. - docs-section: eyebrow, heading and one line, then the section's cards or tiles. - docs-tiles: a markdown list of links as a grid of tiles, each clickable across its whole area; the links stay plain markdown so the flowfuse link check still sees them. AlgoliaSearch gains a taller lg size for the hero. The copy-command block no longer picks up the site-wide code box inside itself on pages outside .nohero.
docs-choices and docs-choice list the ways into FlowFuse, one open at a time: each opens to a line or two on what the option is, then its next step as a button and a guide as a link. They route to the pages that already walk through setup (the Device Agent install, the AI agent picker) rather than repeating them. Each choice is a native details element sharing one name, so the browser keeps a single one open with no script. docs-columns sets two blocks side by side, two thirds and one third, stacked on phones.
A card on a landing page that opens with a paragraph holding only a link takes that link as its title, and the link covers the whole card with a hover state. This replaces Nuxt UI's to attribute, whose URL the flowfuse docs link check misreads (it autolinks the text and keeps the closing quote and brace), and which left internal card links unchecked. A #title slot cannot stand in for it: inside these wrapper components MDC attaches a nested card's #title to the wrapper and swallows the card's closing fence.
FfExpertAsk lays out its box and its prompts as a two-row grid, and the box fills the height its row gives it. DocsColumns hands its first block both rows through subgrid, so that block's box shares the top row with the second column and the two stretch to one height, with the prompts below. The row gaps match; a subgrid with a different gap spreads the difference into its rows and left the box 4px taller.
The trail on /docs would be the single word Docs, so the home page leaves it out; every other docs page, landing or not, keeps its breadcrumb.
Autocomplete loads from a CDN after the page renders, so a detached search showed nothing but its Cmd+K hint until then; on the docs home, where the field leads the hero, that read as a missing search. A stand-in button of the same size now renders with the page and gives way once autocomplete mounts, with no layout shift. A click or Cmd+K before then opens the dialog as soon as it can; the shortcut listeners are set up right away.
FfExpertAsk drops its six prompt pills, so it is the question box alone and simply fills the height it is given; DocsColumns no longer needs a subgrid to line it up with the card beside it, plain grid stretching does. A card beside the Expert box now gets the same compact padding and type as cards in a card-group, and cards that follow the two-column block keep their distance. docs-choice states the rule for its links: one main call to action and at most one secondary action.
Docs pages show Docs beside the logo, linking to the docs home while the logo still goes to the site. On wide screens it pairs with the wordmark as one lockup: capitals as tall as the wordmark's (28px) on the same baseline, lighter and grey so the brand leads. Below 1024px it pairs with the square mark. On tablets the row had no other room (the menus cannot fold into More), so on docs pages Free Trial gives way there and Book a demo keeps its margin; it stays from 1024px up and on every other page.
The gap between the sidebar search and the first group heading was Nuxt UI's label padding, meant to separate a group from the one above, plus the nav's own top padding. The first heading has no group above, so both go, and the space under the search is set so the heading's capitals start on the same line as the page title's.
Docs beside the wordmark is now Heebo 700, whose stems (4px) match the wordmark's (3.9px), at 29px, which splits Heebo's proportions against the wordmark's (capitals 0.6px taller, lowercase 0.4px shorter), on the same baseline. On docs pages the wordmark now waits for xl: between 1024 and 1280px it brought the menus within 16px of Docs, while the square mark keeps at least 45px there, 70px or more from 1100px.
Between 1280 and 1536px the docs page and the header stop at the same max width but were padded differently (the page on the left only), so the sidebar search sat 12px right of the logo. The page now mirrors the header's padding from lg up. Group headings also drop Nuxt UI's label inset, which put them 10px right of the search field: they are headings over indented links, not link text.
Below xl the docs header no longer swaps in the separate square logo, which is drawn larger and in a lighter red: it shows the wordmark itself cropped to its mark, so the logo keeps one shape, colour and size and only its lettering comes and goes. Docs stays 29px at every width, now weight 600: its stems sit just under the wordmark's, 700 read too heavy. On phones below 390px the row cannot hold the mark, Docs, search, Book a demo and the menu, so there Book a demo gives way; from 390px it fits.
Without the prompt pills the box sat in a flex row that sized it to its content, so it shrank to a narrow strip and clipped its footnote. It now grows to the column's width as well as its height.
/docs spans more than the FlowFuse/flowfuse docs: the guides and the Node-RED library come from this repo. Its home therefore lives here, as nuxt/content-guides/README.md, which guides-sync overlays as the docs index. docs-sync stops copying the README at the root of the flowfuse docs tree, which stays that repository's own readme for its docs folder; syncing it neither writes nor removes the home page. Tests cover both the dev watcher's single-file sync and a full sync. The page is the landing page built from the docs-* components, with links to other pages of this site written relative so they resolve on any host, deploy previews included.
In the docs home's list of ways in, the second link of every option now leads to the page that explains the option: about FlowFuse Cloud, the Device Agent, self-hosting, FlowFuse MCP and FlowFuse applications. The first stays the step that starts it. The AI agent option, which had only its first step, gains its about link too.
Opening another option no longer moves the home page heading or the sections below. The hero aligns its columns to the top instead of centring the heading on the list, and the list keeps the height of its tallest open option, measured once mounted and again when its width changes (each option opened in turn with transitions off, in one synchronous pass). Opening and closing an option now animate its height with a short fade, using ::details-content and interpolate-size; a browser without them opens the option immediately, and reduced motion turns the animation off.
FlowFuse Expert on the docs (the Ask Docs button, the question box on the docs home and the conversation modal) ran on src/js/ai-expert-modal.js, which the Eleventy retirement removed from main, and the endpoint that script calls no longer answers without sign-in. This PR keeps the docs home, the header and the search dialog, and Ask Docs follows separately. Removed: DocsAskFab, DocsExpertHost, DocsExpertBrand, FfExpertAsk, useDocsExpert, and DocsColumns, which only held the question box. The layout goes back to main's. The Help section on the docs home keeps its wording without the Expert sentence, and the support card joins the other three cards in a two-column group.
At the wordmark's own size (29px, weight 600) the label read as a second logo on every docs page. It is now 13px, grey, set high beside the logo with its capital level with the wordmark's, like a superscript: it still says this is the docs, without competing with the brand. The smaller label frees room on phones, so Book a demo now gives way only below 360px instead of below 390px (at 360px the row has 20px to spare). The mark-only logo below xl stays: with the whole wordmark the menus would come within about 28px of "Docs" at 1100px.
A reviewer on #5495 asked why docs-sync/guides-sync materialize files into nuxt/content/docs by hand instead of using @nuxt/content's own collection primitives. Checked against the installed @nuxt/content (3.15.2, satisfies the ^3.13.0 this repo pins): a collection's `source` can be an array, each entry with its own `cwd`, and each is globbed and parsed independently at build time. That is enough for the guides authored in nuxt/content-guides/, since they are already MDC and already local: the `docs` collection now reads them straight from that directory as a second source (prefixed onto `docs/` so they land at the same paths), and the `content:file:beforeParse` hook that already existed for the blog collection now also stamps guide pages with their editUrl/updated frontmatter, in place of a copy step that used to write it into a duplicated file. guides-sync.mjs is what is left after that: copying the guides' non-markdown assets to public/docs (a content-collection source cannot do that), and a proactive collision check against FlowFuse/flowfuse's pages (a real collision now fails anyway, since the `docs` collection's `id` is a primary key, but as a SQL error rather than a message naming the file). The section-index README.md convention the guides borrowed from GitHub is renamed to index.md throughout, since @nuxt/content only special-cases the latter and this tree is ours to rename. docs-sync.mjs (the FlowFuse/flowfuse clone) is unchanged: its full-history clone can't become @nuxt/content's own git source, which only supports a shallow clone and would flatten every page's `updated` date to the sync commit - the reason the clone is not shallow already, predating this change. core-nodes-sync.mjs is unchanged for the same reason it was never a candidate: its input is an HTTP fetch, not files on disk, so it still writes into nuxt/content/docs like a build artifact, because it is one. Verified the source/prefix mechanics against @nuxt/content's own module code (resolveSource, defineLocalSource, the collection build loop) and with a standalone experiment reproducing the exact id/path computation for both sources - not just theoretically, but with real @nuxt/content code executed against toy directories, confirming the guides source resolves to the same /docs/... paths the old copy step produced. nuxt/lib/guides-sync.test.mjs is rewritten for the slimmed-down API.
Dropping the copy step took the guides out of the only path remark-docs-links recognised. It keys off a `/docs/` segment in the file's path on disk, which held while guides-sync materialized them into nuxt/content/docs, and stops holding now they are read straight out of nuxt/content-guides/. The plugin returned early on every guide page, so their relative image URLs reached the browser unresolved and the browser resolved them against the page's own URL: ./images/x.png on /docs/node-red/database/influxdb/ asked for /docs/node-red/database/influxdb/images/x.png and 404'd. The asset was copied to the right place throughout; only the URL was wrong. Three hundred-odd references across 33 pages, and nothing failed: the link checker sees the built HTML, where these are valid relative URLs, and the images themselves are not fetched. The path mapping moves to nuxt/lib so node --test can reach it, and it now understands both of the collection's sources. The test asserts over the real tree that every guide using a relative asset URL is one this can resolve, so the two cannot drift apart again without failing.
With the guides read as a collection source rather than copied in, a section index has to be named index.md, so the docs home added in #5866 follows the other guide indexes.
dimitrieh
force-pushed
the
docs/content-collections-instead-of-sync
branch
from
October 5, 2026 16:40
ddb9c47 to
5967a80
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Description
A reviewer asked on #5495 (comment) why the docs pipeline uses a custom sync script instead of
@nuxt/content's own collection primitives. This checks that against the installed version (3.15.2) and applies it where it genuinely helps.The guides overlay (
nuxt/content-guides/) is now a second source on thedocscollection, read directly from disk instead of being copied intonuxt/content/docsfirst. The frontmatter it used to inject during that copy now happens in the existingcontent:file:beforeParsehook.nuxt/content-guides/)docs-sync.mjs)core-nodes-sync.mjs)The other two sources stay as they are:
docs-sync.mjsneeds the full git history of each file it clones (for the "updated" date).@nuxt/content's own git source only does a shallow clone, which would date every page the same.core-nodes-sync.mjsgenerates pages from an HTTP fetch, not files on disk, so there is nothing to point a collection source at.Also renamed the guides'
README.mdsection-index files toindex.md, since@nuxt/contentonly recognizes the latter.What this does not solve: two of the three sync scripts are unchanged.
scripts/sync_docs.mjs(used outside a Nuxt build) no longer copies guide pages intonuxt/content/docs, only their non-markdown assets.Related Issue(s)
#5495 (comment)
Checklist