Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions docs/breaking_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,51 @@ title: Breaking Changes

# Breaking Changes & Deprecations

The introduction of new REST APIs in version 2 and the move to an operations based model has resulted in some version 1 paths being flagged for deprecation.
This document lists breaking changes and deprecations in Signal K Server.

It is recommended that applications and plugins referencing these deprecated paths update their operation to reference the version 2 paths.
---

## Admin UI: React 19 Migration

The Admin UI has been upgraded from React 16 to **React 19**. This is a significant update that may affect embedded webapps and plugin configuration panels.

### What Changed

| Component | Before | After |
| ------------ | ---------- | ---------- |
| React | 16.14.0 | 19.x |
| React DOM | 16.14.0 | 19.x |
| React Router | 4.x | 6.x |
| Language | JavaScript | TypeScript |

### Impact on Embedded Webapps

**If your webapp uses Module Federation to share React with the Admin UI:**

1. **Singleton sharing is now required** - Your webapp must configure React and ReactDOM as singletons with `requiredVersion: false`. See [vite.config.js](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/vite.config.js) for the current configuration.

2. **React 19 compatibility** - If your webapp bundles its own React, it should be compatible with components rendered by the host. Most React 16/17/18 code works unchanged in React 19, but some deprecated APIs have been removed.

3. **String refs removed** - React 19 no longer supports string refs (`ref="myRef"`). Use `useRef()` instead.

4. **`defaultProps` on function components** - Deprecated. Use JavaScript default parameters instead.

### Impact on Plugin Configuration Panels

Plugin configuration panels using `./PluginConfigurationPanel` export continue to work. The props interface remains the same:

- `configuration` - the plugin's configuration data
- `save` - function to save configuration

### No Impact

- **Standalone webapps** - Webapps that don't use Module Federation sharing are not affected
- **Server APIs** - All Signal K HTTP and WebSocket APIs remain unchanged
- **Plugin JavaScript APIs** - Server-side plugin APIs are not affected

---

## Changes
## REST API Changes

The following changes have been implemented with the introduction of **Resources API** and apply to applications using the `./signalk/v2/resources` endpoint.

Expand Down
40 changes: 23 additions & 17 deletions docs/develop/plugins/custom_renderers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ As of Signalk V 2.17.0, you'll notice that the path appears in the Data Browser

<img width="751" height="236" alt="Screenshot 2025-12-15 at 1 56 08 PM" src="https://github.com/user-attachments/assets/2514d3f7-9b6a-4f50-a6cf-d5e8868199a4" />

This is a Custom Renderer. The code for it is embedded in the DataBrowser package. See: [ValueRenderer.js](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/DataBrowser/ValueRenderers.js).
This is a Custom Renderer. The code for it is embedded in the DataBrowser package. See: [ValueRenderers.tsx](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/DataBrowser/ValueRenderers.tsx).

As of Signalk V 2.19.0, there are additional embedded Custom Renderers for Notifications, Attitude, Direction, Meters and Large Arrays.

