npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

signalk-chart-locker

v0.9.0

Published

Signal K plugin that runs a Rust container alongside the server for a boat-wide tile cache, a PMTiles chart provider, and saved downloadable map regions.

Readme

Chart Locker

npm version npm downloads CI License node Buy Me a Coffee

A Signal K plugin that runs a Rust container alongside the server to host a shared tile cache and local PMTiles chart serving.

The cached tiles and local chart files are advisory. They are not certified for safety-of-life navigation: always cross-check against official charts and your primary instruments.

What's new in 0.9.0

Version 0.9.0 rebuilds the configuration panel on signalk-nearlcrews-ui 0.11.1. A render failure inside the panel now offers "Try again" and "Reload page" in place, instead of the Signal K Admin host replacing the whole panel with its generic unavailable notice. A save blocked by an invalid field refuses in place and names the field to fix, rather than leaving a keyboard operator standing on a control that vanished. Fields show their unit beside the input and read it with the value, the theme selector labels its group and its two automatic choices, and a maintenance action that runs past its budget still reports the words the button that started it used.

The plugin keeps an actionable startup problem, a missing signalk-container or an unmounted external cache path, in the status line instead of overwriting it with the generic line that says tile caching is disabled, and it says so when a server leaves the management API unmounted. A charts directory that was rejected at start is polled like any other, so repairing it serves the archives in it without a plugin restart, and the poll rescans only when that directory has actually changed. signalk-container is no longer a peer dependency, so installing this plugin no longer installs a second plugin under it. The tile-cache container reports its log lines as event= key value pairs, which the operations guide lists.

See the 0.9.0 changelog for the full list.

What it does

Chart Locker is a Signal K server plugin. It manages a container (via the signalk-container plugin) that runs a Rust service alongside the server. That service handles the shared tile cache that every device on the boat reads from. The Node.js plugin discovers and serves local .pmtiles charts with proper HTTP caching semantics, independently of the container runtime.

The plugin side is thin by design. It resolves the signalk-container manager, starts the tilecache container, and exposes the regions and chart-management HTTP routes. All tile-cache compute lives in the container.

The tilecache container also reports its update state in the signalk-container Container Manager panel: an "up to date" badge, a "checked N ago" timestamp, and a "Check now" button. The check reads the GitHub releases of this repository, and because the container image tag is pinned to the plugin version, "update available" means a newer Chart Locker release exists: update the plugin in the App Store and the container is recreated on the new tag. Offline at sea the check reports the last cached result and never fabricates an update. The badge needs signalk-container 1.20.2 or newer; older versions skip the registration and everything else works unchanged.

When Chart Locker is absent, the Binnacle chartplotter falls back to direct upstream sources for tiles. A standalone install of Binnacle is unaffected.

Features

  • Shared boat-wide tile cache. Every raster overlay, the vector basemap, and its glyphs are fetched and cached through the Signal K server. Every device on the boat reads from the same cache, the same tile is never fetched more than once, and the overlays keep rendering offline at sea. Learned vector-style metadata is stored with the cache, so warmed styles, glyphs, sprites, and tiles remain routable after the container restarts without internet access.
  • Saved regions. Draw a box in the Binnacle chartplotter and download the raster overlays and the vector basemap covering it into the shared cache before leaving internet coverage. A region that includes a vector basemap also stores its glyphs and sprites, so the basemap renders offline. Each region is named automatically by an optional reverse geocode, saved durably, and can be re-downloaded or deleted. A live byte estimate is re-validated on the server against the saved-regions budget before the download starts, so an over-budget region is refused. The region tiles are pinned and never evicted, and a region never stays stuck downloading.
  • Auto-cache around the boat. An optional throttled fill keeps a small tile radius warm around the vessel as it travels outside the saved regions, always LRU-bounded so it never displaces the pinned coverage. A radius that crosses the antimeridian is split into two bounded boxes and completed as one warm job.
  • Local PMTiles chart provider. Drop .pmtiles archives in the charts folder and the plugin discovers, validates, and registers them without a plugin restart. Each archive is served with a strong ETag and HTTP Range support so the browser cache works. A chart-management panel in the Binnacle chartplotter lists the detected archives. Defers gracefully to signalk-pmtiles-plugin when that plugin is enabled.
  • Operational configuration panel. Inspect cache usage, filesystem headroom, source health, diagnostics, and chart discovery without leaving the Signal K admin UI. Change scroll retention, clear only unpinned scroll tiles, refresh live state, and request a chart rescan from the same panel. The panel uses the accessible, theme-aware signalk-nearlcrews-ui primitives and shares its Auto, System, Light, Dark, and Night preference with other NearlCrews plugin panels. Auto follows an explicit host theme and otherwise uses Light, while System follows the operating-system color scheme.

