Internal shell service
Read-only · no auth · identical for every caller

Shared data for every internal tool

One small, separately deployed Worker that serves shared, read-only data to every internal tool — starting with the navigation menu each tool renders in its own UI.

Every response is read-only, non-sensitive, and identical for every caller. There is no per-user data, no authentication, and no filtering — if something wouldn't be fine to hand to anyone who can reach this URL, it does not belong in this service.

How this service works

What protects it, how paths and versions are structured, and how to consume it well.

Access model

The only protection is which hostname is calling. A cross-origin request's Origin must be on the allowlist below (echoed back in Access-Control-Allow-Origin) or it gets 403; a same-origin request is checked against its own hostname instead.

This stops other sites from embedding this data in a browser. It does not stop a direct request — an acceptable trade because nothing served here is sensitive.

  • utm.basworld.online
  • shell.basworld.online
  • localhost
  • 127.0.0.1

Conventions

  • Every endpoint lives at /{endpoint}/v{major}nav is simply the first.
  • Cached at the edge: Cache-Control: public, max-age=300, stale-while-revalidate=3600 by default.
  • A breaking response-shape change ships as a new major version, served alongside the old one. Additive changes (new optional field, new node type) stay on the current version.
  • Forward compatibility: skip node types you don't recognise, skip malformed nodes, and only treat a response as unavailable if nothing valid survives.

Recommended client behaviour

  • Fetch with a short timeout — don't let this service block your tool's own render.
  • Cache the last good response in localStorage and render that while re-fetching.
  • Keep a small local fallback for first-load-ever, with no cache and no network.
  • If nothing valid survives, fail quietly — don't show an error where a menu should be.
Vite dev-proxy
// vite.config.ts
server: {
  proxy: {
    "/nav": "https://api.basbuiting.nl",
  },
},

Endpoints

Full reference for every registered endpoint, generated from the same registry the router mounts — this page can't drift from what's actually served.