From 658161831c08a121c46ad66feaa1e313de325e75 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Fri, 23 Oct 2026 23:22:36 +0200 Subject: [PATCH 1/3] ci: run workflows on Node 22 postcss-html 2.0.0 (via the stylelint toolchain) requires Node ^22.12 or >=24, so pnpm install fails with ERR_PNPM_UNSUPPORTED_ENGINE on Node 20 and every lint, bundle and storybook job is red, on main and on every PR. The Dockerfiles already build on node:22. The package's engines field stays >=20: the requirement is a dev-toolchain one. Claude-Session: https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee --- .github/workflows/api-docs.yml | 2 +- .github/workflows/api-lint.yml | 2 +- .github/workflows/flowdrop-bundle.yml | 2 +- .github/workflows/flowdrop-lint.yml | 2 +- .github/workflows/flowdrop-storybook.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml index dafdae4f..ee705397 100644 --- a/.github/workflows/api-docs.yml +++ b/.github/workflows/api-docs.yml @@ -29,7 +29,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'pnpm' cache-dependency-path: apps/api-docs/pnpm-lock.yaml diff --git a/.github/workflows/api-lint.yml b/.github/workflows/api-lint.yml index 20b39c37..a27715e6 100644 --- a/.github/workflows/api-lint.yml +++ b/.github/workflows/api-lint.yml @@ -35,7 +35,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'pnpm' cache-dependency-path: apps/api-docs/pnpm-lock.yaml diff --git a/.github/workflows/flowdrop-bundle.yml b/.github/workflows/flowdrop-bundle.yml index 48b7f80a..f8c7b76d 100644 --- a/.github/workflows/flowdrop-bundle.yml +++ b/.github/workflows/flowdrop-bundle.yml @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'pnpm' cache-dependency-path: libs/flowdrop/pnpm-lock.yaml diff --git a/.github/workflows/flowdrop-lint.yml b/.github/workflows/flowdrop-lint.yml index 38fd364c..ad0056aa 100644 --- a/.github/workflows/flowdrop-lint.yml +++ b/.github/workflows/flowdrop-lint.yml @@ -35,7 +35,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'pnpm' cache-dependency-path: libs/flowdrop/pnpm-lock.yaml diff --git a/.github/workflows/flowdrop-storybook.yml b/.github/workflows/flowdrop-storybook.yml index 49b777aa..397f9cfe 100644 --- a/.github/workflows/flowdrop-storybook.yml +++ b/.github/workflows/flowdrop-storybook.yml @@ -37,7 +37,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'pnpm' cache-dependency-path: libs/flowdrop/pnpm-lock.yaml From d2bdee8deb163b71aee507b59339a516007258eb Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Fri, 23 Oct 2026 23:28:54 +0200 Subject: [PATCH 2/3] ci: pin the Storybook runner, fix the oasdiff install, type nullable schemas - Storybook: ubuntu-latest is now 26.04, where Playwright cannot install Chromium. Pin ubuntu-24.04. - oasdiff's install script now installs to /usr/local/bin itself; the following mv found nothing and failed the job. - OpenAPI lint: nullable needs a sibling type (struct rule). The two allOf + nullable properties on PlaygroundChatBinding and WorkflowPlayground gain type: object. Claude-Session: https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee --- .github/workflows/api-lint.yml | 2 +- .github/workflows/flowdrop-storybook.yml | 2 +- libs/flowdrop/api/v1/bundled.yaml | 2 ++ libs/flowdrop/api/v1/components/schemas/workflow.yaml | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/api-lint.yml b/.github/workflows/api-lint.yml index a27715e6..9913d425 100644 --- a/.github/workflows/api-lint.yml +++ b/.github/workflows/api-lint.yml @@ -72,7 +72,7 @@ jobs: - name: Install oasdiff run: | curl -sSL https://raw.githubusercontent.com/Tufin/oasdiff/main/install.sh | sh - sudo mv oasdiff /usr/local/bin/ + oasdiff --version - name: Check for breaking changes run: | diff --git a/.github/workflows/flowdrop-storybook.yml b/.github/workflows/flowdrop-storybook.yml index 397f9cfe..7b5ac2ae 100644 --- a/.github/workflows/flowdrop-storybook.yml +++ b/.github/workflows/flowdrop-storybook.yml @@ -21,7 +21,7 @@ on: jobs: storybook: name: Stories pass as tests, Storybook builds - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 # Playwright cannot install Chromium on 26.04 defaults: run: working-directory: libs/flowdrop diff --git a/libs/flowdrop/api/v1/bundled.yaml b/libs/flowdrop/api/v1/bundled.yaml index 55ab6ad6..1e22f7a4 100644 --- a/libs/flowdrop/api/v1/bundled.yaml +++ b/libs/flowdrop/api/v1/bundled.yaml @@ -6684,6 +6684,7 @@ components: nullable: true description: Interface input that receives the person's message. history: + type: object allOf: - $ref: '#/components/schemas/PlaygroundChatHistory' nullable: true @@ -6716,6 +6717,7 @@ components: binding. properties: chat: + type: object allOf: - $ref: '#/components/schemas/PlaygroundChatBinding' nullable: true diff --git a/libs/flowdrop/api/v1/components/schemas/workflow.yaml b/libs/flowdrop/api/v1/components/schemas/workflow.yaml index c512993c..f89a3a9a 100644 --- a/libs/flowdrop/api/v1/components/schemas/workflow.yaml +++ b/libs/flowdrop/api/v1/components/schemas/workflow.yaml @@ -365,6 +365,7 @@ PlaygroundChatBinding: nullable: true description: Interface input that receives the person's message. history: + type: object allOf: - $ref: '#/PlaygroundChatHistory' nullable: true @@ -398,6 +399,7 @@ WorkflowPlayground: binding. properties: chat: + type: object allOf: - $ref: '#/PlaygroundChatBinding' nullable: true From f0e3265be7c478047ce51eba9ed2c05ac2968d2a Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Fri, 23 Oct 2026 21:13:28 +0200 Subject: [PATCH 3/3] feat(app): forward a navbarEnd snippet to the navbar Claude-Session: https://claude.ai/code/session_01XR2k7eeSeAKTuptqh4uyee --- libs/flowdrop/CHANGELOG.md | 9 +++ libs/flowdrop/src/lib/components/App.svelte | 7 +++ libs/flowdrop/src/lib/svelte-app.ts | 9 +++ .../src/routes/test/editor/+page.svelte | 7 +++ .../tests/e2e/editor-branding.spec.ts | 13 ++++ .../tests/unit/mount/navbarEnd.test.ts | 60 +++++++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 libs/flowdrop/tests/unit/mount/navbarEnd.test.ts diff --git a/libs/flowdrop/CHANGELOG.md b/libs/flowdrop/CHANGELOG.md index f1f31fe8..eea20482 100644 --- a/libs/flowdrop/CHANGELOG.md +++ b/libs/flowdrop/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- **`App` takes a `navbarEnd` snippet.** It renders at the navbar's trailing end, before the settings + gear, so a host can put its own controls there, such as a user menu. `Navbar` already had this as + its `end` slot; `App` now forwards it. It shows only when the navbar does. `mountFlowDropApp` takes + the same `navbarEnd` option. + ## [2.15.2] - 2026-10-18 ### Fixed diff --git a/libs/flowdrop/src/lib/components/App.svelte b/libs/flowdrop/src/lib/components/App.svelte index 23f3d022..6df3c557 100644 --- a/libs/flowdrop/src/lib/components/App.svelte +++ b/libs/flowdrop/src/lib/components/App.svelte @@ -195,6 +195,11 @@ navbarActions?: NavbarAction[]; /** White-label logo for the navbar (replaces the FlowDrop wordmark) */ branding?: NavbarBranding; + /** + * Host content at the navbar's trailing end, before the settings gear (the + * navbar's `end` slot), e.g. a user menu. Only shown with the navbar. + */ + navbarEnd?: Snippet; /** Show settings gear icon in navbar */ showSettings?: boolean; /** Show the "Connected" status indicator in the navbar (default: true) */ @@ -283,6 +288,7 @@ navbarTitle, navbarActions = [], branding, + navbarEnd, showSettings = true, showStatus = true, apiBaseUrl, @@ -2124,6 +2130,7 @@ {showStatus} {showSettings} {branding} + end={navbarEnd} saveShortcut onWorkflowSettings={toggleWorkflowSettings} status={doctorStatus} diff --git a/libs/flowdrop/src/lib/svelte-app.ts b/libs/flowdrop/src/lib/svelte-app.ts index 021feb5b..618664d2 100644 --- a/libs/flowdrop/src/lib/svelte-app.ts +++ b/libs/flowdrop/src/lib/svelte-app.ts @@ -8,6 +8,7 @@ */ import { mount, unmount } from 'svelte'; +import type { Snippet } from 'svelte'; import WorkflowEditor from './components/WorkflowEditor.svelte'; import App from './components/App.svelte'; import type { @@ -167,6 +168,12 @@ export interface FlowDropMountOptions { * logo's accessible name, `logoAlt` overrides the logo's accessible name, `href` an optional link around it. */ branding?: NavbarBranding; + /** + * Host content at the navbar's trailing end, before the settings gear, e.g. a + * user menu. Only shown with the navbar. A Svelte host passes a snippet from its + * template; other hosts can build one with `createRawSnippet`. + */ + navbarEnd?: Snippet; /** Show settings gear icon in navbar */ showSettings?: boolean; /** Show the "Connected" status indicator in the navbar (default: true) */ @@ -741,6 +748,7 @@ export async function mountFlowDropApp( navbarTitle, navbarActions, branding, + navbarEnd, showSettings, showStatus, authProvider, @@ -838,6 +846,7 @@ export async function mountFlowDropApp( navbarTitle, navbarActions, branding, + navbarEnd, showSettings, showStatus, endpointConfig: config, diff --git a/libs/flowdrop/src/routes/test/editor/+page.svelte b/libs/flowdrop/src/routes/test/editor/+page.svelte index 934aefb5..b00588e4 100644 --- a/libs/flowdrop/src/routes/test/editor/+page.svelte +++ b/libs/flowdrop/src/routes/test/editor/+page.svelte @@ -246,6 +246,9 @@ : undefined ); + // --- Host content at the navbar's end (?navbarEnd=1), e.g. a user menu --- + let showNavbarEnd = $derived($page.url.searchParams.get('navbarEnd') === '1'); + // --- White-label logo (?branding=1 name + image; =alt adds logoAlt; =name name only; =wide a logo far wider than the start column) --- const brandingSvg = (width: number) => `data:image/svg+xml;utf8,${encodeURIComponent( @@ -1653,8 +1656,12 @@ {contextMenu} {branding} {navbarActions} + navbarEnd={showNavbarEnd ? navbarEndContent : undefined} {settingsCategories} /> + {#snippet navbarEndContent()} + Ada Lovelace + {/snippet}