Sea & Sea web dashboard
A browser-based live dashboard connecting directly to Signal K via WebSocket. Four pages: tanks, power, tides and environment. Designed to run full-screen on a phone mounted at the helm.
Project links
What it does
This is a set of plain HTML/CSS/JavaScript files that run in any browser on the boat's local network. There is no backend, no server-side rendering, no build step — just static files. The browser connects directly to the Signal K WebSocket stream and updates the display in real time. Tide data comes from a local Node.js tide service running on the Raspberry Pi alongside Signal K. The primary target device is a Nothing Phone 3a Pro mounted at the helm, but it works on any modern browser.
File structure
| File | Purpose |
|---|---|
dashboard.html | Main dashboard page. Four page containers (tanks, power, tides, environment), a fixed bottom navigation bar, and all live data elements. Load this in the browser. |
script.js | All application logic: WebSocket connection to Signal K, tide API fetch, update functions for every data element on every page, page navigation handlers. |
style.css | Dark theme mobile-first CSS. No scroll on any page. Fixed bottom nav bar. Visual tank gauges via CSS height/fill. |
config.js | Connection configuration — Signal K WebSocket URL and tide service URL. Edit this file to point at your own setup. |
index.html | Simple redirect/landing page to dashboard.html |
Configuration — the only file you need to edit
All connection settings are in config.js:
window.APP_CONFIG = {
signalKUrl: 'ws://10.1.1.12:3000/signalk/v1/stream',
tideUrl: 'http://10.1.1.12:3123/tide'
};
Change 10.1.1.12 to the IP address of your Signal K server. Change port 3000 if your Signal K runs on a different port. The tideUrl points to a small local Node.js service that serves tide data from the Admiralty API — replace with any URL that returns tide JSON in the expected format, or remove tide functionality if not needed.
Per-device overrides are supported: set window.APP_CONFIG before config.js loads to override the defaults for a specific device without editing the shared file.
Signal K paths consumed
| Page | Signal K path | Display usage |
|---|---|---|
| Tanks | tanks.water.port.currentLevel | Port water tank gauge and percentage |
| Tanks | tanks.water.centre.currentLevel | Centre water tank gauge |
| Tanks | tanks.water.starboard.currentLevel | Starboard water tank gauge |
| Tanks | tanks.fuel.port.currentLevel | Port fuel tank gauge |
| Tanks | tanks.fuel.starboard.currentLevel | Starboard fuel tank gauge |
| Tanks | environment.inside.temperature.port_water_tank | Port tank compartment sensor |
| Tanks | environment.inside.humidity.port_water_tank | Port tank compartment humidity |
| Power | electrical.batteries.bmv712.voltage | House battery voltage |
| Power | electrical.batteries.starter.voltage | Starter/generator battery voltage |
| Power | electrical.solar.MPPTport.panelPower | Port solar panel power (W) |
| Power | electrical.solar.MPPTstarboard.panelPower | Starboard solar panel power (W) |
| Power | electrical.solar.MPPTport.yieldToday | Port solar yield today (Wh) |
| Power | electrical.solar.MPPTstarboard.yieldToday | Starboard solar yield today (Wh) |
| Tides | environment.depth.belowKeel | Current depth |
| Tides | environment.water.temperature | Water temperature (K → °C) |
How the WebSocket connection works
On page load, script.js opens a WebSocket connection to the Signal K stream URL from config.js. Signal K immediately begins sending all data updates as JSON messages. The script maintains a data store object and updates it on every message received. Each page has update functions that read from this store and update the DOM.
Automatic reconnection is handled — if the WebSocket drops (e.g. Signal K restarts), the script waits a few seconds and reconnects. A connection status indicator shows the current state.
Tide data is fetched via HTTP from the local tide service on page load and every 10 minutes. The tide service (running on the Raspberry Pi) calls the UK Admiralty API and caches the result, so the dashboard doesn't need internet access or an API key directly.
Deploying to your own boat
- Copy the four files (
dashboard.html,script.js,style.css,config.js) to any web server accessible on your boat network, or simply opendashboard.htmldirectly as a file (file://...) — the WebSocket connection works either way as long as the browser can reach the Signal K server. - Edit
config.jsto point at your Signal K server IP and port. - If you don't have the local tide service, you can remove the tide fetch call from
script.jsor replacetideUrlwith any compatible endpoint. - Open
dashboard.htmlin the browser, add it to the home screen for a full-screen experience on mobile.
The dashboard works entirely offline once loaded — it only needs network access to reach the Signal K server, which is on the boat's local WiFi. No internet connection is required during normal use.
Adding your own data points
The pattern throughout script.js is consistent: add a new path to the WebSocket message handler (where paths are matched and values stored), then add an update call to the relevant page's update function, and add the corresponding HTML element in dashboard.html. The architecture document in the repo (ARCHITECTURE.md) lists all current and planned data points with their Signal K paths.
The environment page is currently a placeholder — it is intended for additional sensors such as cabin temperature, barometric pressure and wind, as more ESP32 devices are added to the boat.