ketatlas 0.2.5 → 0.4.0

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/bin/viewer.js CHANGED
@@ -5,6 +5,7 @@ import { resolve, dirname, relative, sep } from "node:path";
5
5
  import { validateAtlas, AtlasValidationError } from "../src/config.js";
6
6
  import { serve } from "./server.js";
7
7
  import { fileURLToPath } from "node:url";
8
+ import { rendererFileName, startRenderer } from "./renderer.js";
8
9
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
9
10
  export async function serveAtlas(file, options = {}) {
10
11
  const absolute = await realpath(resolve(file));
@@ -18,11 +19,42 @@ export async function serveAtlas(file, options = {}) {
18
19
  throw new Error("The JSON file must be inside --root.");
19
20
  const configURL = "/" + rel.split(sep).map(encodeURIComponent).join("/");
20
21
  const token = randomBytes(24).toString("hex");
21
- const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>KetAtlas</title><style>html,body{margin:0;height:100%}#atlas{height:100dvh}#error{font:16px system-ui;padding:24px;white-space:pre-wrap}</style></head><body><main id="atlas"></main><pre id="error" hidden></pre><script type="module">import {loadAtlas} from '/__ketatlas__/src/index.js';try{window.atlas=await loadAtlas(document.querySelector('#atlas'),${JSON.stringify(configURL).replaceAll("<", "\\u003c")},{syncUrl:true,progressEndpoint:"/__ketatlas__/progress",progressToken:${JSON.stringify(token)}});document.title=${JSON.stringify(config.title).replaceAll("<", "\\u003c")}+' · KetAtlas';}catch(error){const el=document.querySelector('#error');el.hidden=false;el.textContent=error.message;}</script></body></html>`;
22
- return serve(root, {
23
- ...options,
24
- viewer: html,
25
- packageRoot,
26
- handler: progressHandler(absolute, absolute, token, !options.readOnly),
27
- });
22
+ let renderer;
23
+ if (options.renderer) {
24
+ const rendererFile = resolve(options.rendererFile || dirname(absolute), rendererFileName);
25
+ const htmlPort =
26
+ options.htmlPort ?? (options.port && options.port < 65535 ? options.port + 1 : 0);
27
+ renderer = await startRenderer(rendererFile, {
28
+ host: options.host,
29
+ port: htmlPort,
30
+ stdio: options.rendererStdio,
31
+ });
32
+ }
33
+ const loadOptions = {
34
+ syncUrl: true,
35
+ progressEndpoint: "/__ketatlas__/progress",
36
+ progressToken: token,
37
+ ...(renderer
38
+ ? {
39
+ screenBaseURL: renderer.screenBaseURL,
40
+ sandbox: "allow-scripts allow-forms allow-same-origin",
41
+ }
42
+ : {}),
43
+ };
44
+ const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>KetAtlas</title><style>html,body{margin:0;height:100%}#atlas{height:100dvh}#error{font:16px system-ui;padding:24px;white-space:pre-wrap}</style></head><body><main id="atlas"></main><pre id="error" hidden></pre><script type="module">import {loadAtlas} from '/__ketatlas__/src/index.js';try{window.atlas=await loadAtlas(document.querySelector('#atlas'),${JSON.stringify(configURL).replaceAll("<", "\\u003c")},${JSON.stringify(loadOptions).replaceAll("<", "\\u003c")});document.title=${JSON.stringify(config.title).replaceAll("<", "\\u003c")}+' · KetAtlas';}catch(error){const el=document.querySelector('#error');el.hidden=false;el.textContent=error.message;}</script></body></html>`;
45
+ try {
46
+ const server = await serve(root, {
47
+ ...options,
48
+ viewer: html,
49
+ packageRoot,
50
+ handler: progressHandler(absolute, absolute, token, !options.readOnly),
51
+ });
52
+ server.renderer = renderer;
53
+ server.htmlOrigin = renderer?.origin;
54
+ server.closeRenderer = () => renderer?.close();
55
+ return server;
56
+ } catch (error) {
57
+ await renderer?.close();
58
+ throw error;
59
+ }
28
60
  }
@@ -1,6 +1,6 @@
1
1
  # Create mockups with an agent
2
2
 
3
- Give an agent the KetAtlas skill and a product brief. The agent produces real HTML screens plus `atlas.json`; KetAtlas opens those files as an interactive workflow map. The brief describes the product, while the generated JSON schema and CLI audit check the output format.
3
+ Give an agent the KetAtlas skill and a product brief. The agent produces native framework screen routes (or static HTML for a static product) plus `atlas.json`; KetAtlas opens them as an interactive workflow map. The brief describes the product, while the schemas and CLI audit check the output contracts.
4
4
 
5
5
  ## Install the skill once
6
6
 
@@ -26,7 +26,7 @@ If the agent does not support skill installation, attach that file or ask it to
26
26
  For a short request, invoke the skill and include the product, target, design reference, and flows:
27
27
 
28
28
  ```text
29
- Use $ketatlas to create one shared HTML mobile prototype for Northstar Tasks
29
+ Use $ketatlas to create one shared React mobile prototype for Northstar Tasks
30
30
  in ./tasks/mobile. Use 390 × 844 screens, English product copy, and the design
31
31
  system in ./design-system. Include sign-in, password recovery, task list,
32
32
  task details, and task completion. Map entry points, actions, outcomes, and
@@ -36,10 +36,14 @@ and preview the result. Return the serve command and verification results.
36
36
 
37
37
  `$ketatlas` is the explicit skill invocation in Codex. In other agents, use that agent's skill selector or explicitly ask it to use the installed KetAtlas skill. Keep the same product brief.
38
38
 
39
- The deliverable is data and product screen assets: JSON/schema, HTML/CSS/JavaScript, local assets, and documentation. Do not add a package manifest, lockfile, node_modules, or copied viewer/test tooling to make the atlas runnable. Use a global KetAtlas installation or a version-pinned npx command. Browser checks can use the agent's existing tooling outside the atlas folder.
39
+ The deliverable is a `<name>.ketatlas/` bundle containing JSON/schema, documentation, and either static screen assets or `atlas.renderer.json`. Do not add a package manifest, lockfile, node_modules, or copied viewer/test tooling inside the bundle. Native React/Vue/KetJS/etc. routes reuse the product's existing framework package and shared UI source outside the atlas folder. Use `ketatlas@0.4.0` for this contract. Browser checks can use the agent's existing tooling outside the atlas folder.
40
40
 
41
41
  The agent should infer routine details and record assumptions. Provide an exact list when “all screens” means a defined inventory, so missing coverage can be checked against a source.
42
42
 
43
+ Before it creates or edits visual screens, the skill asks for one design-system choice: Auto (Két Design System), Két Design System, Carbon, GitHub Primer, Microsoft Fluent 2, no design system, or a repository URL/local path. A design system already named in the request counts as the answer. Auto uses [Két Design System](https://github.com/ketvietlab/ketjs/tree/develop/packages/design-system). The agent inspects its actual tokens, components, assets, patterns, and framework, then renders with that framework instead of duplicating markup. An incorrect canonical component is fixed at its source before Atlas work continues.
44
+
45
+ For several atlases in one workspace, the agent creates or reuses one shared framework module for screen presenters, design-system composition, fixture factories, route helpers, and styles. Individual bundles keep flow/state declarations and namespaced screen paths; they do not copy UI code from one another. Production routes and Atlas fixture routes call the same presenter so the mock and built product do not become two visual sources of truth.
46
+
43
47
  ## Use a saved brief for larger projects
44
48
 
45
49
  Save this template as `mockup-brief.md`, fill in the relevant fields, and ask: **“Use the KetAtlas skill to implement mockup-brief.md.”** The brief stays Markdown; do not add its planning fields to `atlas.json`.
@@ -52,7 +56,8 @@ Save this template as `mockup-brief.md`, fill in the relevant fields, and ask: *
52
56
  - Output directory:
53
57
  - Target platforms and viewport sizes:
54
58
  - Product content language:
55
- - Design system, existing HTML, and reference files/URLs:
59
+ - Design system choice (Auto/Két/Carbon/Primer/Fluent 2/none/custom source):
60
+ - Existing application/framework and reference files/URLs:
56
61
  - Requested flows and screen inventory:
57
62
  - Relevant loading, empty, validation, error, and recovery states:
58
63
  - Interactions to demonstrate and synthetic demo inputs:
@@ -60,15 +65,17 @@ Save this template as `mockup-brief.md`, fill in the relevant fields, and ask: *
60
65
 
61
66
  ## Expected delivery
62
67
 
63
- Create actual HTML screens and one KetAtlas version 1 atlas.json. Reuse
64
- screens and styles across flows. Set explicit flow starts, outcomes, and
65
- labelled transitions. Each named screen state must open directly.
68
+ Create native framework routes, or static HTML only for a static product,
69
+ and one KetAtlas version 1 atlas.json. Reuse shared presenters and styles
70
+ across flows and atlases. Set explicit flow starts, outcomes, and labelled
71
+ transitions. Each named screen state must open directly.
66
72
 
67
73
  Use the generated ketatlas.schema.json. Run KetAtlas audit, test the
68
74
  important interactions in the viewer when browser automation is available,
69
75
  and report results or limitations. Include a README with run commands,
70
- flow coverage, demo inputs, and assumptions. Keep the output free of package
71
- manifests, lockfiles, local dependencies, and copied viewer/test tooling.
76
+ flow coverage, demo inputs, and assumptions. Keep the atlas bundle free of
77
+ package manifests, lockfiles, local dependencies, duplicated component/style
78
+ implementations, and copied viewer/test tooling.
72
79
  ```
73
80
 
74
81
  For an existing prototype, ask the agent to reuse its HTML and add or update the atlas instead of rebuilding it. For later changes, name the flow or screen IDs to preserve, for example: **“Add an expired-code recovery branch to sign-in; keep existing screen IDs and audit the updated project.”**
@@ -76,10 +83,13 @@ For an existing prototype, ask the agent to reuse its HTML and add or update the
76
83
  ## Review the result
77
84
 
78
85
  ```sh
79
- npx ketatlas serve ./tasks/mobile/atlas.json
80
- npx ketatlas audit ./tasks/mobile/atlas.json --strict
86
+ npx --yes ketatlas@0.4.0 discover . --json
87
+ npx --yes ketatlas@0.4.0 serve ./tasks/mobile.ketatlas --renderer --port 60550 --html-port 60551
88
+ npx --yes ketatlas@0.4.0 audit ./tasks/mobile.ketatlas --strict
81
89
  ```
82
90
 
91
+ For a genuinely static project, omit `atlas.renderer.json`, `--renderer`, and `--html-port`.
92
+
83
93
  Check the delivered flow coverage against the brief. Open **Try this screen** to test the actual HTML. A successful audit confirms structural and local-file checks, not visual quality, full product coverage, or working production integrations. Intentional remote URLs require separate verification and produce strict-audit warnings.
84
94
 
85
- The skill lives in this repository so teams can review and evolve it alongside the schema and CLI. It works with the published `ketatlas@0.1.1` format; the skill itself can be distributed through GitHub without waiting for a new npm release.
95
+ The skill lives in this repository so teams can review and evolve it alongside the schema and CLI. It also backfills legacy atlas directories into the discoverable bundle pattern before extending them.
@@ -1,25 +1,34 @@
1
1
  # Architecture
2
2
 
3
- KetAtlas is a static browser viewer plus a Node.js command-line toolkit. There is no database, account service or runtime npm dependency. The localhost CLI has a narrow, protected API to read and save the progress sidecar; static hosting remains read-only.
3
+ KetAtlas is a browser viewer plus a Node.js command-line orchestrator. There is no database, account service or runtime npm dependency. Static screens can still use the built-in file server. Framework-native screens run through the product's own server on a second loopback origin, preserving the component implementation as the single source of truth. The localhost CLI has a narrow, protected API to read and save the progress sidecar; static hosting remains read-only.
4
4
 
5
5
  ```text
6
- atlas.json + screen HTML
6
+ <name>.ketatlas/atlas.json
7
7
  │
8
+ ├── discover → workspace bundle catalog
8
9
  ├── validate / audit → diagnostics and CI exit code
9
- │
10
- └── serve → built-in viewer page
11
- │
12
- ├── config validation + URL resolution
13
- ├── deterministic grid layout
14
- ├── Shadow DOM shell + SVG edges
15
- └── lazy HTML iframes + interactive inspector
10
+ └── serve → viewer/control origin
11
+ ├── config validation + deterministic map
12
+ ├── progress API + Shadow DOM viewer
13
+ └── lazy iframes
14
+ ├── static files on the viewer origin, or
15
+ └── native framework renderer origin
16
+ └── shared presenters + Atlas fixtures
16
17
  ```
17
18
 
18
19
  ## Consumer boundary
19
20
 
20
- KetAtlas is installed globally or executed through npx. Consumers provide JSON, a schema, HTML/CSS/JavaScript mock screens, assets, and documentation. They do not need a Node package, lockfile, development dependencies, viewer implementation, or build/test scripts to scaffold, serve, or audit a map.
21
+ KetAtlas is installed globally or executed through npx. Consumers provide a `<name>.ketatlas/` bundle containing JSON, a schema, documentation, and either static mock screens or `atlas.renderer.json`. The suffix is the discovery boundary: tools inspect only its direct `atlas.json`, not arbitrary workspace JSON. Consumers do not need a KetAtlas package, lockfile, development dependencies, viewer implementation, or build/test scripts. A native renderer deliberately reuses the product's existing framework package and lockfile outside the bundle.
22
+
23
+ The package owns the CLI, viewer, validation, renderer supervision, and contract verification. The product owns screen markup, components, styles, fixtures, and framework tests. Static audit does not execute renderer commands or simulate product interactions. Agent browser checks can run through external tooling without adding a test harness to the delivered atlas folder.
24
+
25
+ ## Native renderer boundary
26
+
27
+ `atlas.renderer.json` declares a framework label, an argv array, a working directory, readiness route, and screen base path. It is separate from `atlas.json`: workflow format version 1 remains framework-neutral. `serve --renderer` is required to execute the command, making local code execution explicit. KetAtlas substitutes host/port tokens, waits for a 2xx readiness response, and terminates the renderer with the viewer.
28
+
29
+ The viewer and renderer use different loopback origins. Relative screen and screen-node URLs resolve against `screenBasePath` on the renderer origin. Relative external/note references still resolve beside `atlas.json`. Renderer iframes receive `allow-same-origin` because the separate origin prevents access to the viewer while enabling native module loading, assets, storage, and same-origin requests.
21
30
 
22
- The package owns the CLI, viewer, validation, and framework verification. A product may have its own application tests elsewhere; those are independent of the map format. Static audit does not simulate product interactions. Agent browser checks can run through external tooling without adding a test harness to the delivered atlas folder.
31
+ Multiple atlases should share one framework renderer source. Shared design-system compositions, presenters, fixture factories, and styles live in one product module; each atlas selects namespaced routes through `screenBasePath` and owns only its flow/state declarations. The core does not define a component DSL or translate component trees.
23
32
 
24
33
  ## Ownership
25
34
 
@@ -32,7 +41,7 @@ The package owns the CLI, viewer, validation, and framework verification. A prod
32
41
  | `src/index.d.ts` | Public TypeScript declarations. |
33
42
  | `styles/` | Viewer layout and generated canonical design-system bundles. |
34
43
  | `assets/` | Local fonts, licenses and provenance manifest. |
35
- | `bin/` | Scaffold, JSON serving, validation and static audit. |
44
+ | `bin/` | Bundle discovery, scaffold, serving, validation and audit. |
36
45
  | `templates/` | Self-contained starting projects included in the npm package. |
37
46
  | `examples/` | Maintainer playground with mobile, web and process flows. |
38
47
  | `scripts/` | Reproducible assets, templates, schema and package checks. |
@@ -42,9 +51,9 @@ The package owns the CLI, viewer, validation, and framework verification. A prod
42
51
 
43
52
  Flows are stacked on one canvas. A row and column grow to fit their largest node, so mobile and desktop aspect ratios can coexist. The layout respects authored grid positions. Arrows use orthogonal routes and a small lane offset; this is not an obstacle-avoiding graph-layout engine. Use nearby grid cells and concise labels for readable large diagrams.
44
53
 
45
- Camera changes use an animation frame and a CSS transform. Only the nearest visible screen cards receive iframes, up to the configured cap. Below the preview threshold, all cards show placeholders. This limits embedded-page cost; every node and edge still has a DOM element. There is no claim of unlimited graph size.
54
+ Camera changes use an animation frame and a CSS transform. Drag, wheel, keyboard and pinch input use shared accelerated motion constants while zoom remains anchored under the pointer. Only the nearest visible screen cards receive iframes, up to the configured cap. Below the preview threshold, all cards show placeholders. This limits embedded-page cost; every node and edge still has a DOM element. There is no claim of unlimited graph size.
46
55
 
47
- The inspector reuses the same screen URL at its declared viewport dimensions, with no extra side padding. Its iframe is removed when closed. Reopening a screen loads a fresh instance; editing a prototype is not persistent business state.
56
+ The inspector reuses the same screen URL at its declared viewport dimensions, with no extra side padding. Its iframe is removed when closed. Reopening a screen loads a fresh instance; editing a prototype is not persistent business state. Framework rendering and business simulation remain inside the renderer, never the viewer.
48
57
 
49
58
  ## Isolation and lifecycle
50
59
 
@@ -60,7 +69,7 @@ The default theme uses Inter and KetJS's canonical tokens and primitives. `prepa
60
69
 
61
70
  ## Version 1 boundaries
62
71
 
63
- KetAtlas is a viewer and authoring toolkit, not a visual graph editor. Users edit JSON and HTML in their normal tools. It does not record a graph by watching clicks, synthesize screens, calculate backend permissions, or execute the arrow graph as an automated test. Cross-flow edges, collaborative editing and browser-based project audits are outside the current contract.
72
+ KetAtlas is a viewer and authoring toolkit, not a visual graph editor. Users edit JSON and product framework source in their normal tools. It does not record a graph by watching clicks, synthesize screens, translate React/Vue/KetJS components, calculate backend permissions, or execute the arrow graph as an automated test. Cross-flow edges, collaborative editing and browser-based project audits are outside the current contract.
64
73
 
65
74
  ## Delivery tracking
66
75
 
package/docs/authoring.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # Authoring a useful atlas
2
2
 
3
- Start with a user goal: sign in, approve a purchase, or deliver an order. Give each flow one clear start and a small number of outcomes. Screen files can come from an existing prototype; KetAtlas does not require a particular frontend framework.
3
+ Start with a user goal: sign in, approve a purchase, or deliver an order. Give each flow one clear start and a small number of outcomes. Screen routes come from the product's actual framework; static HTML remains supported for products that are truly static.
4
4
 
5
5
  ## 1. Create a starting point
6
6
 
7
7
  ```sh
8
- ketatlas scaffold ./customer-journeys --template basic
9
- ketatlas serve ./customer-journeys/atlas.json
8
+ ketatlas scaffold ./customer-journeys.ketatlas --template basic
9
+ ketatlas serve ./customer-journeys.ketatlas
10
10
  ```
11
11
 
12
12
  Open a card with a double-click. The preview is actual HTML; links and JavaScript inside it can work independently of the map. Edit those files before adding more nodes.
13
13
 
14
14
  ## 2. Register your screens
15
15
 
16
- Add each reusable screen once in `screens`. Use paths relative to `atlas.json`, including query parameters for prototype states. A React/Vite prototype can expose its own embedded routes through an HTTP URL, provided it permits iframe embedding. Audit reports remote URLs for separate verification.
16
+ Add each reusable screen once in `screens`. Use relative paths, including query parameters for prototype states. Static paths resolve beside `atlas.json`; framework paths resolve beneath the native renderer's `screenBasePath`.
17
17
 
18
18
  For a desktop page:
19
19
 
@@ -28,6 +28,44 @@ For a desktop page:
28
28
 
29
29
  HTML should include a viewport meta tag. Avoid adding a second device frame, reviewer sidebar or fixed outer margin inside the page being embedded; point to its clean preview route instead.
30
30
 
31
+ ## Framework-native screens
32
+
33
+ Use the same implementation framework as the product and design system. React screens stay React, Vue screens stay Vue, and KetJS server components render through KetJS. Do not reproduce component output with copied HTML, string templates, DOM post-processing, or a parallel Atlas component format.
34
+
35
+ Keep one presentation path:
36
+
37
+ ```text
38
+ business loader ─┐
39
+ ├─ shared screen presenter ─ design-system components/styles
40
+ Atlas fixture ───┘
41
+ ```
42
+
43
+ The business loader supplies real data, permissions, and actions. The Atlas route supplies a deterministic fixture selected by its route/query state. Both call the same presenter. If several atlases need the same shell, field, table, or layout, move that composition and its styles into one shared product module rather than copying it between bundles.
44
+
45
+ Place this sidecar beside `atlas.json`:
46
+
47
+ ```json
48
+ {
49
+ "$schema": "https://unpkg.com/ketatlas@0.4.0/renderer.schema.json",
50
+ "version": 1,
51
+ "framework": "ketjs",
52
+ "command": ["npm", "run", "atlas:serve", "--", "--host", "{host}", "--port", "{port}"],
53
+ "cwd": "../..",
54
+ "readyPath": "/__atlas/ready",
55
+ "screenBasePath": "/__atlas/customer-care/"
56
+ }
57
+ ```
58
+
59
+ Commands are argv arrays and do not run through a shell. `cwd` is relative to the bundle. The command may use `{host}`, `{port}`, and `{atlasDirectory}`; the same values are also available through `KETATLAS_HOST`, `KETATLAS_HTML_PORT`, and `KETATLAS_PROJECT_DIR`. `readyPath` must return 2xx. `screenBasePath` must start and end with `/`.
60
+
61
+ Run the two origins explicitly:
62
+
63
+ ```sh
64
+ npx --yes ketatlas@0.4.0 serve ./customer-journeys.ketatlas --renderer --port 60550 --html-port 60551
65
+ ```
66
+
67
+ The first origin owns only the map and progress API. The second origin owns HTML, framework modules, styles, assets, and screen-side requests. Audit validates the renderer contract and graph without executing the command; browser verification must exercise the combined result.
68
+
31
69
  ## 3. Connect actions and decisions
32
70
 
33
71
  Use short labels such as **Submit request**, **Permission missing**, and **Try again**. Put the main journey on row 0, with explicit columns. Place recovery states on row 1 and give their arrows `kind: "recovery"`.
@@ -41,7 +79,7 @@ Click a node to highlight incoming/outgoing arrows and follow a next-step button
41
79
  ## 5. Audit before sharing
42
80
 
43
81
  ```sh
44
- ketatlas audit ./customer-journeys/atlas.json --strict
82
+ ketatlas audit ./customer-journeys.ketatlas --strict
45
83
  ```
46
84
 
47
85
  Keep the JSON and screens in your project's repository. Review changes in pull requests. Share the directory or run the same serve command in the recipient's checkout. No hosted account or service state is required.
package/docs/cli.md CHANGED
@@ -1,44 +1,64 @@
1
1
  # CLI reference
2
2
 
3
- Install once with `npm install --global ketatlas@0.1.1`, or prefix commands with `npx --yes ketatlas@0.1.1`. No dependency installation is required in the consumer directory. `node /path/to/ketatlas/bin/ketatlas.js` is also available to framework maintainers.
3
+ Install once with `npm install --global ketatlas`, or prefix commands with `npx --yes ketatlas`. No dependency installation is required in the consumer directory. `node /path/to/ketatlas/bin/ketatlas.js` is also available to framework maintainers.
4
4
 
5
- A consumer keeps only its JSON/schema, product HTML/CSS/JavaScript, assets, and documentation. The package manifest, lockfile, development scripts, and browser test dependencies belong to the tool. Normal `serve`, `validate`, and `audit` calls do not create files in the consumer; `audit --output` is an explicit exception.
5
+ A consumer keeps its JSON/schema, documentation, and either static product assets or a native renderer sidecar. KetAtlas package files and browser test dependencies belong to the tool; framework package files remain in the product workspace. Normal `serve`, `validate`, and `audit` calls do not create files in the consumer; `audit --output` is an explicit exception.
6
6
 
7
7
  ## Scaffold
8
8
 
9
9
  ```sh
10
- ketatlas scaffold ./journeys
11
- ketatlas scaffold ./approvals --template web
12
- ketatlas scaffold ./operations --template process
10
+ ketatlas scaffold ./journeys.ketatlas
11
+ ketatlas scaffold ./approvals.ketatlas --template web
12
+ ketatlas scaffold ./operations.ketatlas --template process
13
13
  ```
14
14
 
15
15
  `basic` is the default: two interactive mobile pages and one flow. `web` contains desktop purchase approval pages. `process` contains notes and an external handoff, without HTML screens. Every template includes a local JSON Schema for editor completion and a README. Product HTML and its styles belong to the new project.
16
16
 
17
- `init` is an alias for `scaffold`. The destination must be missing or empty. Existing files are never overwritten; there is no `--force` flag.
17
+ `init` is an alias for `scaffold`. The destination must end in `.ketatlas` and be missing or empty. Existing files are never overwritten; there is no `--force` flag.
18
+
19
+ ## Discover bundles
20
+
21
+ ```sh
22
+ ketatlas discover .
23
+ ketatlas discover . --json
24
+ ```
25
+
26
+ Discovery walks the selected workspace for exact `*.ketatlas/atlas.json` bundles. It skips dependency, generated, cache, Git and vendor directories; it does not parse unrelated JSON. The JSON report contains `version`, `root`, `atlases`, and `errors`, including each atlas title, path, directory, screens and flow count. Invalid bundle manifests are reported and produce exit code 1.
27
+
28
+ Legacy manifest paths remain valid command arguments, but discovery intentionally ignores them. Migrate a self-contained legacy directory by renaming it to `<name>.ketatlas`; see the bundled skill for mixed-directory migration safeguards.
18
29
 
19
30
  ## Serve a JSON file
20
31
 
21
32
  ```sh
22
- ketatlas serve ./tasks/onboarding/atlas.json
23
- ketatlas serve ./tasks/onboarding/atlas.json --port 4180
24
- ketatlas serve ./tasks/onboarding/atlas.json --root .
33
+ ketatlas serve ./tasks/onboarding.ketatlas
34
+ ketatlas serve ./tasks/onboarding.ketatlas --port 4180
35
+ ketatlas serve ./tasks/onboarding.ketatlas --renderer --port 60550 --html-port 60551
36
+ ketatlas serve ./legacy/atlas.json --root .
25
37
  ```
26
38
 
27
- The tool supplies the viewer page. It validates the JSON at startup, serves your files, and mounts the atlas at `/`. The default file root is the JSON file's directory. Choose `--root` when a relative URL points to a sibling directory outside that default root. The JSON must be inside the selected root.
39
+ The tool supplies the viewer page. It validates the JSON at startup, serves your files, and mounts the atlas at `/`. Passing a `.ketatlas` directory resolves its `atlas.json` and uses the bundle as the file root. Explicit legacy JSON paths still support `--root` when a relative URL points outside the manifest directory.
28
40
 
29
41
  Open the printed localhost URL. Changes appear after refreshing; there is no hot reload or authoring server state. Use `?flow=your-flow-id` or `?screen=your-screen-id` to open a specific part of the map. An unknown ID falls back to the first flow.
30
42
 
31
43
  The `/__ketatlas__/` route is reserved for viewer assets. Dotfiles and paths resolving outside the file root, including symlink escapes, are not served. Only GET/HEAD are supported. The server binds to `127.0.0.1`; it is a local preview server, not a production application server.
32
44
 
45
+ ### Native renderer mode
46
+
47
+ `--renderer` reads `atlas.renderer.json` beside the manifest and executes its command array without a shell. This is opt-in because the project controls the command. The renderer gets `KETATLAS_HOST`, `KETATLAS_HTML_PORT`, and `KETATLAS_PROJECT_DIR`; command arguments can also use `{host}`, `{port}`, and `{atlasDirectory}` placeholders.
48
+
49
+ `--port` selects the viewer/control origin. `--html-port` selects the separate framework renderer origin and defaults to the following port. The ports must differ. KetAtlas waits for the configured `readyPath`, resolves relative screen URLs beneath `screenBasePath`, prints both origins, and terminates the renderer when the viewer receives SIGINT or SIGTERM.
50
+
51
+ The second origin lets trusted React/Vue/KetJS routes load their own modules, styles, assets, and same-origin requests while remaining isolated from the viewer origin. A shared product renderer can serve namespaced routes for several atlas bundles so they reuse the same presenters and styles.
52
+
33
53
  `serve <directory>` also works as a plain static preview for an existing HTML integration. JSON mode is recommended for project planning.
34
54
 
35
55
  ## Audit
36
56
 
37
57
  ```sh
38
- ketatlas audit ./atlas.json
39
- ketatlas audit ./atlas.json --root .. --strict
40
- ketatlas audit ./atlas.json --json
41
- ketatlas audit ./atlas.json --json --output audit-report.json
58
+ ketatlas audit ./tasks/onboarding.ketatlas
59
+ ketatlas audit ./tasks/onboarding.ketatlas --strict
60
+ ketatlas audit ./tasks/onboarding.ketatlas --json
61
+ ketatlas audit ./tasks/onboarding.ketatlas --json --output audit-report.json
42
62
  ```
43
63
 
44
64
  Audit checks:
@@ -49,8 +69,9 @@ Audit checks:
49
69
  - Local screen files and node URL overrides, using the same root boundary as the server.
50
70
  - Literal resource references in HTML (`src`/`href`), links between HTML pages, and CSS imports/URLs.
51
71
  - A viewport meta tag in HTML previews.
72
+ - A colocated native renderer contract when present. Its screen paths are treated as framework routes rather than local files.
52
73
 
53
- Remote URLs are reported but not fetched. Audit does not execute JavaScript, discover dynamic imports/URLs, validate remote CSP or `X-Frame-Options`, simulate user actions, or verify backend/native behavior. Use your project's browser tests for those checks.
74
+ Remote URLs are reported but not fetched. Audit does not execute renderer commands or JavaScript, discover dynamic imports/URLs, validate remote CSP or `X-Frame-Options`, simulate user actions, or verify backend/native behavior. Use the two-port preview and your project's browser tests for those checks.
54
75
 
55
76
  Exit codes:
56
77
 
@@ -64,7 +85,7 @@ Exit codes:
64
85
  ## Validate and version
65
86
 
66
87
  ```sh
67
- ketatlas validate ./atlas.json
88
+ ketatlas validate ./tasks/onboarding.ketatlas
68
89
  ketatlas --version
69
90
  ketatlas --help
70
91
  ```
@@ -73,4 +94,4 @@ ketatlas --help
73
94
 
74
95
  ## Screen progress
75
96
 
76
- `progress <atlas.json> --json` reads the progress record, content revision and unique-screen summary. `--init` creates a missing sidecar. `--set <screen-id> --record <record.json> --expect <revision>` replaces one record with conflict detection. `serve <atlas.json> --read-only` disables local progress writes. See [Screen progress](progress.md) for examples and persistence rules.
97
+ `progress <bundle|atlas.json> --json` reads the progress record, content revision and unique-screen summary. `--init` creates a missing sidecar. `--set <screen-id> --record <record.json> --expect <revision>` replaces one record with conflict detection. `serve <bundle|atlas.json> --read-only` disables local progress writes. See [Screen progress](progress.md) for examples and persistence rules.
@@ -14,7 +14,26 @@ The [JSON Schema](../schema.json) defines version 1. A generated project contain
14
14
  | `flows` | Yes | A nonempty array of workflows. |
15
15
  | `$schema` | No | Schema URL/path for your editor. |
16
16
 
17
- All viewer UI is English. Project titles, descriptions and labels can use any language. Search ignores case and combining accents.
17
+ All viewer UI is English. Project titles, descriptions and labels can use any language. Search ignores case and combining accents. Workflow format version 1 remains framework-neutral; native rendering is declared in a separate sidecar.
18
+
19
+ ## Native renderer sidecar
20
+
21
+ `atlas.renderer.json` is optional and sits beside `atlas.json`. Its [schema](../renderer.schema.json) has these fields:
22
+
23
+ | Field | Required | Default / meaning |
24
+ | ---------------- | -------- | ------------------------------------------------------------------- |
25
+ | `version` | Yes | Renderer contract version; must be `1`. |
26
+ | `framework` | Yes | Human/tooling label such as `react`, `vue`, or `ketjs`. |
27
+ | `command` | Yes | Nonempty argv array executed directly, without a shell. |
28
+ | `cwd` | No | Working directory relative to the bundle; defaults to `.`. |
29
+ | `readyPath` | No | Origin-relative 2xx readiness route; defaults to `/`. |
30
+ | `screenBasePath` | No | Origin-relative screen route prefix ending in `/`; defaults to `/`. |
31
+ | `readyTimeoutMs` | No | Startup timeout from 100–120000 milliseconds; defaults to 15000. |
32
+ | `$schema` | No | Schema URL/path for editor completion. |
33
+
34
+ The command may interpolate `{host}`, `{port}`, and `{atlasDirectory}`. The corresponding environment values are `KETATLAS_HOST`, `KETATLAS_HTML_PORT`, and `KETATLAS_PROJECT_DIR`. The sidecar changes relative resolution for registered screens and screen-node URL overrides only; note/external references remain relative to `atlas.json`.
35
+
36
+ `audit` validates a discovered sidecar without running it. `serve --renderer` explicitly authorizes command execution and starts the framework on `--html-port`.
18
37
 
19
38
  ## Screen
20
39
 
@@ -22,7 +41,7 @@ All viewer UI is English. Project titles, descriptions and labels can use any la
22
41
  | ------------- | -------- | --------------------------------------------------------------------- |
23
42
  | `id` | Yes | Unique across the atlas. |
24
43
  | `title` | Yes | Human-readable screen name. |
25
- | `url` | Yes | Relative URL or HTTP(S) URL for actual HTML. |
44
+ | `url` | Yes | Relative or HTTP(S) URL for the actual rendered page. |
26
45
  | `viewport` | No | Overrides the atlas viewport. Both dimensions are integers, 160–4096. |
27
46
  | `description` | No | Context inherited by its nodes. |
28
47
  | `badge` | No | Small card footer label; defaults to `Preview`. |
@@ -62,6 +62,7 @@ The browser implementation has no React dependency. Instantiate it after mount;
62
62
  | Option | Default | Purpose |
63
63
  | ------------------ | ------------------------------------------ | ------------------------------------------------------------------------------- |
64
64
  | `baseURL` | Page URL; JSON response URL in `loadAtlas` | Resolve screen and node URLs. |
65
+ | `screenBaseURL` | `baseURL` | Resolve registered screens and screen-node URL overrides on another origin. |
65
66
  | `assetBaseURL` | Package directory | Public directory containing `styles/` and `assets/`; must end in `/`. |
66
67
  | `initialFlow` | First flow | Initial flow ID. |
67
68
  | `theme` | `light` | `light` or `dark`. |
@@ -101,7 +102,9 @@ These are viewer events. KetAtlas does not inspect or synchronize navigation ins
101
102
 
102
103
  ## Embedding behavior
103
104
 
104
- Iframe previews are sandboxed. Scripts and forms work by default, but the page has an opaque origin: authenticated fetch, storage, some module imports, and other same-origin features can require additional permissions. Only add `allow-same-origin` for trusted prototypes. Combining it with scripts on a same-origin page weakens sandbox isolation.
105
+ Iframe previews are sandboxed. Scripts and forms work by default, but a static page has an opaque origin: authenticated fetch, storage, some module imports, and other same-origin features can require additional permissions. Only add `allow-same-origin` for trusted prototypes. Combining it with scripts on a same-origin page weakens sandbox isolation.
106
+
107
+ The CLI's native renderer mode uses `screenBaseURL` and adds `allow-same-origin` automatically. Its HTML server is a separate loopback origin from the viewer, so framework routes can use native modules and same-origin resources without gaining same-origin access to the viewer/control page.
105
108
 
106
109
  Remote pages can reject framing using CSP or `X-Frame-Options`. KetAtlas cannot override that. Use a permitted embedded route or the **Open in new tab** action. Test links/forms with the default sandbox before sharing a project.
107
110
 
package/docs/migration.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Migrating the KétSuite mobile map
2
2
 
3
+ ## From copied HTML to a 0.4 native renderer
4
+
5
+ Version 0.4 does not require static projects to change. When an atlas copied or reconstructed markup from a React, Vue, KetJS, or other framework, remove that duplicate implementation instead:
6
+
7
+ 1. Extract one shared screen presenter in the product's framework and compose canonical design-system components there.
8
+ 2. Keep business loaders and Atlas fixtures separate; pass both into the same presenter shape.
9
+ 3. Reuse that presenter and its styles across all atlases in the workspace.
10
+ 4. Add namespaced Atlas routes and `atlas.renderer.json` beside each manifest.
11
+ 5. Change screen URLs to paths relative to the declared `screenBasePath`.
12
+ 6. Run `ketatlas@0.4.0 audit`, then use `serve --renderer` and verify both origins in a browser.
13
+
14
+ Do not migrate to a JSON component tree or another generated HTML layer. The framework component remains the screen source of truth.
15
+
16
+ ## Bundle layout backfill
17
+
18
+ Current projects use `<name>.ketatlas/atlas.json`. For a legacy self-contained Atlas directory, rename the whole directory so relative screen, style and asset URLs remain unchanged. When `atlas.json` shares a directory with unrelated application code, create a sibling `<name>.ketatlas` bundle, move only Atlas-owned files, and update relative URLs for resources that intentionally remain outside it. Keep one canonical manifest, then run `ketatlas discover <workspace> --json`, `ketatlas validate <name>.ketatlas`, and `ketatlas audit <name>.ketatlas --strict`.
19
+
20
+ The CLI continues to accept a direct legacy JSON path so migration can be audited before and after the move. Discovery intentionally reports only the standard bundle pattern.
21
+
3
22
  The original mobile map remains in its project. KetAtlas does not copy its business data or change the mobile repository. The extraction generalizes the viewer; project migration is a separate configuration change.
4
23
 
5
24
  ## Field mapping
package/docs/progress.md CHANGED
@@ -71,11 +71,11 @@ Evidence kinds are `pr`, `test`, `release`, `reference`. Required fields: `id`,
71
71
  ## Editing locally and from agents
72
72
 
73
73
  ```sh
74
- npx --yes ketatlas@0.2.5 serve atlas.json
75
- npx --yes ketatlas@0.2.5 serve atlas.json --read-only
76
- npx --yes ketatlas@0.2.5 progress atlas.json --init
77
- npx --yes ketatlas@0.2.5 progress atlas.json --json
78
- npx --yes ketatlas@0.2.5 progress atlas.json --set sign-in --record record.json --expect REVISION_FROM_READ
74
+ npx --yes ketatlas serve ./account-access.ketatlas
75
+ npx --yes ketatlas serve ./account-access.ketatlas --read-only
76
+ npx --yes ketatlas progress ./account-access.ketatlas --init
77
+ npx --yes ketatlas progress ./account-access.ketatlas --json
78
+ npx --yes ketatlas progress ./account-access.ketatlas --set sign-in --record record.json --expect REVISION_FROM_READ
79
79
  ```
80
80
 
81
81
  `--init` explicitly creates Unassessed records and refuses an existing progress file. `--set` replaces one complete screen record; preserve existing checklist IDs, evidence and state references. Read the revision with `--json` first. Do not retry a stale revision by blindly substituting a new one: reload and reconcile changes. `updatedAt` is stamped on successful record writes.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketatlas",
3
- "version": "0.2.5",
4
- "description": "Interactive HTML maps for screens, workflows, and user journeys.",
3
+ "version": "0.4.0",
4
+ "description": "Interactive framework-native maps for screens, workflows, and user journeys.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -19,7 +19,8 @@
19
19
  "import": "./src/index.js"
20
20
  },
