create-honua-app 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # create-honua-app
2
2
 
3
3
  Scaffold a [Honua JavaScript SDK](https://github.com/honua-io/honua-sdk-js) map application — Vite + TypeScript,
4
- pinned to the certified SDK release, running a map on the first `npm run dev`.
4
+ running a map on the first `npm run dev`. These commands explicitly pin the SDK version documented here;
5
+ omit `--sdk-version` to follow the promoted release channel or this scaffold's certified fallback.
5
6
 
7
+ <!-- doc-run: run ready-url="http://localhost:5173/" -->
6
8
  ```bash
7
- npm create honua-app@0.1.6 my-map
9
+ npm create honua-app@latest my-map -- --sdk-version 0.1.15 # x-release-please-version
8
10
  cd my-map
9
11
  npm install
10
12
  npm run dev
@@ -27,7 +29,7 @@ create-honua-app [directory] [options]
27
29
  With `npm create`, pass CLI options after `--`:
28
30
 
29
31
  ```bash
30
- npm create honua-app@0.1.6 my-react-map -- --template react-ts
32
+ npm create honua-app@latest my-react-map -- --template react-ts --sdk-version 0.1.15 # x-release-please-version
31
33
  ```
32
34
 
33
35
  ## Which SDK version a scaffold pins
@@ -42,7 +44,7 @@ version this release of `create-honua-app` ships with. The default path never pi
42
44
  yourself, pass `--sdk-version`:
43
45
 
44
46
  ```bash
45
- npm create honua-app@0.1.6 my-pinned-map -- --sdk-version 0.1.13
47
+ npm create honua-app@latest my-pinned-map -- --sdk-version 0.1.15 # x-release-please-version
46
48
  ```
47
49
 
48
50
  ## Templates
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-honua-app",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Scaffold a Honua JavaScript SDK map application: Vite + TypeScript + MapLibre starters that connect and mount a source without hand-assembling peers",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Honua",
@@ -62,3 +62,7 @@ npm run build
62
62
  ```
63
63
 
64
64
  The fixture data is synthetic demonstration data from the Honua SDK sample fixtures (Apache-2.0).
65
+
66
+ ## Live basemap
67
+
68
+ The default fixture lane stays offline. When `VITE_HONUA_ENDPOINT` selects a live endpoint, the map uses keyless OpenFreeMap Positron (or Dark for the system theme) and keeps source attribution visible. Set `VITE_HONUA_BASEMAP_STYLE` to a custom/self-hosted style URL. A basemap asset failure leaves operational data and controls available with an actionable status. Keep the expanded source credits in screenshots and exports.
@@ -16,7 +16,7 @@
16
16
  "@bufbuild/protobuf": "2.13.0",
17
17
  "@connectrpc/connect": "2.1.2",
18
18
  "@connectrpc/connect-web": "2.1.2",
19
- "@honua/sdk-js": "0.1.13",
19
+ "@honua/sdk-js": "0.1.14",
20
20
  "maplibre-gl": "6.4.1",
21
21
  "react": "19.2.8",
22
22
  "react-dom": "19.2.8"
@@ -4,6 +4,7 @@ import { maplibreRenderer } from "@honua/sdk-js/runtime";
4
4
  import * as maplibregl from "maplibre-gl";
5
5
  import type { RefObject } from "react";
6
6
  import { useEffect, useRef, useState } from "react";
7
+ import { mountSampleOnlineBasemap } from "./online-basemap.js";
7
8
 
8
9
  import { FIXTURE_LAYER_PATH } from "./fixture-endpoint.js";
9
10
 
@@ -54,11 +55,17 @@ function useExternalMap(): { containerRef: RefObject<HTMLDivElement | null>; map
54
55
  style: BASEMAP_STYLE,
55
56
  center: INITIAL_VIEW.center,
56
57
  zoom: INITIAL_VIEW.zoom,
57
- attributionControl: false,
58
+ attributionControl: { compact: true },
58
59
  });
60
+ const disposeBasemap = configuredEndpoint
61
+ ? mountSampleOnlineBasemap(created, {
62
+ styleUrl: import.meta.env.VITE_HONUA_BASEMAP_STYLE?.trim() || undefined,
63
+ })
64
+ : () => {};
59
65
  setMap(created);
