sdtk-design-kit 0.4.0 → 0.5.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `sdtk-design-kit` is the public CLI package for SDTK-DESIGN.
4
4
 
5
- Package version in this source snapshot: `0.4.0`
5
+ Package version in this source snapshot: `0.5.0`
6
6
  CLI command: `sdtk-design`
7
7
 
8
8
  SDTK-DESIGN is a local-first MVP design planner and reviewer. It turns either a rough MVP idea or explicit SDTK-SPEC design artifacts into reviewable design docs, a static prototype, visual review evidence, and an SDTK-CODE handoff.
@@ -61,6 +61,7 @@ sdtk-design wireframe --screen landing
61
61
  sdtk-design system --style minimal-saas
62
62
  sdtk-design prototype
63
63
  sdtk-design preview
64
+ sdtk-design open
64
65
  sdtk-design styles
65
66
  sdtk-design review --artifact docs/design/prototype/index.html
66
67
  sdtk-design handoff
@@ -69,6 +70,8 @@ sdtk-design status
69
70
 
70
71
  `preview` starts a local Preview Studio (browser): it renders the prototype screens, lets you click/shift-click elements to annotate them with a note, and (via the **Tokens** panel) live-preview design-token tweaks on the `:root` CSS variables a screen declares. On "Send to agent" it shows a confirm summary, writes `docs/design/feedback/DESIGN_FEEDBACK_<timestamp>.md` (schema `sdtk.design.feedback.v1`), then a copy-ready instruction to apply it. Run the `design-prototype` skill afterward to apply that scoped feedback. The studio serves the prototype read-only, writes only under `docs/design/feedback/`, and never runs the agent itself.
71
72
 
73
+ `open` is the always-open entry to the same Preview Studio: unlike a strict preview it never hard-fails on a missing prototype — if none exists yet it opens an empty-state with the Style Gallery and "run `sdtk-design prototype` first" guidance; once a prototype is present it renders the screens for annotation. (`preview` is now equally graceful about a missing manifest.)
74
+
72
75
  `styles` opens the same studio focused on the **Style Gallery** — a visual menu of the category-oriented style presets (swatches + type sample + summary). Click a card to copy its `start --style <preset>` command. It needs no prototype (pick a style before generating) and is choose-only: it copies a command, it writes nothing.
73
76
 
74
77
  Visual style presets:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdtk-design-kit",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Local-first MVP design planner and reviewer for SDTK workspaces.",