21
21
  "./schema.json": "./schema.json",
22
- "./progress.schema.json": "./progress.schema.json"
22
+ "./progress.schema.json": "./progress.schema.json",
23
+ "./renderer.schema.json": "./renderer.schema.json"
23
24
  },
24
25
  "bin": {
25
26
  "ketatlas": "bin/ketatlas.js"
@@ -37,19 +38,21 @@
37
38
  "skills",
38
39
  "docs",
39
40
  "CHANGELOG.md",
40
- "progress.schema.json"
41
+ "progress.schema.json",
42
+ "renderer.schema.json"
41
43
  ],
42
44
  "scripts": {
43
45
  "dev": "node bin/ketatlas.js serve examples/atlas.json --root . --port 4178",
46
+ "build:demo": "node scripts/build-demo.mjs",
44
47
  "validate": "node bin/ketatlas.js audit examples/atlas.json --root . && node bin/ketatlas.js audit templates/basic/atlas.json && node bin/ketatlas.js audit templates/web/atlas.json && node bin/ketatlas.js audit templates/process/atlas.json",
45
48
  "test": "node --test tests/*.test.js",
46
- "test:e2e": "node tests/browser.mjs && node tests/progress-browser.mjs",
49
+ "test:e2e": "node tests/browser.mjs && node tests/progress-browser.mjs && node tests/renderer-browser.mjs",
47
50
  "check": "npm run validate && npm test && npm run test:e2e",
48
51
  "format": "prettier --write src styles/ketatlas.css bin scripts docs examples starter templates skills tests '*.md' '*.json' .github/workflows",
49
52
  "format:check": "prettier --check src styles/ketatlas.css bin scripts docs examples starter templates skills tests '*.md' '*.json' .github/workflows",
50
53
  "prepare:assets": "node scripts/prepare-assets.mjs",
51
54
  "prepack": "node scripts/verify-assets.mjs",
52
- "prepare:templates": "node scripts/schema.mjs && node scripts/progress-schema.mjs && node scripts/prepare-templates.mjs",
55
+ "prepare:templates": "node scripts/schema.mjs && node scripts/progress-schema.mjs && node scripts/renderer-schema.mjs && node scripts/prepare-templates.mjs",
53
56
  "test:package": "node tests/package.mjs"
54
57
  },
55
58
  "devDependencies": {
@@ -0,0 +1,44 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "KetAtlas native renderer configuration",
4
+ "type": "object",
5
+ "properties": {
6
+ "$schema": {
7
+ "type": "string"
8
+ },
9
+ "version": {
10
+ "const": 1
11
+ },
12
+ "framework": {
13
+ "type": "string",
14
+ "pattern": "\\S"
15
+ },
16
+ "command": {
17
+ "type": "array",
18
+ "minItems": 1,
19
+ "items": {
20
+ "type": "string",
21
+ "pattern": "\\S"
22
+ }
23
+ },
24
+ "cwd": {
25
+ "type": "string",
26
+ "pattern": "\\S"
27
+ },
28
+ "readyPath": {
29
+ "type": "string",
30
+ "pattern": "^/"
31
+ },
32
+ "screenBasePath": {
33
+ "type": "string",
34
+ "pattern": "^/.*/$|^/$"
35
+ },
36
+ "readyTimeoutMs": {
37
+ "type": "integer",
38
+ "minimum": 100,
39
+ "maximum": 120000
40
+ }
41
+ },
42
+ "required": ["version", "framework", "command"],
43
+ "additionalProperties": false
44
+ }