Requirements

  • Signal K server >= 2.24.0, which provides the React 19.2 Admin host required by the configuration panel.
  • Node.js >= 22.
  • A Signal K Admin browser or embedded WebView with native CSS @scope: Chromium or Edge 118, Firefox 146, or Safari 17.4 and newer.
  • signalk-container >= 1.20.0 and a container runtime (Podman or Docker) accessible to Signal K are required for tile caching, saved-region downloads, position warming, and reverse geocoding. Local PMTiles discovery and serving continue without them. Version 1.20.2 or newer is recommended for the Container Manager update badge.
  • Binnacle Chartplotter 0.15.4 or newer for reliable saved-region create and re-download recovery, plus the regions and chart-management panels. Binnacle 0.15.3 and older do not accept Chart Locker's recovery-pending response.

On secured Signal K servers that expose scoped plugin routers, chart tiles, styles, readiness checks, and PMTiles files are available to authenticated readonly, readwrite, and administrator users. Servers without that router API preserve the legacy public-read routes required by chart clients. Saving regions, changing cache settings, reverse geocoding, and editing chart metadata always require an administrator session. Signal K servers with security disabled expose the read routes without a login.

Installation

From the App Store (recommended). In the Signal K admin UI, open Apps and Plugins, then Store, search for Chart Locker, and install. Restart the server when prompted.

With npm. Install into the server's home directory and restart Signal K:

cd ~/.signalk
npm install signalk-chart-locker

Configuration

After installation, enable the plugin in the Signal K plugin configuration panel. Chart Locker starts the tilecache container automatically when Signal K restarts. No further configuration is required for the tile cache or the PMTiles provider.

Tile cache capacity. The cache cap slider moves in 4 GiB steps from 4 through 32 GiB. On a new configuration, the panel recommends a share of the free space on the filesystem that will hold the cache: about 80 percent when at least 16 GiB is free, and about 50 percent below that so a small disk keeps more headroom. The recommendation is floored to the nearest 4 GiB, never drops below 4 GiB, and never exceeds 32 GiB. When an external cache path is configured and available, its filesystem is measured. If it is unavailable, the panel clearly reports that free-space guidance has fallen back to the Signal K data filesystem.

The saved-regions budget is a ceiling on pinned region tiles. Leave it at 0 to use half the cache cap. It must not exceed the cache cap. This budget does not remove space from the scroll cache until a region is saved. A region download pins its tiles and evicts only unpinned scroll tiles to make room. Pinned tiles are never evicted by scroll-cache pressure.

Cache-cap reductions are applied transactionally. If the requested cap is below the bytes that saved coverage currently pins, the tile cache rejects the reduction without publishing partial settings. The previous container configuration remains active when one exists; a fresh container whose retained database already exceeds its first requested cap remains unconfigured. Increase the cap, or delete saved coverage and redownload only the regions that fit, before retrying the lower value.

The settings panel also provides live cache operations: total, pinned, and scroll usage; remaining saved-region headroom; actual filesystem free space; per-source usage and upstream health; scroll retention; and a safe clear action that preserves saved-region tiles. The cache keeps 256 MiB of filesystem headroom outside its configured cap. Under disk pressure it continues serving fetched tiles without writing them and reports the degraded state in the panel.

Scroll retention. Set retention from 0 through 365 days. A value of 0 disables age-based removal. The clear action removes every unpinned scroll tile and preserves saved-region and other pinned tiles. Retention changes are persisted even when the container is temporarily unavailable and are pushed again on the next start.

External cache drive. The Advanced section accepts an absolute host path for a USB SSD, NVMe drive, or other cache filesystem. A relative path is rejected. Create the directory first, and make sure a removable drive is mounted before Signal K starts. With the default rootless Podman mapping, grant the Signal K host user read and write access. With Docker or rootful Podman configurations that retain container IDs, grant UID and GID 65532 access. If disableUserNamespaceRemap is enabled, verify the effective host ownership used by the runtime and grant that identity access. Chart Locker treats the path as required and refuses to start the tilecache instead of silently filling the Signal K data filesystem when the path is absent. The PMTiles provider remains available, and the plugin error identifies the missing path.

Reverse geocoding. Region auto-naming is enabled by default and can be disabled in Advanced. When enabled, starting a region download may send the box-center latitude and longitude, rounded to five decimal places, to OpenStreetMap Nominatim. The container applies one application-wide request per second, keeps up to 256 successful lookups in memory for 24 hours, and never sends a request while the control is disabled. The cache is cleared when the container restarts. A disabled or unavailable geocoder does not block a region download; the chartplotter uses an editable coordinate-derived name.