5
5
  "bin": {
6
6
  "sdtk-design": "bin/sdtk-design.js"
@@ -15,6 +15,7 @@ Usage:
15
15
  sdtk-design system --style minimal-saas
16
16
  sdtk-design prototype
17
17
  sdtk-design preview
18
+ sdtk-design open
18
19
  sdtk-design styles
19
20
  sdtk-design review --artifact docs/design/prototype/index.html
20
21
  sdtk-design handoff
@@ -60,6 +61,7 @@ Command status:
60
61
  system Available.
61
62
  prototype Available SPEC-driven prototype manifest launcher.
62
63
  preview Available local Preview Studio (render screens + element-level annotate to feedback).
64
+ open Available always-open Preview Studio (empty-state when no prototype yet).
63
65
  styles Available visual Style Gallery (browse + copy a "start --style" command).
64
66
  handoff Available.
65
67
  review Available for local markdown and static HTML artifacts.
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+
3
+ // BK-278 P-A — `sdtk-design open`: the discoverable entry point that opens the
4
+ // Preview Studio whether or not a prototype exists yet. It is a thin wrapper
5
+ // over `runDesignPreview` (which is now graceful about a missing manifest), so
6
+ // `sdtk-design open` always starts the studio — empty-state when there is no
7
+ // prototype, full annotate surface once `sdtk-design prototype` has run. This
8
+ // mirrors how `sdtk-wiki atlas open` / `sdtk-wiki kanban` always open.
9
+
10
+ const { parseFlags } = require("../lib/args");
11
+ const { ValidationError } = require("../lib/errors");
12
+ const { runDesignPreview, tryOpenBrowser } = require("./preview");
13
+
14
+ const OPEN_FLAG_DEFS = {
15
+ help: { type: "boolean" },
16
+ "project-path": { type: "string" },
17
+ port: { type: "string" },
18
+ "no-open": { type: "boolean" },
19
+ };
20
+
21
+ function cmdOpenHelp() {
22
+ console.log(`SDTK-DESIGN Open (Preview Studio)
23
+
24
+ Usage:
25
+ sdtk-design open [--project-path <path>] [--port <n>] [--no-open]
26
+
27
+ Example:
28
+ sdtk-design open
29
+ sdtk-design open --no-open
30
+
31
+ What it does:
32
+ Opens the Preview Studio in your browser. Unlike a strict preview, it always
33
+ opens: if no prototype exists yet it shows an empty-state with the Style
34
+ Gallery and "run sdtk-design prototype first" guidance; once a prototype is
35
+ present it renders the screens for element-level annotation.
36
+
37
+ Reads:
38
+ docs/design/prototype/.manifest.json (optional)
39
+ docs/design/prototype/screens/*.html (skill-owned screen HTML, when present)
40
+
41
+ Creates:
42
+ Nothing directly. The studio writes only via its in-browser "Send to agent"
43
+ action: docs/design/feedback/DESIGN_FEEDBACK_<timestamp>.md.
44
+
45
+ Safety:
46
+ Local server on 127.0.0.1 only; no external network. Never shells out.
47
+ In WSL2/Docker, use --no-open and tunnel the printed URL (e.g. cloudflared).`);
48
+ return 0;
49
+ }
50
+
51
+ async function cmdOpen(args) {
52
+ const { flags, positionals } = parseFlags(args || [], OPEN_FLAG_DEFS);
53
+ if (flags.help) return cmdOpenHelp();
54
+ if (positionals.length > 0) {
55
+ throw new ValidationError(
56
+ `Unsupported open argument: ${positionals.join(" ")}. Use sdtk-design open [--project-path <path>] [--port <n>] [--no-open]. No server started.`
57
+ );
58
+ }
59
+
60
+ const result = await runDesignPreview({
61
+ projectPath: flags["project-path"],
62
+ port: flags.port,
63
+ noOpen: Boolean(flags["no-open"]),
64
+ });
65
+
66
+ console.log(`[design] Preview Studio: ${result.url}`);
67
+ if (result.screenCount > 0) {
68
+ console.log(`[design] Serving ${result.screenCount} screen(s) from docs/design/prototype/`);
69
+ console.log("[design] Annotate elements, then \"Send to agent\" writes docs/design/feedback/DESIGN_FEEDBACK_<timestamp>.md");
70
+ } else {
71
+ console.log("[design] No prototype yet — opening with an empty-state. Browse the Style Gallery,");
72
+ console.log("[design] then run sdtk-design prototype to populate screens for annotation.");
73
+ }
74
+ if (result.noOpen) {
75
+ console.log("[design] --no-open: not launching a browser. Open the URL above (tunnel it on WSL2/Docker).");
76
+ } else {
77
+ tryOpenBrowser(result.url);
78
+ }
79
+ console.log("[design] Press Ctrl+C to stop the server.");
80
+
81
+ return new Promise((resolve) => {
82
+ const shutdown = () => {
83
+ try { result.server.close(); } catch (_) {}
84
+ resolve(0);
85
+ };
86
+ process.on("SIGINT", shutdown);
87
+ process.on("SIGTERM", shutdown);
88
+ });
89
+ }
90
+
91
+ module.exports = {
92
+ cmdOpen,
93
+ cmdOpenHelp,
94
+ };
@@ -40,7 +40,8 @@ Example:
40
40
  sdtk-design preview --port 3210 --no-open
41
41
 
42
42
  Reads:
43
- docs/design/prototype/.manifest.json (run sdtk-design prototype first)
43
+ docs/design/prototype/.manifest.json (optional without it the studio opens
44
+ with an empty-state; run sdtk-design prototype to populate screens)
44
45
  docs/design/prototype/screens/*.html (skill-owned screen HTML)
45
46
 
46
47
  In the studio:
@@ -100,16 +101,17 @@ async function runDesignPreview({ projectPath, port, noOpen = false }) {
100
101
  throw new ValidationError(`--project-path is not a valid directory: ${resolvedProjectPath}. No server started.`);
101
102
  }
102
103
  const paths = describeDesignPaths(resolvedProjectPath);
103
- if (!fs.existsSync(paths.prototypeManifestPath)) {
104
- throw new ValidationError(
105
- "Missing docs/design/prototype/.manifest.json. Run sdtk-design prototype first. No server started."
106
- );
107
- }
108
- let manifest;
109
- try {
110
- manifest = JSON.parse(fs.readFileSync(paths.prototypeManifestPath, "utf-8"));
111
- } catch (err) {
112
- throw new ValidationError(`Could not read prototype manifest: ${err.message}. No server started.`);
104
+ // Graceful no-manifest (BK-278 P-A): the studio opens with an empty-state
105
+ // instead of hard-failing, mirroring `sdtk-design styles`. A missing or
106
+ // malformed manifest must not block opening the studio — the user can still
107
+ // browse the Style Gallery and read the "run prototype first" instructions.
108
+ let manifest = { screens: [] };
109
+ if (fs.existsSync(paths.prototypeManifestPath)) {
110
+ try {
111
+ manifest = JSON.parse(fs.readFileSync(paths.prototypeManifestPath, "utf-8"));
112
+ } catch (_) {
113
+ manifest = { screens: [] };
114
+ }
113
115
  }
114
116
  const screenCount = Array.isArray(manifest.screens) ? manifest.screens.length : 0;
115
117
 
@@ -163,9 +165,14 @@ async function cmdPreview(args) {
163
165
  });
164
166
 
165
167
  console.log(`[design] Preview Studio: ${result.url}`);
166
- console.log(`[design] Serving ${result.screenCount} screen(s) from docs/design/prototype/`);
167
- console.log("[design] Annotate elements, then \"Send to agent\" writes docs/design/feedback/DESIGN_FEEDBACK_<timestamp>.md");
168
- console.log("[design] Then run the design-prototype skill to apply the scoped feedback.");
168
+ if (result.screenCount > 0) {
169
+ console.log(`[design] Serving ${result.screenCount} screen(s) from docs/design/prototype/`);
170
+ console.log("[design] Annotate elements, then \"Send to agent\" writes docs/design/feedback/DESIGN_FEEDBACK_<timestamp>.md");
171
+ console.log("[design] Then run the design-prototype skill to apply the scoped feedback.");
172
+ } else {
173
+ console.log("[design] No prototype yet — opening with an empty-state. Browse the Style Gallery,");
174
+ console.log("[design] then run sdtk-design prototype to populate screens for annotation.");
175
+ }
169
176
  if (result.noOpen) {
170
177
  console.log("[design] --no-open: not launching a browser. Open the URL above (tunnel it on WSL2/Docker).");
171
178
  } else {
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ const { cmdHandoff } = require("./commands/handoff");
5
5
  const { cmdHelp } = require("./commands/help");
6
6
  const { cmdInit } = require("./commands/init");
7
7
  const { cmdPreview } = require("./commands/preview");
8
+ const { cmdOpen } = require("./commands/open");
8
9
  const { cmdStyles } = require("./commands/styles");
9
10
  const { cmdPrototype } = require("./commands/prototype");
10
11
  const { cmdReview } = require("./commands/review");
@@ -76,6 +77,9 @@ async function run(argv) {
76
77
  if (command === "preview") {
77
78
  return cmdPreview(args);
78
79
  }
80
+ if (command === "open") {
81
+ return cmdOpen(args);
82
+ }
79
83
  if (command === "styles") {
80
84
  return cmdStyles(args);
81
85
  }