60
66
  return () => {
61
67
  setMap(null);
68
+ disposeBasemap();
62
69
  created.remove();
63
70
  };
64
71
  }, []);
@@ -0,0 +1,84 @@
1
+ import * as runtime from "@honua/sdk-js/runtime";
2
+
3
+ type HonuaOnlineBasemapTheme = "positron" | "liberty" | "dark";
4
+ interface OnlineBasemapBinding {
5
+ activate(options: { theme: HonuaOnlineBasemapTheme; styleUrl?: string }): Promise<boolean>;
6
+ dispose(): void;
7
+ }
8
+ type OnlineBasemapConstructor = new (
9
+ map: MapLibreMap,
10
+ options: { onError: (message: string) => void; onReady: () => void },
11
+ ) => OnlineBasemapBinding;
12
+ import type { Map as MapLibreMap } from "maplibre-gl";
13
+
14
+ /** Explicit live-lane enhancement. Local fixture lanes never call this helper. */
15
+ export function mountSampleOnlineBasemap(
16
+ map: MapLibreMap,
17
+ options: {
18
+ readonly styleUrl?: string;
19
+ readonly lightTheme?: Exclude<HonuaOnlineBasemapTheme, "dark">;
20
+ readonly styleEnvironmentVariable?: string;
21
+ } = {},
22
+ ): () => void {
23
+ const notice = document.createElement("div");
24
+ notice.setAttribute("role", "status");
25
+ notice.dataset.basemapStatus = "loading";
26
+ notice.style.cssText =
27
+ "position:absolute;left:12px;right:12px;bottom:40px;z-index:5;padding:8px 12px;background:Canvas;color:CanvasText;border:1px solid currentColor;border-radius:6px;font:13px system-ui;pointer-events:none;display:none";
28
+ map.getContainer().append(notice);
29
+ // Older published SDKs can still run the local fixture lane. A live map
30
+ // explicitly reports the required upgrade instead of failing module loading.
31
+ const Binding = (runtime as unknown as { readonly HonuaOnlineBasemapBinding?: OnlineBasemapConstructor })
32
+ .HonuaOnlineBasemapBinding;
33
+ if (typeof Binding !== "function") {
34
+ notice.textContent =
35
+ "Online basemaps require a newer @honua/sdk-js release with HonuaOnlineBasemapBinding. Upgrade @honua/sdk-js after the basemap SDK release is published, then reload. Operational data remains usable.";
36
+ notice.dataset.basemapStatus = "error";
37
+ notice.style.display = "block";
38
+ return () => notice.remove();
39
+ }
40
+ const binding = new Binding(map, {
41
+ onError: (message) => {
42
+ notice.textContent = `${message} Set ${options.styleEnvironmentVariable ?? "VITE_HONUA_BASEMAP_STYLE"} to your custom/self-hosted style URL.`;
43
+ notice.dataset.basemapStatus = "error";
44
+ notice.style.display = "block";
45
+ },
46
+ onReady: () => {
47
+ notice.textContent = "";
48
+ notice.dataset.basemapStatus = "ready";
49
+ notice.style.display = "none";
50
+ },
51
+ });
52
+ const preferred = matchMedia("(prefers-color-scheme: dark)");
53
+ let pendingTheme: HonuaOnlineBasemapTheme | undefined;
54
+ const flush = () => {
55
+ if (!pendingTheme || !map.isStyleLoaded()) return;
56
+ const theme = pendingTheme;
57
+ pendingTheme = undefined;
58
+ void binding.activate({ theme, styleUrl: options.styleUrl });
59
+ };
60
+ const update = () => {
61
+ const selected = document.documentElement.dataset.theme;
62
+ const dark = selected === "dark" || (!selected && preferred.matches);
63
+ pendingTheme = dark ? "dark" : (options.lightTheme ?? "positron");
64
+ flush();
65
+ };
66
+ const observer = new MutationObserver(update);
67
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
68
+ preferred.addEventListener("change", update);
69
+ // Theme changes during tile/sprite loading must survive until the renderer
70
+ // is ready again. Consume only the latest pending theme, once per update.
71
+ map.on("idle", flush);
72
+ map.once("load", flush);
73
+ update();
74
+ const dispose = () => {
75
+ map.off("load", flush);
76
+ map.off("idle", flush);
77
+ observer.disconnect();
78
+ preferred.removeEventListener("change", update);
79
+ binding.dispose();
80
+ notice.remove();
81
+ };
82
+ // Dispose before remove(), while the renderer's style resources still exist.
83
+ return dispose;
84
+ }
@@ -59,3 +59,7 @@ npm run build
59
59
  ```
60
60
 
61
61
  The fixture data is synthetic demonstration data from the Honua SDK sample fixtures (Apache-2.0).
62
+
63
+ ## Live basemap
64
+
65
+ The default fixture lane stays offline. When `VITE_HONUA_ENDPOINT` selects a live endpoint, the map uses keyless OpenFreeMap Positron (or Dark for the system theme) and keeps source attribution visible. Set `VITE_HONUA_BASEMAP_STYLE` to a custom/self-hosted style URL. A basemap asset failure leaves operational data and controls available with an actionable status. Keep the expanded source credits in screenshots and exports.
@@ -16,7 +16,7 @@
16
16
  "@bufbuild/protobuf": "2.13.0",
17
17
  "@connectrpc/connect": "2.1.2",
18
18
  "@connectrpc/connect-web": "2.1.2",
19
- "@honua/sdk-js": "0.1.13",
19
+ "@honua/sdk-js": "0.1.14",
20
20
  "maplibre-gl": "6.4.1"
21
21
  },
22
22
  "devDependencies": {
@@ -1,3 +1,4 @@
1
+ import { mountSampleOnlineBasemap } from "./online-basemap.js";
1
2
  import "./maplibre-worker.js";
2
3
  import "maplibre-gl/dist/maplibre-gl.css";
3
4
 
@@ -16,7 +17,7 @@ const BASEMAP_STYLE = {
16
17
  layers: [{ id: "background", type: "background", paint: { "background-color": "#0e1a17" } }],
17
18
  };
18
19
 
19
- const MAP_OPTIONS = { center: [-157.873, 21.2985], zoom: 11.4, attributionControl: false };
20
+ const MAP_OPTIONS = { center: [-157.873, 21.2985], zoom: 11.4, attributionControl: { compact: true } };
20
21
 
21
22
  /** Bounded row budget. Honua never mounts a truncated result silently. */
22
23
  const MAX_FEATURES = 250;
@@ -99,6 +100,21 @@ async function run(): Promise<void> {
99
100
  rendererOptions: { mapOptions: MAP_OPTIONS },
100
101
  });
101
102
  await mounted.ready;
103
+ const rawMap = mounted.raw("maplibre");
104
+ const disposeBasemap =
105
+ configuredEndpoint && rawMap
106
+ ? mountSampleOnlineBasemap(rawMap as maplibregl.Map, {
107
+ styleUrl: import.meta.env.VITE_HONUA_BASEMAP_STYLE?.trim() || undefined,
108
+ })
109
+ : () => {};
110
+ window.addEventListener(
111
+ "pagehide",
112
+ () => {
113
+ disposeBasemap();
114
+ void honua.dispose();
115
+ },
116
+ { once: true },
117
+ );
102
118
  stage("mount", "done", "mounted");
103
119
  element("status").textContent = "The accepted plan is mounted. Every stage above ran through the public SDK API.";
104
120
  } catch (error) {
@@ -0,0 +1,84 @@
1
+ import * as runtime from "@honua/sdk-js/runtime";
2
+
3
+ type HonuaOnlineBasemapTheme = "positron" | "liberty" | "dark";
4
+ interface OnlineBasemapBinding {
5
+ activate(options: { theme: HonuaOnlineBasemapTheme; styleUrl?: string }): Promise<boolean>;
6
+ dispose(): void;
7
+ }
8
+ type OnlineBasemapConstructor = new (
9
+ map: MapLibreMap,
10
+ options: { onError: (message: string) => void; onReady: () => void },
11
+ ) => OnlineBasemapBinding;
12
+ import type { Map as MapLibreMap } from "maplibre-gl";
13
+
14
+ /** Explicit live-lane enhancement. Local fixture lanes never call this helper. */
15
+ export function mountSampleOnlineBasemap(
16
+ map: MapLibreMap,
17
+ options: {
18
+ readonly styleUrl?: string;
19
+ readonly lightTheme?: Exclude<HonuaOnlineBasemapTheme, "dark">;
20
+ readonly styleEnvironmentVariable?: string;
21
+ } = {},
22
+ ): () => void {
23
+ const notice = document.createElement("div");
24
+ notice.setAttribute("role", "status");
25
+ notice.dataset.basemapStatus = "loading";
26
+ notice.style.cssText =
27
+ "position:absolute;left:12px;right:12px;bottom:40px;z-index:5;padding:8px 12px;background:Canvas;color:CanvasText;border:1px solid currentColor;border-radius:6px;font:13px system-ui;pointer-events:none;display:none";
28
+ map.getContainer().append(notice);
29
+ // Older published SDKs can still run the local fixture lane. A live map
30
+ // explicitly reports the required upgrade instead of failing module loading.
31
+ const Binding = (runtime as unknown as { readonly HonuaOnlineBasemapBinding?: OnlineBasemapConstructor })
32
+ .HonuaOnlineBasemapBinding;
33
+ if (typeof Binding !== "function") {
34
+ notice.textContent =
35
+ "Online basemaps require a newer @honua/sdk-js release with HonuaOnlineBasemapBinding. Upgrade @honua/sdk-js after the basemap SDK release is published, then reload. Operational data remains usable.";
36
+ notice.dataset.basemapStatus = "error";
37
+ notice.style.display = "block";
38
+ return () => notice.remove();
39
+ }
40
+ const binding = new Binding(map, {
41
+ onError: (message) => {
42
+ notice.textContent = `${message} Set ${options.styleEnvironmentVariable ?? "VITE_HONUA_BASEMAP_STYLE"} to your custom/self-hosted style URL.`;
43
+ notice.dataset.basemapStatus = "error";
44
+ notice.style.display = "block";
45
+ },
46
+ onReady: () => {
47
+ notice.textContent = "";
48
+ notice.dataset.basemapStatus = "ready";
49
+ notice.style.display = "none";
50
+ },
51
+ });
52
+ const preferred = matchMedia("(prefers-color-scheme: dark)");
53
+ let pendingTheme: HonuaOnlineBasemapTheme | undefined;
54
+ const flush = () => {
55
+ if (!pendingTheme || !map.isStyleLoaded()) return;
56
+ const theme = pendingTheme;
57
+ pendingTheme = undefined;
58
+ void binding.activate({ theme, styleUrl: options.styleUrl });
59
+ };
60
+ const update = () => {
61
+ const selected = document.documentElement.dataset.theme;
62
+ const dark = selected === "dark" || (!selected && preferred.matches);
63
+ pendingTheme = dark ? "dark" : (options.lightTheme ?? "positron");
64
+ flush();
65
+ };
66
+ const observer = new MutationObserver(update);
67
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
68
+ preferred.addEventListener("change", update);
69
+ // Theme changes during tile/sprite loading must survive until the renderer
70
+ // is ready again. Consume only the latest pending theme, once per update.
71
+ map.on("idle", flush);
72
+ map.once("load", flush);
73
+ update();
74
+ const dispose = () => {
75
+ map.off("load", flush);
76
+ map.off("idle", flush);
77
+ observer.disconnect();
78
+ preferred.removeEventListener("change", update);
79
+ binding.dispose();
80
+ notice.remove();
81
+ };
82
+ // Dispose before remove(), while the renderer's style resources still exist.
83
+ return dispose;
84
+ }
@@ -4,7 +4,7 @@
4
4
  "sdk": {
5
5
  "package": "@honua/sdk-js",
6
6
  "channel": "release-2026.1",
7
- "version": "0.1.13"
7
+ "version": "0.1.14"
8
8
  },
9
9
  "repository": {
10
10
  "owner": "honua-io",