create-honua-app 0.1.1

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.
Files changed (33) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +50 -0
  3. package/bin/create-honua-app.mjs +7 -0
  4. package/lib/cli.mjs +149 -0
  5. package/lib/scaffold.mjs +134 -0
  6. package/lib/templates.mjs +138 -0
  7. package/package.json +32 -0
  8. package/templates/react-ts/.stackblitzrc +4 -0
  9. package/templates/react-ts/README.md +64 -0
  10. package/templates/react-ts/_gitignore +6 -0
  11. package/templates/react-ts/fixtures/features.json +46 -0
  12. package/templates/react-ts/fixtures/layer.json +34 -0
  13. package/templates/react-ts/index.html +12 -0
  14. package/templates/react-ts/package.json +31 -0
  15. package/templates/react-ts/src/App.tsx +153 -0
  16. package/templates/react-ts/src/fixture-endpoint.ts +9 -0
  17. package/templates/react-ts/src/main.tsx +18 -0
  18. package/templates/react-ts/src/styles.css +149 -0
  19. package/templates/react-ts/tsconfig.json +15 -0
  20. package/templates/react-ts/vite.config.ts +50 -0
  21. package/templates/vanilla-ts/.stackblitzrc +4 -0
  22. package/templates/vanilla-ts/README.md +60 -0
  23. package/templates/vanilla-ts/_gitignore +6 -0
  24. package/templates/vanilla-ts/fixtures/features.json +46 -0
  25. package/templates/vanilla-ts/fixtures/layer.json +34 -0
  26. package/templates/vanilla-ts/index.html +37 -0
  27. package/templates/vanilla-ts/package.json +27 -0
  28. package/templates/vanilla-ts/src/fixture-endpoint.ts +9 -0
  29. package/templates/vanilla-ts/src/main.ts +113 -0
  30. package/templates/vanilla-ts/src/styles.css +149 -0
  31. package/templates/vanilla-ts/tsconfig.json +14 -0
  32. package/templates/vanilla-ts/vite.config.ts +50 -0
  33. package/templates.manifest.json +61 -0