PMTiles charts. Place .pmtiles files in charts/pmtiles under the Signal K configuration directory, which is ~/.signalk/charts/pmtiles on a default install. Chart Locker creates that directory on first start, then detects and registers archives automatically. To use a different directory, set the PMTiles charts directory in the plugin configuration to a path relative to the Signal K configuration directory. If signalk-pmtiles-plugin is already enabled, Chart Locker surfaces a clear status and defers to it.

Vector (MVT) and raster (PNG, JPEG, WebP, and AVIF) PMTiles archives are all supported. An archive with any other tile type is reported as invalid in the panel.

The panel reports valid and invalid archives, their latest scan time, and each validation error. Use the Rescan charts action after copying files when an operating-system watch event was delayed.

The charts path must be relative to the Signal K configuration directory and cannot escape it with ... The optional image tag in Advanced must be a valid OCI tag. Invalid settings are shown next to the configuration and rejected again by the plugin before any container work starts.

Saving cache limits, chart discovery settings, or container settings can reapply configuration or recreate the tile-cache container. The panel summarizes that restart impact before saving.

Reliability and recovery

Chart Locker probes the tilecache through the host-side address that Signal K uses. After three consecutive failures, it runs the healthcheck inside the container. If the container is healthy but the published port is unreachable, Chart Locker restarts the container, resolves the port again, and restores its source and budget configuration before reporting recovery. Failed recovery attempts are rate-limited for five minutes and remain visible in the plugin status.

The health payload also carries configuration readiness, so an automatic Docker or Podman restart that leaves the process healthy but clears its in-memory sources triggers the same configuration restore without another container restart.

  • State files are written through a flushed temporary file and atomically renamed, preventing a partial JSON document after power loss.
  • A database-aware health check verifies SQLite before the container reports healthy. The plugin separately reports whether the source and budget configuration push has completed.
  • If the disposable cache database is recreated, saved regions whose pinned bytes disappeared are marked needs-redownload instead of remaining falsely ready.
  • A rejected or failed region replacement keeps the prior usable pins. Accepted warm starts whose response is lost are recovered by region ID, while a confirmed missing job is reconciled to an error instead of leaving the region stuck downloading.
  • Position-warm, saved-region, chart override, and direct plugin configuration inputs are validated at their server boundaries.

See Operations for status interpretation, diagnostics, recovery procedures, and structured log events. See the HTTP API for the plugin routes and validation limits.

Configuration panel

| Light | Dark | Night red | | ----- | ---- | --------- | | Light configuration panel | Dark configuration panel | Night-red configuration panel |

Development

This project targets Node.js 22 or newer. The Rust container is a Cargo workspace under container/ and uses the pinned Rust 1.98.0 toolchain. TypeScript compilation uses the 7.0 native compiler, while ESLint's type-aware parser uses the TypeScript 6 compiler API compatibility package. ESLint remains on the latest 9.x release until neostandard and eslint-plugin-react support ESLint 10.

git clone https://github.com/NearlCrews/signalk-chart-locker.git
cd signalk-chart-locker
npm ci
npx --no-install playwright install --with-deps chromium firefox webkit # one-time browser install
npm run typecheck   # TypeScript type-check
npm run lint        # ESLint
npm test            # node --test unit tests
npm run test:browser:cross # production panel remote in Chromium, Firefox, WebKit, and mobile Chromium
npm run build       # clean and compile dist/, then build the panel remote
npm run check:package
npm run licenses:rust:check # verify locked Rust runtime attribution
npm audit           # runtime and build-time dependencies

Rust (Cargo workspace):

cd container
cargo test --locked --workspace --all-features
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
cargo build --locked --release --bin tilecache --all-features
cargo install cargo-audit --version 0.22.2 --locked
cargo audit --file Cargo.lock
cd ..
TILECACHE_BIN="$PWD/container/target/release/tilecache" npm run test:node-rust-contract

Before a release, also verify the panel in a real browser and follow the repository's protected release workflow. Publishing the npm package or creating the version tag requires explicit owner approval.

License

The Node.js plugin is MIT licensed. The Rust tile-cache workspace is Apache-2.0 licensed. See the MIT license, the Apache 2.0 license, and third-party notices. Locked Rust runtime dependency licenses are recorded in the Rust license report. The software is provided "AS IS", without warranty of any kind.

Acknowledgments

Chart Locker is written and maintained by Nearl Crews. It relies on:

Chart Locker pairs with the Binnacle Chartplotter.

Support

Find this project useful? You can support its continued development by buying me a coffee.