Expand All @@ -30,30 +30,36 @@ const BoldRenderer = ({ value }) => {
}
```

There are more interesting examples in the ValueRenderer.js file.
There are more interesting examples in the ValueRenderers.tsx file.

## Making Your Renderer Available at Runtime

- Create a plugin
- Add your Component in a separate file (usually under [plugin dir]/src/component)
- Add webpack includes and scripts to your package.json
- Add build tool includes and scripts to your package.json (Webpack or Vite)
- Add keyword "signalk-node-server-addon" to your package.json
- Create a webpack.config.js (see any Plugin with their own configuration component) file that exports the renderer:

```
plugins: [
new ModuleFederationPlugin({
name: "Sample renderer",
library: { type: "var", name: packageJson.name.replace(/[-@/]/g, "_") },
filename: "remoteEntry.js",
exposes: {
"SampleRenderer": "./src/components/SampleRenderer",
},
shared: [{ react: { singleton: false, strictVersion: true } }],
}),
...
- Configure Module Federation to export the renderer. Example using Webpack:

```javascript
plugins: [
new ModuleFederationPlugin({
name: "Sample renderer",
library: { type: "var", name: packageJson.name.replace(/[-@/]/g, "_") },
filename: "remoteEntry.js",
exposes: {
"./SampleRenderer": "./src/components/SampleRenderer",
},
shared: {
react: { singleton: true, requiredVersion: false },
"react-dom": { singleton: true, requiredVersion: false }
},
}),
...
]
```

**Important:** Configure React as a singleton with `requiredVersion: false` to share the host's React 19 instance. See [vite.config.js](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/vite.config.js) for the Admin UI's configuration.

- Build your plugin (`npm run build`)

## Use Your Renderer
Expand Down
23 changes: 15 additions & 8 deletions docs/develop/webapps.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Signal K Server provides the following ways to add web-based user interfaces to
1. **Standalone WebApps** are web applications that when launched, the server Admin UI disappears and the webapp controls the whole page (browser window / tab).

2. **Embedded WebApps** are web applications that when launched, are **embedded in the server Admin UI**, leaving the toolbar and menu available to the user.
![vesselpositions](../img/vesselpositions.png 'Vesselpositions Embedded Webapp')

3. **Embedded Plugin Configuration Forms** are forms provided by a plugin that the server embeds within the _Plugin Config_ screen to replace the generic form rendered using the plugin _configuration schema_. This allows a richer set of controls to be provided for the user to configure the plugin compared to the more generice server generated form provides.
![calibration](../img/calibration.png 'Calibration plugin configuration form')
Expand Down Expand Up @@ -151,21 +150,29 @@ _Example response:_

## Embedded Components and Admin UI / Server interfaces

Embedded components are implemented using [Webpack Federated Modules](https://webpack.js.org/concepts/module-federation/) and [React Code Splitting](https://reactjs.org/docs/code-splitting.html).
Embedded components are implemented using [Module Federation](https://module-federation.io/) and [React Code Splitting](https://react.dev/reference/react/lazy).

_Note: There is no keyword for a module that provides only embedded components, use `signalk-webapp` instead._

You need to configured Webpack to create the necessary code for federation using _ModuleFederationPlugin_ and expose the component with fixed names:
You need to configure your build tool (Webpack or Vite) to create the necessary code for federation and expose the component with fixed names:

- embeddable webapp: `./AppPanel`
- plugin configuration form: `./PluginConfigurationPanel`
- embedded component: `./AddonPanel`

The ModuleFederationPlugin library name must match the package name and be a "safe" name for a webpack module like in `library: { type: 'var', name: packageJson.name.replace(/[-@/]/g, '_') },`
The ModuleFederationPlugin library name must match the package name and be a "safe" name for a module like in `library: { type: 'var', name: packageJson.name.replace(/[-@/]/g, '_') },`

The exposed modules need to `export default` a React component - both class based components and stateless functional components can be used. The server dependencies like `reactstrap` can and should be used. Add `@signalk/server-admin-ui-dependencies` as a dependency to the webapp, it defines the depedencies used by the server admin UI.
The exposed modules need to `export default` a React component. Functional components with hooks are recommended. The server dependencies like `reactstrap` can and should be used. Add `@signalk/server-admin-ui-dependencies` as a dependency to the webapp, it defines the dependencies used by the server admin UI.

See the vesselpositions embedded webapp/component and Calibration plugin for examples of each. It is probably easier to start with either one and modify them to suit your needs. Don't forget to change the module id and name in package.json!
### React Version Compatibility

The Admin UI uses **React 19** with shared dependencies via Module Federation. Your embedded webapp should:

1. **Share React as a singleton** - Configure Module Federation to use the host's React instance with `requiredVersion: false`. See [vite.config.js](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/vite.config.js) for the current configuration.

2. **Use functional components** - The Admin UI is built with functional components and React hooks. While class components still work, functional components are recommended for consistency.

See the Calibration plugin for an example. It is probably easier to start with an existing plugin and modify it to suit your needs. Don't forget to change the module id and name in package.json!

## WebApp / Component and Admin UI / Server interfaces

Expand All @@ -180,13 +187,13 @@ Embedded webapp properties:
- getting and setting application data
- opening an automatically reconnecting WebSocket connection to the server
- getting Signal K data via `get`
- [Embedded](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/Webapps/Embedded.js)
- [Embedded](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/Webapps/Embedded.tsx)

PluginConfigurationForm properties:

- `configuration` : the configuration data of the plugin
- `save`: function to save the configuration data
- [EmbeddedPluginConfigurationForm](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/Configuration/EmbeddedPluginConfigurationForm.js)
- [EmbeddedPluginConfigurationForm](https://github.com/SignalK/signalk-server/blob/master/packages/server-admin-ui/src/views/Configuration/EmbeddedPluginConfigurationForm.tsx)

**_Note: The documentation regarding embedded WebApps and Components provided at this time is rudimentary and should be considered under development as the concept is evolving._**

Expand Down
Binary file removed docs/img/vesselpositions.png
Binary file not shown.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@
"@signalk/set-system-time": "^1.5.0",
"@signalk/signalk-to-nmea0183": "^1.0.0",
"@signalk/udp-nmea-plugin": "^2.0.0",
"@signalk/vesselpositions": "^1.0.0",
"serialport": "^11.0.0",
"signalk-n2kais-to-nmea0183": "^2.0.0",
"signalk-to-nmea2000": "^2.16.0"
Expand Down
15 changes: 7 additions & 8 deletions packages/server-admin-ui-dependencies/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
},
"peerDependencies": {
"@fortawesome/fontawesome-free": "^5.15.1",
"bootstrap": "^4.5.3",
"@reduxjs/toolkit": "^2.3.0",
"bootstrap": "^5.3.3",
"font-awesome": "^4.7.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^5.1.2",
"react-select": "^3.1.0",
"reactstrap": "^5.0.0",
"redux": "^3.7.2",
"redux-thunk": "2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-redux": "^9.1.2",
"react-select": "^5.10.2",
"reactstrap": "^9.2.3",
"simple-line-icons": "^2.5.5"
}
}
3 changes: 2 additions & 1 deletion packages/server-admin-ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ Thumbs.db
.env
.idea
npm-debug.log
compilation-stats.json
compilation-stats.json
bundle-stats.html
4 changes: 2 additions & 2 deletions packages/server-admin-ui/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ jspm_packages

src
public_src
webpack.config.js
scss
vite.config.js
tsconfig.json
compilation-stats.json
.babelrc
public/*.hot-update.js
public/*.hot-update.json
public/stats.json
18 changes: 16 additions & 2 deletions packages/server-admin-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@ Used within the [Signal K](http://signalk.org) [Node Server](https://github.com/

This is its own package so when its installed the javascript asset files come compiled. It makes the build process from the git repo easier and more efficient.

## Technology Stack

- **React 19** with functional components and hooks
- **TypeScript** for type safety
- **Vite** for fast builds with Module Federation support
- **Redux** for state management (with `useSelector`/`useDispatch` hooks)
- **React Router v6** for routing
- **Reactstrap 9** with Bootstrap 5 for UI components

## Development

- Install dev packages with `npm i`.
- Edit files with `/src`.
- Run `npm run prepublishOnly`
- Edit files within `/src`.
- Run `npm run build` to build
- Run `npm run prepublishOnly` for production build
- `npm link`
- `cd ../../`
- `npm link @signalk/server-admin-ui`
- Restart signalk `npm start`

## Module Federation

The Admin UI supports embedded webapps and plugin configuration panels via Module Federation. External webapps can share React and ReactDOM as singletons to ensure compatibility. See the main [WebApps documentation](../../docs/develop/webapps.md) for details on building embedded components.
38 changes: 20 additions & 18 deletions packages/server-admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,47 @@
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/preset-react": "^7.10.4",
"@fortawesome/fontawesome-free": "^5.15.1",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@fortawesome/react-fontawesome": "^3.1.1",
"@module-federation/vite": "^1.0.10",
"@rjsf/bootstrap-4": "^5.24.13",
"@reduxjs/toolkit": "^2.3.0",
"@rjsf/core": "^5.24.13",
"@rjsf/utils": "^5.24.13",
"@rjsf/validator-ajv8": "^5.24.13",
"@signalk/server-admin-ui-dependencies": "1.0.1",
"@types/escape-html": "^1.0.4",
"@types/lodash.remove": "^4.7.9",
"@types/lodash.set": "^4.3.9",
"@types/lodash.uniq": "^4.5.9",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@types/react-redux": "^7.1.34",
"@vitejs/plugin-react": "^4.3.4",
"ansi-to-html": "^0.6.14",
"bootstrap": "^4.5.3",
"bootstrap": "^5.3.3",
"buffer": "^6.0.3",
"escape-html": "^1.0.3",
"font-awesome": "^4.7.0",
"jsonlint-mod": "^1.7.6",
"lodash.remove": "^4.7.0",
"lodash.set": "^4.3.2",
"lodash.uniq": "^4.5.0",
"moment": "^2.29.1",
"react": "^16.14.0",
"react-bootstrap": "^1.6.8",
"react-copy-to-clipboard": "^5.0.3",
"react-dom": "^16.14.0",
"react-html-parser": "^2.0.2",
"dayjs": "^1.11.13",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"html-react-parser": "^5.2.5",
"react-infinite-scroll-component": "^6.1.0",
"react-json-tree": "^0.20.0",
"react-redux": "^5.1.2",
"react-router-dom": "^4.3.1",
"react-select": "^3.1.0",
"reactstrap": "^5.0.0",
"react-redux": "^9.1.2",
"react-router-dom": "^6.28.0",
"react-select": "^5.10.2",
"reactstrap": "^9.2.3",
"reconnecting-websocket": "^4.4.0",
"redux": "^3.7.2",
"redux-thunk": "2.3.0",
"rollup-plugin-visualizer": "^5.12.0",
"sass": "^1.81.0",
"simple-line-icons": "^2.5.5",
"typescript": "^5.7.2",
"vite": "^6.0.5"
},
"scripts": {
Expand Down
10 changes: 9 additions & 1 deletion packages/server-admin-ui/scss/_bootstrap-variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $pink: #e83e8c !default;
$red: #f86c6b;
$orange: #f8cb00;
$yellow: #ffcc00 !default;
$green: #4dbd74;
$green: #00cd79;
$teal: #20c997 !default;
$cyan: #63c2de;

Expand Down Expand Up @@ -80,6 +80,7 @@ $breadcrumb-margin-bottom: 1.5rem;

// Cards

$card-bg: $white;
$card-border-color: $gray-200;
$card-cap-bg: $gray-100;

Expand All @@ -99,11 +100,18 @@ $progress-bg: $gray-100;

// Tables

$table-bg: $white;
$table-bg-accent: $gray-100;
$table-bg-hover: $gray-100;

// Forms

$input-bg: $white;
$input-focus-bg: $white;
$input-group-addon-bg: $gray-100;
$input-border-color: $gray-200;
$input-group-addon-border-color: $gray-200;

// List groups

$list-group-bg: $white;
Loading