@@ -0,0 +1,60 @@
1
+ # Honua map app (vanilla TypeScript)
2
+
3
+ A Vite + TypeScript starter for the [Honua JavaScript SDK](https://github.com/honua-io/honua-sdk-js). It runs the
4
+ SDK's protocol-neutral workflow end to end:
5
+
6
+ ```text
7
+ connect → inspect → explain → query → mount
8
+ ```
9
+
10
+ ## Run it
11
+
12
+ ```bash
13
+ npm install
14
+ npm run dev
15
+ ```
16
+
17
+ The default lane serves a committed GeoServices fixture from the Vite dev server, so the first map needs no account,
18
+ no API key, and no third-party network call. The same fixture is served by `npm run preview` after `npm run build`.
19
+
20
+ ## Point it at live data
21
+
22
+ ```bash
23
+ VITE_HONUA_ENDPOINT=https://your-public-service.example/rest/services/example/FeatureServer/0 npm run dev
24
+ ```
25
+
26
+ - `VITE_HONUA_ENDPOINT` — an anonymous, CORS-enabled GeoServices FeatureServer layer or OGC API Features landing page.
27
+ - `VITE_HONUA_PROTOCOL` — `auto`, `geoservices-feature-service`, or `ogc-features` (default:
28
+ `geoservices-feature-service`, which matches the fixture).
29
+
30
+ Do not put durable credentials in Vite environment variables: Vite embeds them in public JavaScript. Use an anonymous
31
+ endpoint or a server-side proxy.
32
+
33
+ ## What to edit
34
+
35
+ | File | Why |
36
+ | --- | --- |
37
+ | `src/main.ts` | The whole workflow: connect, inspect, explain, query, mount. Change the query here. |
38
+ | `src/fixture-endpoint.ts` | The same-origin path the offline fixture is served on. |
39
+ | `vite.config.ts` | The fixture service. Delete it once you point the app at a real endpoint. |
40
+ | `fixtures/` | The committed GeoServices layer description and its query response. |
41
+
42
+ ## Dependencies
43
+
44
+ `@honua/sdk-js` and `maplibre-gl` are the two packages this app calls directly. `@bufbuild/protobuf` and the two
45
+ `@connectrpc` packages are the SDK's optional transport peers: they are installed and pinned here so the bundle builds
46
+ without any peer-dependency assembly, and they are what a Honua-server connection uses.
47
+
48
+ This starter pins **MapLibre GL JS 5.24.0**, the major the published `@honua/sdk-js` release accepts as an optional
49
+ peer. MapLibre 6 is supported by the SDK source (`^5.0.0 || ^6.0.0`) and ships in the next release; upgrading to 6.x
50
+ also means configuring MapLibre's ESM worker before the first map is created — under Vite, `setWorkerUrl` with
51
+ `import maplibreWorkerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url"`.
52
+
53
+ ## Checks
54
+
55
+ ```bash
56
+ npm run typecheck
57
+ npm run build
58
+ ```
59
+
60
+ The fixture data is synthetic demonstration data from the Honua SDK sample fixtures (Apache-2.0).
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ .env.local
5
+ *.log
6
+ .DS_Store
@@ -0,0 +1,46 @@
1
+ {
2
+ "objectIdFieldName": "OBJECTID",
3
+ "geometryType": "esriGeometryPolygon",
4
+ "spatialReference": { "wkid": 4326 },
5
+ "fields": [
6
+ { "name": "OBJECTID", "type": "esriFieldTypeOID", "alias": "OBJECTID" },
7
+ { "name": "NAME", "type": "esriFieldTypeString", "alias": "Name" },
8
+ { "name": "STATUS", "type": "esriFieldTypeString", "alias": "Status" },
9
+ { "name": "CATEGORY", "type": "esriFieldTypeString", "alias": "Category" }
10
+ ],
11
+ "features": [
12
+ {
13
+ "attributes": {
14
+ "OBJECTID": 1,
15
+ "NAME": "Civic center service zone",
16
+ "STATUS": "Monitoring",
17
+ "CATEGORY": "Operations"
18
+ },
19
+ "geometry": {
20
+ "rings": [[[-157.866, 21.311], [-157.856, 21.311], [-157.856, 21.302], [-157.866, 21.302], [-157.866, 21.311]]]
21
+ }
22
+ },
23
+ {
24
+ "attributes": {
25
+ "OBJECTID": 2,
26
+ "NAME": "Harbor response district",
27
+ "STATUS": "Field review",
28
+ "CATEGORY": "Maritime"
29
+ },
30
+ "geometry": {
31
+ "rings": [[[-157.891, 21.304], [-157.879, 21.304], [-157.879, 21.294], [-157.891, 21.294], [-157.891, 21.304]]]
32
+ }
33
+ },
34
+ {
35
+ "attributes": {
36
+ "OBJECTID": 3,
37
+ "NAME": "Kakaako utility corridor",
38
+ "STATUS": "Ready",
39
+ "CATEGORY": "Infrastructure"
40
+ },
41
+ "geometry": {
42
+ "rings": [[[-157.87, 21.296], [-157.856, 21.296], [-157.856, 21.286], [-157.87, 21.286], [-157.87, 21.296]]]
43
+ }
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "currentVersion": 11.3,
3
+ "id": 0,
4
+ "name": "Honolulu operations areas",
5
+ "type": "Feature Layer",
6
+ "description": "The same three synthetic First Map polygons exposed by the OGC API Features projection.",
7
+ "copyrightText": "Copyright Honua contributors; synthetic demonstration data.",
8
+ "provenance": {
9
+ "source": "honua-sdk-js test/fixtures/honua-quickstart-demo",
10
+ "retrievedAt": "2026-07-13T00:00:00.000Z"
11
+ },
12
+ "geometryType": "esriGeometryPolygon",
13
+ "objectIdField": "OBJECTID",
14
+ "maxRecordCount": 25,
15
+ "advancedQueryCapabilities": {
16
+ "supportsPagination": true,
17
+ "supportsReturningQueryExtent": false,
18
+ "supportsStatistics": false
19
+ },
20
+ "extent": {
21
+ "xmin": -157.891,
22
+ "ymin": 21.286,
23
+ "xmax": -157.856,
24
+ "ymax": 21.311,
25
+ "spatialReference": { "wkid": 4326 }
26
+ },
27
+ "fields": [
28
+ { "name": "OBJECTID", "type": "esriFieldTypeOID", "alias": "OBJECTID" },
29
+ { "name": "NAME", "type": "esriFieldTypeString", "alias": "Name" },
30
+ { "name": "STATUS", "type": "esriFieldTypeString", "alias": "Status" },
31
+ { "name": "CATEGORY", "type": "esriFieldTypeString", "alias": "Category" }
32
+ ],
33
+ "capabilities": "Query"
34
+ }
@@ -0,0 +1,37 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Honua map app</title>
7
+ </head>
8
+ <body>
9
+ <main class="app">
10
+ <section class="panel" aria-label="Workflow">
11
+ <p class="eyebrow">Honua JavaScript SDK</p>
12
+ <h1 class="title">connect → inspect → explain → query → mount</h1>
13
+ <p id="status" class="status" role="status" aria-live="polite">Starting the workflow…</p>
14
+ <ol class="stages">
15
+ <li data-stage="connect"><span class="stage-name">Connect</span><span class="stage-state">waiting</span></li>
16
+ <li data-stage="inspect"><span class="stage-name">Inspect</span><span class="stage-state">waiting</span></li>
17
+ <li data-stage="explain"><span class="stage-name">Explain</span><span class="stage-state">waiting</span></li>
18
+ <li data-stage="query"><span class="stage-name">Query</span><span class="stage-state">waiting</span></li>
19
+ <li data-stage="mount"><span class="stage-name">Mount</span><span class="stage-state">waiting</span></li>
20
+ </ol>
21
+ <dl class="facts">
22
+ <div><dt>Data lane</dt><dd id="fact-mode">—</dd></div>
23
+ <div><dt>Endpoint</dt><dd id="fact-endpoint">—</dd></div>
24
+ <div><dt>Protocol</dt><dd id="fact-protocol">—</dd></div>
25
+ <div><dt>Source</dt><dd id="fact-source">—</dd></div>
26
+ <div><dt>Features</dt><dd id="fact-features">—</dd></div>
27
+ </dl>
28
+ <p class="hint">
29
+ Edit <code>src/main.ts</code> to change the query, or set <code>VITE_HONUA_ENDPOINT</code> to run the same
30
+ workflow against a live public service.
31
+ </p>
32
+ </section>
33
+ <div id="map" class="map" role="application" aria-label="Mounted map"></div>
34
+ </main>
35
+ <script type="module" src="/src/main.ts"></script>
36
+ </body>
37
+ </html>
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "honua-app",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=20.19.0"
8
+ },
9
+ "scripts": {
10
+ "dev": "vite",
11
+ "build": "vite build",
12
+ "preview": "vite preview",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "@bufbuild/protobuf": "2.13.0",
17
+ "@connectrpc/connect": "2.1.2",
18
+ "@connectrpc/connect-web": "2.1.2",
19
+ "@honua/sdk-js": "0.1.2-beta.0",
20
+ "maplibre-gl": "5.24.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "24.13.3",
24
+ "typescript": "5.9.3",
25
+ "vite": "8.2.0"
26
+ }
27
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Same-origin path the committed fixture service answers on.
3
+ *
4
+ * `vite.config.ts` serves the fixture here in both `npm run dev` and
5
+ * `npm run preview`, and `src/main.ts` connects here whenever no live endpoint
6
+ * is configured. Keeping the path in one module is what makes the default lane
7
+ * work with no account, no key, and no third-party network call.
8
+ */
9
+ export const FIXTURE_LAYER_PATH = "/fixture/rest/services/honua-demo/FeatureServer/0";
@@ -0,0 +1,113 @@
1
+ import "maplibre-gl/dist/maplibre-gl.css";
2
+
3
+ import { createHonua } from "@honua/sdk-js";
4
+ import type { ConnectProtocolHint } from "@honua/sdk-js";
5
+ import { maplibreRenderer } from "@honua/sdk-js/runtime";
6
+ import * as maplibregl from "maplibre-gl";
7
+
8
+ import { FIXTURE_LAYER_PATH } from "./fixture-endpoint.js";
9
+ import "./styles.css";
10
+
11
+ /** Offline basemap: the starter never fetches third-party tiles on its default lane. */
12
+ const BASEMAP_STYLE = {
13
+ version: 8,
14
+ sources: {},
15
+ layers: [{ id: "background", type: "background", paint: { "background-color": "#0e1a17" } }],
16
+ };
17
+
18
+ const MAP_OPTIONS = { center: [-157.873, 21.2985], zoom: 11.4, attributionControl: false };
19
+
20
+ /** Bounded row budget. Honua never mounts a truncated result silently. */
21
+ const MAX_FEATURES = 250;
22
+
23
+ const configuredEndpoint = import.meta.env.VITE_HONUA_ENDPOINT?.trim();
24
+ const configuredProtocol = import.meta.env.VITE_HONUA_PROTOCOL?.trim();
25
+
26
+ const endpoint =
27
+ configuredEndpoint && configuredEndpoint.length > 0
28
+ ? configuredEndpoint
29
+ : new URL(FIXTURE_LAYER_PATH, window.location.origin).toString();
30
+ const protocol = (
31
+ configuredProtocol && configuredProtocol.length > 0 ? configuredProtocol : "geoservices-feature-service"
32
+ ) as ConnectProtocolHint;
33
+ const dataLane = configuredEndpoint && configuredEndpoint.length > 0 ? "Live endpoint" : "Committed fixture";
34
+
35
+ function element(id: string): HTMLElement {
36
+ const found = document.getElementById(id);
37
+ if (!found) throw new Error(`Missing #${id} element`);
38
+ return found;
39
+ }
40
+
41
+ function fact(name: string, value: string): void {
42
+ element(`fact-${name}`).textContent = value;
43
+ }
44
+
45
+ function stage(name: string, state: "running" | "done" | "failed", detail: string): void {
46
+ const item = document.querySelector<HTMLElement>(`[data-stage="${name}"]`);
47
+ if (!item) return;
48
+ item.dataset["state"] = state;
49
+ const label = item.querySelector<HTMLElement>(".stage-state");
50
+ if (label) label.textContent = detail;
51
+ }
52
+
53
+ async function run(): Promise<void> {
54
+ fact("mode", dataLane);
55
+ fact("endpoint", endpoint);
56
+
57
+ const honua = createHonua();
58
+ try {
59
+ stage("connect", "running", "connecting");
60
+ const connection = await honua.connect(
61
+ { url: endpoint, protocol },
62
+ { authorizationScopeFingerprint: "anonymous-public" },
63
+ );
64
+ stage("connect", "done", "connected");
65
+
66
+ stage("inspect", "running", "discovering");
67
+ const inspection = await connection.inspect();
68
+ const sourceId = inspection.defaultSourceId ?? inspection.sources[0]?.descriptor.id;
69
+ if (!sourceId) throw new Error("The endpoint advertised no queryable source.");
70
+ fact("protocol", inspection.protocol);
71
+ fact("source", sourceId);
72
+ stage("inspect", "done", `${inspection.sources.length} source(s)`);
73
+
74
+ stage("explain", "running", "planning");
75
+ const plan = await connection.explain(
76
+ {
77
+ returnGeometry: true,
78
+ pagination: { limit: MAX_FEATURES },
79
+ ...(inspection.protocol === "geoservices-feature-service" ? { outSr: 4326 } : {}),
80
+ },
81
+ { sourceId },
82
+ );
83
+ stage("explain", "done", "plan accepted");
84
+
85
+ stage("query", "running", "executing");
86
+ const result = await connection.query(plan);
87
+ fact("features", `${result.features.length}${result.exceededTransferLimit ? " (truncated)" : ""}`);
88
+ stage("query", "done", `${result.features.length} feature(s)`);
89
+
90
+ stage("mount", "running", "rendering");
91
+ // A selector or element target makes the SDK own the map's lifecycle; pass
92
+ // an existing `maplibregl.Map` instead to keep ownership in the app.
93
+ const mounted = await connection.mount(element("map"), {
94
+ renderer: maplibreRenderer(maplibregl),
95
+ query: plan,
96
+ sourceId,
97
+ style: BASEMAP_STYLE,
98
+ rendererOptions: { mapOptions: MAP_OPTIONS },
99
+ });
100
+ await mounted.ready;
101
+ stage("mount", "done", "mounted");
102
+ element("status").textContent = "The accepted plan is mounted. Every stage above ran through the public SDK API.";
103
+ } catch (error) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ element("status").textContent = `The workflow stopped: ${message}`;
106
+ for (const item of document.querySelectorAll<HTMLElement>("[data-stage]")) {
107
+ if (item.dataset["state"] === "running") stage(item.dataset["stage"] ?? "", "failed", "failed");
108
+ }
109
+ await honua.dispose();
110
+ }
111
+ }
112
+
113
+ void run();
@@ -0,0 +1,149 @@
1
+ :root {
2
+ --surface: #f6f7f5;
3
+ --panel: #ffffff;
4
+ --ink: #10201b;
5
+ --muted: #5c6b66;
6
+ --line: #d9e0dc;
7
+ --accent: #0f766e;
8
+ color-scheme: light dark;
9
+ }
10
+
11
+ @media (prefers-color-scheme: dark) {
12
+ :root {
13
+ --surface: #0b1210;
14
+ --panel: #111a17;
15
+ --ink: #e8f0ec;
16
+ --muted: #93a49e;
17
+ --line: #23322c;
18
+ --accent: #5eead4;
19
+ }
20
+ }
21
+
22
+ * {
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ body {
27
+ margin: 0;
28
+ background: var(--surface);
29
+ color: var(--ink);
30
+ font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
31
+ }
32
+
33
+ .app {
34
+ display: grid;
35
+ grid-template-columns: minmax(280px, 360px) 1fr;
36
+ gap: 16px;
37
+ padding: 16px;
38
+ height: 100vh;
39
+ }
40
+
41
+ @media (max-width: 820px) {
42
+ .app {
43
+ grid-template-columns: 1fr;
44
+ grid-template-rows: auto minmax(320px, 1fr);
45
+ height: auto;
46
+ }
47
+ }
48
+
49
+ .panel {
50
+ background: var(--panel);
51
+ border: 1px solid var(--line);
52
+ border-radius: 12px;
53
+ padding: 20px;
54
+ overflow-y: auto;
55
+ }
56
+
57
+ .eyebrow {
58
+ margin: 0;
59
+ color: var(--accent);
60
+ font-size: 12px;
61
+ font-weight: 600;
62
+ letter-spacing: 0.08em;
63
+ text-transform: uppercase;
64
+ }
65
+
66
+ .title {
67
+ margin: 6px 0 12px;
68
+ font-size: 18px;
69
+ line-height: 1.3;
70
+ }
71
+
72
+ .status {
73
+ margin: 0 0 16px;
74
+ color: var(--muted);
75
+ }
76
+
77
+ .stages {
78
+ list-style: none;
79
+ margin: 0 0 20px;
80
+ padding: 0;
81
+ display: grid;
82
+ gap: 6px;
83
+ }
84
+
85
+ .stages li {
86
+ display: flex;
87
+ justify-content: space-between;
88
+ gap: 12px;
89
+ padding: 8px 10px;
90
+ border: 1px solid var(--line);
91
+ border-radius: 8px;
92
+ font-size: 13px;
93
+ }
94
+
95
+ .stages li[data-state="running"] {
96
+ border-color: var(--accent);
97
+ }
98
+
99
+ .stages li[data-state="done"] .stage-state {
100
+ color: var(--accent);
101
+ }
102
+
103
+ .stages li[data-state="failed"] .stage-state {
104
+ color: #dc2626;
105
+ }
106
+
107
+ .stage-state {
108
+ color: var(--muted);
109
+ }
110
+
111
+ .facts {
112
+ display: grid;
113
+ gap: 8px;
114
+ margin: 0 0 16px;
115
+ }
116
+
117
+ .facts div {
118
+ display: grid;
119
+ grid-template-columns: 96px 1fr;
120
+ gap: 10px;
121
+ font-size: 13px;
122
+ }
123
+
124
+ .facts dt {
125
+ color: var(--muted);
126
+ }
127
+
128
+ .facts dd {
129
+ margin: 0;
130
+ overflow-wrap: anywhere;
131
+ }
132
+
133
+ .hint {
134
+ margin: 0;
135
+ color: var(--muted);
136
+ font-size: 13px;
137
+ }
138
+
139
+ code {
140
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
141
+ font-size: 12px;
142
+ }
143
+
144
+ .map {
145
+ min-height: 360px;
146
+ border: 1px solid var(--line);
147
+ border-radius: 12px;
148
+ overflow: hidden;
149
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "verbatimModuleSyntax": true,
10
+ "allowSyntheticDefaultImports": true,
11
+ "types": ["vite/client", "node"]
12
+ },
13
+ "include": ["src/**/*.ts", "vite.config.ts"]
14
+ }
@@ -0,0 +1,50 @@
1
+ import { readFileSync } from "node:fs";
2
+ import type { IncomingMessage, ServerResponse } from "node:http";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import { type Plugin, defineConfig } from "vite";
6
+
7
+ import { FIXTURE_LAYER_PATH } from "./src/fixture-endpoint.js";
8
+
9
+ function fixtureDocument(name: string): string {
10
+ return readFileSync(fileURLToPath(new URL(`./fixtures/${name}`, import.meta.url)), "utf8");
11
+ }
12
+
13
+ /**
14
+ * Deterministic, offline GeoServices FeatureServer fixture.
15
+ *
16
+ * The starter's green path must never depend on a third-party endpoint, so the
17
+ * dev and preview servers answer the two routes the SDK's GeoServices adapter
18
+ * needs: the layer description and its bounded query. Point
19
+ * `VITE_HONUA_ENDPOINT` at a real service to run the same code against live data.
20
+ */
21
+ function honuaFixtureService(): Plugin {
22
+ const layer = fixtureDocument("layer.json");
23
+ const features = fixtureDocument("features.json");
24
+ const middleware = (request: IncomingMessage, response: ServerResponse, next: () => void): void => {
25
+ const pathname = new URL(request.url ?? "/", "http://localhost").pathname;
26
+ let body: string | undefined;
27
+ if (pathname === FIXTURE_LAYER_PATH) body = layer;
28
+ else if (pathname === `${FIXTURE_LAYER_PATH}/query`) body = features;
29
+ if (body === undefined) {
30
+ next();
31
+ return;
32
+ }
33
+ response.setHeader("content-type", "application/json; charset=utf-8");
34
+ response.setHeader("cache-control", "no-store");
35
+ response.end(body);
36
+ };
37
+ return {
38
+ name: "honua-fixture-service",
39
+ configureServer(server) {
40
+ server.middlewares.use(middleware);
41
+ },
42
+ configurePreviewServer(server) {
43
+ server.middlewares.use(middleware);
44
+ },
45
+ };
46
+ }
47
+
48
+ export default defineConfig({
49
+ plugins: [honuaFixtureService()],
50
+ });
@@ -0,0 +1,61 @@
1
+ {
2
+ "format": "honua.sdk.create-honua-app-templates.v1",
3
+ "schemaVersion": 1,
4
+ "sdk": {
5
+ "package": "@honua/sdk-js",
6
+ "version": "0.1.2-beta.0"
7
+ },
8
+ "repository": {
9
+ "owner": "honua-io",
10
+ "name": "honua-sdk-js",
11
+ "branch": "trunk"
12
+ },
13
+ "playgroundProviders": [
14
+ {
15
+ "id": "stackblitz",
16
+ "title": "StackBlitz",
17
+ "urlTemplate": "https://stackblitz.com/github/{owner}/{repository}/tree/{branch}/{path}"
18
+ },
19
+ {
20
+ "id": "codesandbox",
21
+ "title": "CodeSandbox",
22
+ "urlTemplate": "https://codesandbox.io/s/github/{owner}/{repository}/tree/{branch}/{path}"
23
+ }
24
+ ],
25
+ "templates": [
26
+ {
27
+ "id": "vanilla-ts",
28
+ "title": "Vanilla TypeScript",
29
+ "summary": "Vite + TypeScript app that connects to an endpoint, explains a bounded query, and mounts the accepted plan on MapLibre.",
30
+ "path": "packages/create-honua-app/templates/vanilla-ts",
31
+ "entryFile": "src/main.ts",
32
+ "dataLane": "fixture",
33
+ "default": true,
34
+ "dependencies": [
35
+ "@honua/sdk-js",
36
+ "maplibre-gl",
37
+ "@bufbuild/protobuf",
38
+ "@connectrpc/connect",
39
+ "@connectrpc/connect-web"
40
+ ]
41
+ },
42
+ {
43
+ "id": "react-ts",
44
+ "title": "React TypeScript",
45
+ "summary": "Vite + React + TypeScript app that mounts the same accepted plan through @honua/sdk-js/react hooks on an app-owned MapLibre map.",
46
+ "path": "packages/create-honua-app/templates/react-ts",
47
+ "entryFile": "src/App.tsx",
48
+ "dataLane": "fixture",
49
+ "default": false,
50
+ "dependencies": [
51
+ "@honua/sdk-js",
52
+ "maplibre-gl",
53
+ "react",
54
+ "react-dom",
55
+ "@bufbuild/protobuf",
56
+ "@connectrpc/connect",
57
+ "@connectrpc/connect-web"
58
+ ]
59
+ }
60
+ ]
61
+ }