@dfosco/storyboard 0.7.1 → 0.9.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/dist/storyboard-ui.css +1 -1
- package/dist/storyboard-ui.js +14128 -10953
- package/dist/storyboard-ui.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tiny-canvas.css +1 -1
- package/package.json +138 -128
- package/scaffold/AGENTS.md +9 -7
- package/scaffold/README.md +18 -0
- package/scaffold/deploy.yml +21 -0
- package/scaffold/gitignore +8 -14
- package/scaffold/preview.yml +40 -0
- package/scaffold/{manifest.json → scaffold.config.json} +73 -3
- package/scaffold/scripts/aggregate-artifacts.mjs +257 -0
- package/scaffold/skills/canvas/SKILL.md +1 -1
- package/scaffold/skills/migrate-0.5.0/SKILL.md +1 -1
- package/scaffold/skills/ship/SKILL.md +2 -2
- package/scaffold/skills/worktree/SKILL.md +1 -1
- package/scaffold/src/_prototype.jsx +17 -0
- package/scaffold/src/_story.jsx +13 -0
- package/scaffold/src/library/README.md +34 -0
- package/scaffold/src/library/_app.jsx +41 -0
- package/scaffold/src/library/_app.module.css +2 -0
- package/scaffold/src/library/create.jsx +10 -0
- package/scaffold/src/library/index.jsx +14 -0
- package/scaffold/src/library/mount.jsx +51 -0
- package/scaffold/src/library/prototypes-entry.jsx +57 -0
- package/scaffold/src/library/routes.jsx +205 -0
- package/scaffold/src/library/viewfinder.jsx +13 -0
- package/scaffold/src/library/workspace.jsx +17 -0
- package/scripts/aggregate-artifacts.mjs +257 -0
- package/src/canvas/style.css +16 -16
- package/src/core/artifact/operations.js +54 -15
- package/src/core/artifact/schemas/canvas.schema.json +7 -1
- package/src/core/autosync/server.test.js +1 -1
- package/src/core/canvas/hot-pool.js +21 -33
- package/src/core/canvas/materializer.js +39 -13
- package/src/core/canvas/selectedWidgets.js +1 -1
- package/src/core/canvas/server.js +376 -100
- package/src/core/canvas/server.test.js +472 -2
- package/src/core/canvas/terminal-server.js +144 -57
- package/src/core/canvas/undoRedo.js +174 -0
- package/src/core/canvas/undoRedo.test.js +250 -0
- package/src/core/cli/artifact.js +2 -0
- package/src/core/cli/buildManifest.js +34 -0
- package/src/core/cli/canvasRedo.js +44 -0
- package/src/core/cli/canvasUndo.js +40 -0
- package/src/core/cli/create.js +151 -23
- package/src/core/cli/dev.js +23 -35
- package/src/core/cli/index.js +21 -0
- package/src/core/cli/schemas.js +8 -4
- package/src/core/cli/serverUrl.js +24 -0
- package/src/core/cli/setup.js +14 -25
- package/src/core/cli/terminal-welcome.js +12 -6
- package/src/core/cli/updateVersion.js +42 -2
- package/src/core/cli/workleaf.js +140 -0
- package/src/core/comments/api.js +1 -1
- package/src/core/comments/queries.js +3 -0
- package/src/core/comments/ui/CommentWindow.jsx +3 -2
- package/src/core/comments/ui/comment-layout.css +14 -14
- package/src/core/data/artifactIndex.js +235 -0
- package/src/core/data/artifactIndex.test.js +203 -0
- package/src/core/data/artifactManifest.js +290 -0
- package/src/core/data/artifactManifest.test.js +207 -0
- package/src/core/data/viewfinder.js +47 -7
- package/src/core/index.js +24 -1
- package/src/core/inspector/highlighter.js +1 -1
- package/src/core/inspector/mouseMode.js +2 -2
- package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar-image.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar.jsx +2 -2
- package/src/core/lib/components/ui/checkbox/checkbox.jsx +12 -9
- package/src/core/lib/components/ui/dialog/dialog-content.jsx +45 -31
- package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +9 -5
- package/src/core/lib/components/ui/dialog/dialog.jsx +12 -3
- package/src/core/lib/components/ui/dialog/dialog.module.css +118 -0
- package/src/core/lib/components/ui/dialog/index.js +4 -34
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +3 -3
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +19 -9
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +8 -8
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +15 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +14 -7
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +8 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +4 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +8 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +2 -2
- package/src/core/lib/components/ui/label/label.jsx +1 -2
- package/src/core/lib/components/ui/panel/panel-close.jsx +7 -4
- package/src/core/lib/components/ui/panel/panel-content.jsx +7 -9
- package/src/core/lib/components/ui/panel/panel-title.jsx +3 -3
- package/src/core/lib/components/ui/panel/panel.jsx +11 -2
- package/src/core/lib/components/ui/separator/separator.jsx +6 -4
- package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +7 -6
- package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +13 -6
- package/src/core/lib/components/ui/tooltip/tooltip.jsx +5 -5
- package/src/core/modes/modes.css +4 -4
- package/src/core/mountStoryboardCore.js +287 -83
- package/src/core/mountStoryboardCore.test.js +198 -0
- package/src/core/rename-watcher/config.json +1 -1
- package/src/core/rename-watcher/watcher.js +330 -37
- package/src/core/rename-watcher/watcher.test.js +253 -0
- package/src/core/scaffold/fragments.js +287 -0
- package/src/core/scaffold/fragments.test.js +401 -0
- package/src/core/scaffold/index.js +291 -0
- package/src/core/scaffold/migrateLegacyGitignore.js +157 -0
- package/src/core/scaffold/scaffold-integration.test.js +247 -0
- package/src/core/scaffold.js +4 -97
- package/src/core/stores/canvasInteractionStore.js +120 -0
- package/src/core/stores/canvasInteractionStore.test.js +126 -0
- package/src/core/stores/configSchema.js +64 -8
- package/src/core/stores/configSchema.test.js +3 -0
- package/src/core/stores/customerModeConfig.js +24 -3
- package/src/core/stores/customerModeConfig.test.js +46 -0
- package/src/core/stores/presentationStore.js +118 -0
- package/src/core/stores/presentationStore.test.js +114 -0
- package/src/core/stores/recentArtifacts.js +49 -2
- package/src/core/stores/recentArtifacts.test.js +59 -6
- package/src/core/stores/themeBootstrap.js +264 -0
- package/src/core/stores/themeBootstrap.test.js +211 -0
- package/src/core/stores/themeStore.test.js +154 -0
- package/src/core/stores/themeStore.ts +235 -220
- package/src/core/stores/uiConfig.js +10 -2
- package/src/core/styles/generateThemesCss.js +63 -0
- package/src/core/styles/tailwind.css +150 -94
- package/src/core/styles/workspace-chrome.css +13 -0
- package/src/core/tools/handlers/paletteTheme.js +11 -8
- package/src/core/ui/ActionMenuButton.jsx +2 -1
- package/src/core/ui/AutosyncMenuButton.css +7 -7
- package/src/core/ui/BranchSelect.module.css +5 -5
- package/src/core/ui/CanvasCreateMenu.jsx +1 -19
- package/src/core/ui/ChromeSlot.jsx +92 -0
- package/src/core/ui/ChromeSlot.test.jsx +140 -0
- package/src/core/ui/CoreUIBar.css +5 -5
- package/src/core/ui/CoreUIBar.jsx +170 -142
- package/src/core/ui/InspectorPanel.css +5 -5
- package/src/core/ui/InspectorPanel.jsx +9 -9
- package/src/core/ui/PwaInstallBanner.css +5 -5
- package/src/core/ui/PwaInstallBanner.jsx +5 -5
- package/src/core/ui/ThemeMenuButton.jsx +45 -30
- package/src/core/ui/core-ui-colors.css +28 -66
- package/src/core/ui/sidepanel.css +12 -12
- package/src/core/vite/server-plugin.js +13 -0
- package/src/core/workleaf/cleanup.js +102 -0
- package/src/core/workleaf/create.js +199 -0
- package/src/core/workleaf/delete.js +101 -0
- package/src/core/workleaf/list.js +57 -0
- package/src/core/workleaf/merge.js +238 -0
- package/src/core/workleaf/paths.js +146 -0
- package/src/core/workleaf/paths.test.js +230 -0
- package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +130 -34
- package/src/core/workshop/features/createFlow/server.js +5 -1
- package/src/core/workshop/features/createPrototype/server.js +5 -1
- package/src/core/workshop/features/templateIndex.js +28 -1
- package/src/core/worktree/port.js +48 -5
- package/src/core/worktree/port.test.js +42 -0
- package/src/internals/ArtifactForm/ArtifactForm.jsx +173 -112
- package/src/internals/ArtifactForm/ArtifactForm.module.css +51 -69
- package/src/internals/ArtifactForm/artifactSchemas.js +40 -5
- package/src/internals/AuthModal/AuthModal.module.css +34 -34
- package/src/internals/BaseUiForm/BaseUiForm.jsx +293 -0
- package/src/internals/BaseUiForm/BaseUiForm.module.css +542 -0
- package/src/internals/BranchBar/BranchBar.module.css +4 -4
- package/src/internals/BranchesDropdown/BranchesDropdown.jsx +69 -0
- package/src/internals/BranchesDropdown/BranchesDropdown.module.css +84 -0
- package/src/internals/CommandPalette/CommandPalette.jsx +41 -29
- package/src/internals/CommandPalette/CreateArtifactForm.jsx +150 -0
- package/src/internals/CommandPalette/CreateDialog.jsx +20 -110
- package/src/internals/CommandPalette/WidgetArtifactDialog.css +16 -16
- package/src/internals/CommandPalette/WidgetArtifactDialog.jsx +1 -1
- package/src/internals/CommandPalette/command-palette.css +14 -14
- package/src/internals/CommandPalette/createHelpers.js +30 -0
- package/src/internals/CreatePage/CreatePage.jsx +57 -0
- package/src/internals/CreatePage/CreatePage.module.css +34 -0
- package/src/internals/Dialog.jsx +51 -0
- package/src/internals/FlowError.module.css +5 -5
- package/src/internals/PrototypeErrorBoundary.module.css +15 -15
- package/src/internals/SimpleWorkspace/SimpleWorkspace.jsx +534 -0
- package/src/internals/SimpleWorkspace/SimpleWorkspace.module.css +323 -0
- package/src/internals/Tooltip.jsx +39 -0
- package/src/internals/Viewfinder.jsx +229 -64
- package/src/internals/Viewfinder.module.css +253 -182
- package/src/internals/canvas/CanvasControls.module.css +11 -11
- package/src/internals/canvas/CanvasPage.bridge.test.jsx +11 -37
- package/src/internals/canvas/CanvasPage.jsx +358 -217
- package/src/internals/canvas/CanvasPage.module.css +20 -19
- package/src/internals/canvas/CanvasPage.multiselect.test.jsx +39 -26
- package/src/internals/canvas/CanvasToolbar.module.css +11 -11
- package/src/internals/canvas/ConnectorLayer.jsx +39 -2
- package/src/internals/canvas/ConnectorLayer.module.css +10 -10
- package/src/internals/canvas/PageSelector.jsx +15 -1
- package/src/internals/canvas/PageSelector.module.css +41 -27
- package/src/internals/canvas/canvasApi.js +40 -5
- package/src/internals/canvas/canvasTheme.js +22 -111
- package/src/internals/canvas/isolation/createIsolationMiddleware.js +68 -0
- package/src/internals/canvas/isolation/mountIsolationApp.jsx +88 -0
- package/src/internals/canvas/isolation/prototypeRoutes.jsx +140 -0
- package/src/internals/canvas/isolation/prototypesEntry.jsx +28 -0
- package/src/internals/canvas/isolation/storiesEntry.jsx +20 -0
- package/src/internals/canvas/isolation/storyRoutes.jsx +55 -0
- package/src/internals/canvas/useUndoRedo.js +75 -60
- package/src/internals/canvas/useUndoRedo.test.js +46 -178
- package/src/internals/canvas/widgets/CodePenEmbed.jsx +16 -36
- package/src/internals/canvas/widgets/CodePenEmbed.module.css +12 -12
- package/src/internals/canvas/widgets/CropOverlay.module.css +23 -23
- package/src/internals/canvas/widgets/ExpandedPane.module.css +8 -8
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +1 -1
- package/src/internals/canvas/widgets/FigmaEmbed.jsx +15 -36
- package/src/internals/canvas/widgets/FigmaEmbed.module.css +15 -15
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +30 -21
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +5 -5
- package/src/internals/canvas/widgets/ImageWidget.jsx +7 -2
- package/src/internals/canvas/widgets/ImageWidget.module.css +3 -3
- package/src/internals/canvas/widgets/LinkPreview.module.css +79 -80
- package/src/internals/canvas/widgets/MarkdownBlock.module.css +31 -31
- package/src/internals/canvas/widgets/PromptWidget.jsx +2 -16
- package/src/internals/canvas/widgets/PromptWidget.module.css +33 -33
- package/src/internals/canvas/widgets/PrototypeEmbed.jsx +92 -17
- package/src/internals/canvas/widgets/PrototypeEmbed.module.css +58 -56
- package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +118 -4
- package/src/internals/canvas/widgets/ResizeHandle.module.css +4 -4
- package/src/internals/canvas/widgets/StorySetWidget.jsx +53 -25
- package/src/internals/canvas/widgets/StoryWidget.jsx +71 -56
- package/src/internals/canvas/widgets/StoryWidget.module.css +22 -20
- package/src/internals/canvas/widgets/TerminalReadWidget.jsx +13 -15
- package/src/internals/canvas/widgets/TerminalReadWidget.module.css +4 -4
- package/src/internals/canvas/widgets/TerminalWidget.jsx +56 -45
- package/src/internals/canvas/widgets/TerminalWidget.module.css +10 -10
- package/src/internals/canvas/widgets/TilesWidget.module.css +17 -17
- package/src/internals/canvas/widgets/WidgetChrome.jsx +1 -1
- package/src/internals/canvas/widgets/WidgetChrome.module.css +76 -61
- package/src/internals/canvas/widgets/WidgetWrapper.module.css +2 -2
- package/src/internals/canvas/widgets/embedOverlay.module.css +14 -4
- package/src/internals/canvas/widgets/embedTheme.js +12 -104
- package/src/internals/canvas/widgets/expandUtils.js +19 -19
- package/src/internals/canvas/widgets/normalizeLegacyEmbedSrc.js +74 -0
- package/src/internals/canvas/widgets/widgetConfig.js +5 -5
- package/src/internals/context.jsx +22 -1
- package/src/internals/context.test.jsx +47 -0
- package/src/internals/hooks/useArtifactIndex.js +31 -0
- package/src/internals/hooks/useArtifactIndex.test.js +45 -0
- package/src/internals/hooks/usePrototypeReloadGuard.js +14 -8
- package/src/internals/index.js +6 -0
- package/src/internals/loadConsumerWrapper.js +60 -0
- package/src/internals/story/ComponentSetPage.jsx +75 -34
- package/src/internals/story/ComponentSetPage.module.css +14 -14
- package/src/internals/story/StoryPage.jsx +16 -25
- package/src/internals/story/StoryPage.module.css +2 -2
- package/src/internals/vite/data-plugin.js +317 -149
- package/src/internals/vite/data-plugin.test.js +11 -11
- package/{scaffold/storyboard.config.json → storyboard.config.json} +25 -0
- package/terminal.config.json +1 -1
- package/src/core/lib/components/ui/card/card-action.jsx +0 -11
- package/src/core/lib/components/ui/card/card-content.jsx +0 -11
- package/src/core/lib/components/ui/card/card-description.jsx +0 -11
- package/src/core/lib/components/ui/card/card-footer.jsx +0 -11
- package/src/core/lib/components/ui/card/card-header.jsx +0 -19
- package/src/core/lib/components/ui/card/card-title.jsx +0 -11
- package/src/core/lib/components/ui/card/card.jsx +0 -17
- package/src/core/lib/components/ui/card/index.js +0 -25
- package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/index.js +0 -13
- package/src/core/lib/components/ui/dialog/dialog-close.jsx +0 -7
- package/src/core/lib/components/ui/dialog/dialog-description.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-footer.jsx +0 -23
- package/src/core/lib/components/ui/dialog/dialog-header.jsx +0 -11
- package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-portal.jsx +0 -4
- package/src/core/lib/components/ui/dialog/dialog-title.jsx +0 -15
- package/src/core/lib/components/ui/popover/index.js +0 -28
- package/src/core/lib/components/ui/popover/popover-close.jsx +0 -7
- package/src/core/lib/components/ui/popover/popover-content.jsx +0 -22
- package/src/core/lib/components/ui/popover/popover-description.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-header.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-portal.jsx +0 -4
- package/src/core/lib/components/ui/popover/popover-title.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-trigger.jsx +0 -8
- package/src/core/lib/components/ui/popover/popover.jsx +0 -4
- package/src/core/lib/components/ui/select/index.js +0 -37
- package/src/core/lib/components/ui/select/select-content.jsx +0 -30
- package/src/core/lib/components/ui/select/select-group-heading.jsx +0 -17
- package/src/core/lib/components/ui/select/select-group.jsx +0 -15
- package/src/core/lib/components/ui/select/select-item.jsx +0 -26
- package/src/core/lib/components/ui/select/select-label.jsx +0 -11
- package/src/core/lib/components/ui/select/select-portal.jsx +0 -4
- package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-separator.jsx +0 -15
- package/src/core/lib/components/ui/select/select-trigger.jsx +0 -25
- package/src/core/lib/components/ui/select/select.jsx +0 -4
- package/src/core/lib/components/ui/sheet/index.js +0 -34
- package/src/core/lib/components/ui/sheet/sheet-close.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet-content.jsx +0 -35
- package/src/core/lib/components/ui/sheet/sheet-description.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-footer.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-header.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-portal.jsx +0 -4
- package/src/core/lib/components/ui/sheet/sheet-title.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet.jsx +0 -4
- package/src/core/lib/components/ui/toggle/index.js +0 -8
- package/src/core/lib/components/ui/toggle/toggle.jsx +0 -36
- package/src/core/lib/components/ui/toggle-group/index.js +0 -10
- package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +0 -29
- package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +0 -43
- package/src/internals/canvas/StoryErrorBoundary.jsx +0 -47
- package/src/internals/canvas/WebGLContextPool.jsx +0 -291
- package/src/internals/canvas/WebGLContextPool.test.jsx +0 -165
- package/src/internals/canvas/componentIsolate.jsx +0 -144
- package/src/internals/canvas/componentSetIsolate.jsx +0 -300
- package/src/internals/canvas/widgets/ComponentSetWidget.module.css +0 -89
- package/src/internals/canvas/widgets/InlineStoryRenderer.jsx +0 -129
- package/src/internals/canvas/widgets/InlineStoryRenderer.test.jsx +0 -68
- package/src/internals/canvas/widgets/StorySetWidget.module.css +0 -89
- package/src/primer/ThemeSync.jsx +0 -73
- package/src/primer/index.js +0 -1
package/scaffold/AGENTS.md
CHANGED
|
@@ -100,7 +100,7 @@ The default location is in `.agents/plans`, but the user may ask for a specific
|
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
102
|
npm run setup # First-time: install deps, Caddy proxy, start proxy
|
|
103
|
-
|
|
103
|
+
npm run dev # Start dev server (wraps `storyboard dev`)
|
|
104
104
|
npm run dev:vite # Start vite directly (bypasses CLI)
|
|
105
105
|
npm run build # Production build
|
|
106
106
|
npm run lint # Run ESLint
|
|
@@ -108,14 +108,15 @@ npm run lint # Run ESLint
|
|
|
108
108
|
|
|
109
109
|
### Storyboard CLI
|
|
110
110
|
|
|
111
|
-
The `storyboard` CLI (`sb` alias) wraps dev tooling
|
|
111
|
+
The `storyboard` CLI (`sb` alias) wraps dev tooling. The standard `npm run dev` script in this repo just calls `storyboard dev` — use `npm run dev` unless you need a CLI-only feature (e.g. starting a dev server for a different worktree).
|
|
112
112
|
|
|
113
|
+
<!-- cli-table --start-->
|
|
113
114
|
| Command | Description |
|
|
114
115
|
|---------|-------------|
|
|
115
|
-
| `
|
|
116
|
+
| `npm run dev` _(preferred)_ | Start the Vite dev server for the current worktree |
|
|
117
|
+
| `storyboard dev [branch]` | Start a dev server — pass a branch to target a different worktree |
|
|
116
118
|
| `storyboard code [branch]` | Open current worktree (or specific branch) in VS Code |
|
|
117
119
|
| `storyboard setup` | Install deps, Caddy, `gh` check, start proxy |
|
|
118
|
-
| `storyboard proxy` | Generate Caddyfile + start/reload Caddy |
|
|
119
120
|
| `storyboard update:version [version]` | Update `@dfosco/storyboard-*` packages to latest (or specific version) |
|
|
120
121
|
| `storyboard canvas read [name]` | Read canvas widgets with content, URLs, file paths, and bounds |
|
|
121
122
|
| `storyboard canvas bounds [name]` | Get widget size and positional bounds (spatial queries) |
|
|
@@ -152,6 +153,7 @@ The `storyboard` CLI (`sb` alias) wraps dev tooling:
|
|
|
152
153
|
| `storyboard messages send` | Publish and wait for correlated response |
|
|
153
154
|
| `storyboard messages read` | Read events from a channel |
|
|
154
155
|
| `storyboard messages batch` | Batch publish + read operations |
|
|
156
|
+
<!-- cli-table --end-->
|
|
155
157
|
|
|
156
158
|
> **Convention: Every server API endpoint must have a corresponding CLI command with 1:1 flag-to-field mapping.** Agents use CLI commands, not curl. When adding a new API endpoint, always create a matching CLI command.
|
|
157
159
|
|
|
@@ -159,7 +161,7 @@ For the full canvas CLI reference (positioning, batch ops, collision detection),
|
|
|
159
161
|
|
|
160
162
|
### Dev URLs
|
|
161
163
|
|
|
162
|
-
With Caddy proxy running (`
|
|
164
|
+
With Caddy proxy running (set up via `npm run setup`):
|
|
163
165
|
- Main: `http://storyboard.localhost/storyboard/`
|
|
164
166
|
- Worktree `fix-bug`: `http://storyboard.localhost/fix-bug/storyboard/`
|
|
165
167
|
|
|
@@ -169,7 +171,7 @@ Without proxy (fallback with port numbers):
|
|
|
169
171
|
|
|
170
172
|
### Dev URL session state
|
|
171
173
|
|
|
172
|
-
Whenever Copilot starts a dev server (e.g. `
|
|
174
|
+
Whenever Copilot starts a dev server (e.g. `npm run dev`), save the URL as `devURL` in the SQL session database. Read the proxy URL from the dev server's startup output (`[storyboard] proxy URL: <url>`):
|
|
173
175
|
|
|
174
176
|
```sql
|
|
175
177
|
INSERT OR REPLACE INTO session_state (key, value) VALUES ('devURL', 'http://storyboard.localhost/storyboard/');
|
|
@@ -180,7 +182,7 @@ If the proxy is not running, fall back to the direct URL from the output (`[stor
|
|
|
180
182
|
This `devURL` is used as the default target by the **agent-browser** skill when the user says "inspect the browser", "check the page", etc. — no URL argument needed.
|
|
181
183
|
|
|
182
184
|
**How `devURL` gets set:**
|
|
183
|
-
- **Automatically** — when Copilot runs `
|
|
185
|
+
- **Automatically** — when Copilot runs `npm run dev` (or directly `storyboard dev`), persist the proxy URL (or direct URL if no proxy) to `devURL`.
|
|
184
186
|
- **From user input** — if the user says "the dev server is at http://localhost:3000", save that as `devURL`.
|
|
185
187
|
- **Implicitly from inspection** — if no `devURL` is set and the user says "inspect http://storyboard.localhost/storyboard/", that URL becomes the `devURL` for the rest of the session.
|
|
186
188
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Storyboard
|
|
2
|
+
|
|
3
|
+
> Note: this is a scaffold-source README. The file copied to client repos
|
|
4
|
+
> only contains the fragment bodies — the bare `<!-- … --start-->` markers
|
|
5
|
+
> below are stripped on whole-file copy. Clients can also adopt individual
|
|
6
|
+
> fragments by adding `<!-- storyboard:scaffold/README.md:<id> --start-->`
|
|
7
|
+
> markers around their own content.
|
|
8
|
+
|
|
9
|
+
## Storyboard Launcher (Desktop App)
|
|
10
|
+
|
|
11
|
+
<!-- launcher-download --start-->
|
|
12
|
+
Download the macOS Launcher from the [latest launcher release](https://github.com/dfosco/storyboard/releases?q=storyboard-launcher&expanded=true).
|
|
13
|
+
|
|
14
|
+
After installing, run:
|
|
15
|
+
```bash
|
|
16
|
+
sudo xattr -rd com.apple.quarantine '/Applications/Storyboard Launcher.app'
|
|
17
|
+
```
|
|
18
|
+
<!-- launcher-download --end-->
|
package/scaffold/deploy.yml
CHANGED
|
@@ -101,3 +101,24 @@ jobs:
|
|
|
101
101
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
102
102
|
git commit -m "Update branch manifest"
|
|
103
103
|
git push origin gh-pages
|
|
104
|
+
|
|
105
|
+
- name: Generate artifacts index
|
|
106
|
+
run: |
|
|
107
|
+
set -e
|
|
108
|
+
# Remove stale worktrees from previous steps
|
|
109
|
+
git worktree list --porcelain | awk '/^worktree \/tmp/{print $2}' | while read wt; do
|
|
110
|
+
git worktree remove --force "$wt" 2>/dev/null || true
|
|
111
|
+
done
|
|
112
|
+
git fetch origin gh-pages:gh-pages 2>/dev/null || true
|
|
113
|
+
DEPLOY_DIR=$(mktemp -d)
|
|
114
|
+
git worktree add "$DEPLOY_DIR" gh-pages
|
|
115
|
+
|
|
116
|
+
node "$GITHUB_WORKSPACE/.github/workflows/scripts/aggregate-artifacts.mjs" "$DEPLOY_DIR"
|
|
117
|
+
|
|
118
|
+
cd "$DEPLOY_DIR"
|
|
119
|
+
git add artifacts.index.json
|
|
120
|
+
git diff --cached --quiet && echo "Artifacts index unchanged" && exit 0
|
|
121
|
+
git config user.name "github-actions[bot]"
|
|
122
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
123
|
+
git commit -m "Update artifacts index"
|
|
124
|
+
git push origin gh-pages
|
package/scaffold/gitignore
CHANGED
|
@@ -52,25 +52,19 @@ packages/core/dist/storyboard-ui.*
|
|
|
52
52
|
# Agent Browser
|
|
53
53
|
agent-browser.json
|
|
54
54
|
|
|
55
|
-
#
|
|
56
|
-
.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.storyboard/.selectedwidgets.json
|
|
60
|
-
|
|
61
|
-
# Runtime/transient state (per-machine, per-session)
|
|
62
|
-
.storyboard/agent-sessions/
|
|
63
|
-
.storyboard/hot-pool/
|
|
64
|
-
.storyboard/logs/
|
|
65
|
-
.storyboard/terminal-buffers/
|
|
66
|
-
.storyboard/messages/
|
|
67
|
-
|
|
68
|
-
# Private canvas images (tilde prefix = not committed)
|
|
55
|
+
# <!-- runtime-state --start-->
|
|
56
|
+
# Storyboard runtime state + private tilde-prefixed files.
|
|
57
|
+
# Kept in sync by storyboard-scaffold — edit `packages/storyboard/scaffold/gitignore` in storyboard-core.
|
|
58
|
+
.storyboard/
|
|
69
59
|
src/canvas/images/~*
|
|
70
60
|
assets/canvas/images/~*
|
|
61
|
+
assets/canvas/images/drafts/
|
|
71
62
|
assets/canvas/snapshots/~*
|
|
72
63
|
assets/.storyboard-public/terminal-snapshots/~*
|
|
64
|
+
src/canvas/**/drafts/
|
|
65
|
+
src/prototypes/**/drafts/
|
|
73
66
|
.sync-target
|
|
67
|
+
# <!-- runtime-state --end-->
|
|
74
68
|
|
|
75
69
|
# Integration test results (ephemeral local artifacts)
|
|
76
70
|
test-results/
|
package/scaffold/preview.yml
CHANGED
|
@@ -115,6 +115,27 @@ jobs:
|
|
|
115
115
|
git commit -m "Update branch manifest"
|
|
116
116
|
git push origin gh-pages
|
|
117
117
|
|
|
118
|
+
- name: Generate artifacts index
|
|
119
|
+
run: |
|
|
120
|
+
set -e
|
|
121
|
+
# Remove stale worktrees from previous steps
|
|
122
|
+
git worktree list --porcelain | awk '/^worktree \/tmp/{print $2}' | while read wt; do
|
|
123
|
+
git worktree remove --force "$wt" 2>/dev/null || true
|
|
124
|
+
done
|
|
125
|
+
git fetch origin gh-pages:gh-pages 2>/dev/null || true
|
|
126
|
+
DEPLOY_DIR=$(mktemp -d)
|
|
127
|
+
git worktree add "$DEPLOY_DIR" gh-pages
|
|
128
|
+
|
|
129
|
+
node "$GITHUB_WORKSPACE/.github/workflows/scripts/aggregate-artifacts.mjs" "$DEPLOY_DIR"
|
|
130
|
+
|
|
131
|
+
cd "$DEPLOY_DIR"
|
|
132
|
+
git add artifacts.index.json
|
|
133
|
+
git diff --cached --quiet && echo "Artifacts index unchanged" && exit 0
|
|
134
|
+
git config user.name "github-actions[bot]"
|
|
135
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
136
|
+
git commit -m "Update artifacts index"
|
|
137
|
+
git push origin gh-pages
|
|
138
|
+
|
|
118
139
|
- name: Print preview URL
|
|
119
140
|
run: |
|
|
120
141
|
echo "## 🔗 Branch Preview" >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -179,3 +200,22 @@ jobs:
|
|
|
179
200
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
180
201
|
git commit -m "Update branch manifest"
|
|
181
202
|
git push origin gh-pages
|
|
203
|
+
|
|
204
|
+
# cleanup-preview does not install npm dependencies. Check out the source
|
|
205
|
+
# tree separately so the checked-in workflow helper can run with plain Node.
|
|
206
|
+
- name: Checkout source workflow scripts
|
|
207
|
+
uses: actions/checkout@v6
|
|
208
|
+
with:
|
|
209
|
+
path: source
|
|
210
|
+
|
|
211
|
+
- name: Generate artifacts index
|
|
212
|
+
run: |
|
|
213
|
+
set -e
|
|
214
|
+
node source/.github/workflows/scripts/aggregate-artifacts.mjs "$GITHUB_WORKSPACE"
|
|
215
|
+
|
|
216
|
+
git add artifacts.index.json
|
|
217
|
+
git diff --cached --quiet && echo "Artifacts index unchanged" && exit 0
|
|
218
|
+
git config user.name "github-actions[bot]"
|
|
219
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
220
|
+
git commit -m "Update artifacts index"
|
|
221
|
+
git push origin gh-pages
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
{
|
|
4
4
|
"source": "scaffold/AGENTS.md",
|
|
5
5
|
"target": "AGENTS.md",
|
|
6
|
-
"mode": "
|
|
6
|
+
"mode": "scaffold"
|
|
7
7
|
},
|
|
8
8
|
{
|
|
9
9
|
"source": "scaffold/gitignore",
|
|
10
10
|
"target": ".gitignore",
|
|
11
|
-
"mode": "
|
|
11
|
+
"mode": "scaffold"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
"source": "
|
|
14
|
+
"source": "storyboard.config.json",
|
|
15
15
|
"target": "storyboard.config.json",
|
|
16
16
|
"mode": "scaffold"
|
|
17
17
|
},
|
|
@@ -67,6 +67,11 @@
|
|
|
67
67
|
"target": ".github/workflows/preview.yml",
|
|
68
68
|
"mode": "updateable"
|
|
69
69
|
},
|
|
70
|
+
{
|
|
71
|
+
"source": "scaffold/scripts/aggregate-artifacts.mjs",
|
|
72
|
+
"target": ".github/workflows/scripts/aggregate-artifacts.mjs",
|
|
73
|
+
"mode": "updateable"
|
|
74
|
+
},
|
|
70
75
|
{
|
|
71
76
|
"source": "scaffold/githooks/",
|
|
72
77
|
"target": ".githooks/",
|
|
@@ -88,6 +93,71 @@
|
|
|
88
93
|
"source": "scaffold/codex/config.toml",
|
|
89
94
|
"target": ".codex/config.toml",
|
|
90
95
|
"mode": "updateable"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"source": "scaffold/src/library/mount.jsx",
|
|
99
|
+
"target": "src/library/mount.jsx",
|
|
100
|
+
"mode": "updateable"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"source": "scaffold/src/library/prototypes-entry.jsx",
|
|
104
|
+
"target": "src/library/prototypes-entry.jsx",
|
|
105
|
+
"mode": "updateable"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"source": "scaffold/src/library/routes.jsx",
|
|
109
|
+
"target": "src/library/routes.jsx",
|
|
110
|
+
"mode": "updateable"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"source": "scaffold/src/library/_app.jsx",
|
|
114
|
+
"target": "src/library/_app.jsx",
|
|
115
|
+
"mode": "updateable"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"source": "scaffold/src/library/_app.module.css",
|
|
119
|
+
"target": "src/library/_app.module.css",
|
|
120
|
+
"mode": "updateable"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"source": "scaffold/src/library/workspace.jsx",
|
|
124
|
+
"target": "src/library/workspace.jsx",
|
|
125
|
+
"mode": "updateable"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"source": "scaffold/src/library/viewfinder.jsx",
|
|
129
|
+
"target": "src/library/viewfinder.jsx",
|
|
130
|
+
"mode": "updateable"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"source": "scaffold/src/library/create.jsx",
|
|
134
|
+
"target": "src/library/create.jsx",
|
|
135
|
+
"mode": "updateable"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"source": "scaffold/src/library/index.jsx",
|
|
139
|
+
"target": "src/library/index.jsx",
|
|
140
|
+
"mode": "updateable"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"source": "scaffold/src/library/README.md",
|
|
144
|
+
"target": "src/library/README.md",
|
|
145
|
+
"mode": "updateable"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"source": "scaffold/src/_prototype.jsx",
|
|
149
|
+
"target": "src/_prototype.jsx",
|
|
150
|
+
"mode": "scaffold"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"source": "scaffold/src/_story.jsx",
|
|
154
|
+
"target": "src/_story.jsx",
|
|
155
|
+
"mode": "scaffold"
|
|
91
156
|
}
|
|
157
|
+
],
|
|
158
|
+
"fragmentSources": [
|
|
159
|
+
"scaffold/gitignore",
|
|
160
|
+
"scaffold/AGENTS.md",
|
|
161
|
+
"scaffold/README.md"
|
|
92
162
|
]
|
|
93
163
|
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import process from 'process'
|
|
6
|
+
|
|
7
|
+
const INDEX_FILENAME = 'artifacts.index.json'
|
|
8
|
+
const TMP_FILENAME = '.artifacts.index.json.tmp'
|
|
9
|
+
const SCHEMA_VERSION = 1
|
|
10
|
+
|
|
11
|
+
function compareBranchNames(a, b) {
|
|
12
|
+
if (a.branch === 'main' && b.branch !== 'main') return -1
|
|
13
|
+
if (b.branch === 'main' && a.branch !== 'main') return 1
|
|
14
|
+
return String(a.branch || '').localeCompare(String(b.branch || ''))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function withTrailingSlash(folder) {
|
|
18
|
+
if (!folder) return ''
|
|
19
|
+
return folder.endsWith('/') ? folder : `${folder}/`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function generatedAtMs(manifest) {
|
|
23
|
+
const value = Date.parse(manifest?.generatedAt || '')
|
|
24
|
+
return Number.isNaN(value) ? 0 : value
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function deriveFolder(manifest, dir, ghPagesDir) {
|
|
28
|
+
if (dir === ghPagesDir) return ''
|
|
29
|
+
if (typeof manifest.folder === 'string') return manifest.folder
|
|
30
|
+
return path.basename(dir)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function deriveBranch(manifest, folder) {
|
|
34
|
+
if (!folder) return 'main'
|
|
35
|
+
if (typeof manifest.branch === 'string' && manifest.branch) return manifest.branch
|
|
36
|
+
return manifest.deployBranch || folder.replace(/^branch--/, '')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function deriveDeployBranch(manifest, branch, folder) {
|
|
40
|
+
if (!folder || branch === 'main') return 'main'
|
|
41
|
+
if (typeof manifest.deployBranch === 'string' && manifest.deployBranch) return manifest.deployBranch
|
|
42
|
+
return folder.replace(/^branch--/, '')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function readManifest(dir) {
|
|
46
|
+
const manifestPath = path.join(dir, 'artifacts.json')
|
|
47
|
+
const label = path.basename(dir) || dir
|
|
48
|
+
|
|
49
|
+
let raw
|
|
50
|
+
try {
|
|
51
|
+
raw = fs.readFileSync(manifestPath, 'utf8')
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (err?.code === 'ENOENT') {
|
|
54
|
+
console.info(`[aggregate-artifacts] Skipping ${label}: artifacts.json not found`)
|
|
55
|
+
return { manifest: null, readError: false }
|
|
56
|
+
}
|
|
57
|
+
console.warn(`[aggregate-artifacts] Skipping ${label}: could not read artifacts.json (${err.message})`)
|
|
58
|
+
return { manifest: null, readError: true }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let manifest
|
|
62
|
+
try {
|
|
63
|
+
manifest = JSON.parse(raw)
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.warn(`[aggregate-artifacts] Skipping ${label}: malformed artifacts.json (${err.message})`)
|
|
66
|
+
return { manifest: null, readError: false }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (manifest?.schemaVersion !== SCHEMA_VERSION) {
|
|
70
|
+
console.warn(`[aggregate-artifacts] Skipping ${label}: unsupported schemaVersion ${manifest?.schemaVersion}`)
|
|
71
|
+
return { manifest: null, readError: false }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { manifest, readError: false }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function listManifestDirs(ghPagesDir) {
|
|
78
|
+
const entries = fs.readdirSync(ghPagesDir, { withFileTypes: true })
|
|
79
|
+
const branchDirs = entries
|
|
80
|
+
.filter(entry => entry.isDirectory() && entry.name.startsWith('branch--'))
|
|
81
|
+
.map(entry => path.join(ghPagesDir, entry.name))
|
|
82
|
+
.sort((a, b) => path.basename(a).localeCompare(path.basename(b)))
|
|
83
|
+
|
|
84
|
+
return [ghPagesDir, ...branchDirs]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function collectManifests(ghPagesDir) {
|
|
88
|
+
const manifestsByFolder = new Map()
|
|
89
|
+
let readErrorCount = 0
|
|
90
|
+
|
|
91
|
+
for (const dir of listManifestDirs(ghPagesDir)) {
|
|
92
|
+
const { manifest, readError } = readManifest(dir)
|
|
93
|
+
if (readError) readErrorCount += 1
|
|
94
|
+
if (!manifest) continue
|
|
95
|
+
|
|
96
|
+
const folder = deriveFolder(manifest, dir, ghPagesDir)
|
|
97
|
+
const current = { manifest, dir, folder }
|
|
98
|
+
const previous = manifestsByFolder.get(folder)
|
|
99
|
+
|
|
100
|
+
if (!previous) {
|
|
101
|
+
manifestsByFolder.set(folder, current)
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const previousBranch = deriveBranch(previous.manifest, previous.folder)
|
|
106
|
+
const currentBranch = deriveBranch(manifest, folder)
|
|
107
|
+
const keepCurrent = generatedAtMs(manifest) > generatedAtMs(previous.manifest)
|
|
108
|
+
const keptBranch = keepCurrent ? currentBranch : previousBranch
|
|
109
|
+
|
|
110
|
+
console.warn(
|
|
111
|
+
`[aggregate-artifacts] Branch folder collision for "${folder || '(root)'}" between "${previousBranch}" and "${currentBranch}"; keeping "${keptBranch}"`,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if (keepCurrent) manifestsByFolder.set(folder, current)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (readErrorCount > 1) {
|
|
118
|
+
throw new Error(`Failed to read ${readErrorCount} artifacts manifests; preserving existing ${INDEX_FILENAME}`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const manifests = [...manifestsByFolder.values()]
|
|
122
|
+
if (manifests.length === 0) {
|
|
123
|
+
throw new Error(`No readable artifacts.json manifests found; preserving existing ${INDEX_FILENAME}`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return manifests
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function addPrototype(index, manifestInfo, item) {
|
|
130
|
+
const id = item?.artifactId || item?.id
|
|
131
|
+
if (!id) return
|
|
132
|
+
|
|
133
|
+
const { manifest, folder } = manifestInfo
|
|
134
|
+
const branch = deriveBranch(manifest, folder)
|
|
135
|
+
const key = String(id)
|
|
136
|
+
|
|
137
|
+
if (!index.prototypes[key]) {
|
|
138
|
+
index.prototypes[key] = { id: key, branches: [] }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
index.prototypes[key].branches.push({
|
|
142
|
+
branch,
|
|
143
|
+
folder: withTrailingSlash(folder),
|
|
144
|
+
title: item.title ?? item.id ?? key,
|
|
145
|
+
route: item.route ?? null,
|
|
146
|
+
isExternal: Boolean(item.isExternal),
|
|
147
|
+
externalUrl: item.externalUrl ?? null,
|
|
148
|
+
folderName: item.folder ?? null,
|
|
149
|
+
sha: manifest.sha ?? null,
|
|
150
|
+
lastModified: item.lastModified ?? null,
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function addCanvas(index, manifestInfo, item) {
|
|
155
|
+
const id = item?.artifactId || item?.id
|
|
156
|
+
if (!id) return
|
|
157
|
+
|
|
158
|
+
const { manifest, folder } = manifestInfo
|
|
159
|
+
const branch = deriveBranch(manifest, folder)
|
|
160
|
+
const key = String(id)
|
|
161
|
+
|
|
162
|
+
if (!index.canvases[key]) {
|
|
163
|
+
index.canvases[key] = { id: key, branches: [] }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
index.canvases[key].branches.push({
|
|
167
|
+
branch,
|
|
168
|
+
folder: withTrailingSlash(folder),
|
|
169
|
+
name: item.name ?? item.id ?? key,
|
|
170
|
+
route: item.route ?? null,
|
|
171
|
+
folderName: item.folder ?? null,
|
|
172
|
+
sha: manifest.sha ?? null,
|
|
173
|
+
lastModified: item.lastModified ?? null,
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function sortArtifactMap(map) {
|
|
178
|
+
const sorted = {}
|
|
179
|
+
|
|
180
|
+
for (const key of Object.keys(map).sort((a, b) => a.localeCompare(b))) {
|
|
181
|
+
sorted[key] = {
|
|
182
|
+
...map[key],
|
|
183
|
+
branches: [...map[key].branches].sort(compareBranchNames),
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return sorted
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function buildIndex(manifests) {
|
|
191
|
+
const index = {
|
|
192
|
+
schemaVersion: SCHEMA_VERSION,
|
|
193
|
+
generatedAt: new Date().toISOString(),
|
|
194
|
+
branches: [],
|
|
195
|
+
prototypes: {},
|
|
196
|
+
canvases: {},
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
for (const manifestInfo of manifests) {
|
|
200
|
+
const { manifest, folder } = manifestInfo
|
|
201
|
+
const branch = deriveBranch(manifest, folder)
|
|
202
|
+
const deployBranch = deriveDeployBranch(manifest, branch, folder)
|
|
203
|
+
|
|
204
|
+
index.branches.push({ branch, deployBranch, folder })
|
|
205
|
+
|
|
206
|
+
for (const item of Array.isArray(manifest.prototypes) ? manifest.prototypes : []) {
|
|
207
|
+
addPrototype(index, manifestInfo, item)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
for (const item of Array.isArray(manifest.canvases) ? manifest.canvases : []) {
|
|
211
|
+
addCanvas(index, manifestInfo, item)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
index.branches = [...index.branches].sort(compareBranchNames)
|
|
216
|
+
index.prototypes = sortArtifactMap(index.prototypes)
|
|
217
|
+
index.canvases = sortArtifactMap(index.canvases)
|
|
218
|
+
|
|
219
|
+
return index
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function writeIndex(ghPagesDir, index) {
|
|
223
|
+
const targetPath = path.join(ghPagesDir, INDEX_FILENAME)
|
|
224
|
+
const tmpPath = path.join(ghPagesDir, TMP_FILENAME)
|
|
225
|
+
const contents = `${JSON.stringify(index, null, 2)}\n`
|
|
226
|
+
|
|
227
|
+
fs.writeFileSync(tmpPath, contents, 'utf8')
|
|
228
|
+
fs.renameSync(tmpPath, targetPath)
|
|
229
|
+
|
|
230
|
+
return targetPath
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function aggregateArtifacts(ghPagesDir) {
|
|
234
|
+
const resolvedDir = path.resolve(ghPagesDir)
|
|
235
|
+
const manifests = collectManifests(resolvedDir)
|
|
236
|
+
const index = buildIndex(manifests)
|
|
237
|
+
return writeIndex(resolvedDir, index)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function main() {
|
|
241
|
+
const ghPagesDir = process.argv[2]
|
|
242
|
+
|
|
243
|
+
if (!ghPagesDir) {
|
|
244
|
+
console.error('Usage: node aggregate-artifacts.mjs <gh-pages-dir>')
|
|
245
|
+
process.exit(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const targetPath = aggregateArtifacts(ghPagesDir)
|
|
250
|
+
console.info(`[aggregate-artifacts] Wrote ${targetPath}`)
|
|
251
|
+
} catch (err) {
|
|
252
|
+
console.error(`[aggregate-artifacts] ${err.message}`)
|
|
253
|
+
process.exit(1)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
main()
|
|
@@ -23,7 +23,7 @@ Reads, manipulates, and arranges widgets on a Storyboard canvas. Supports absolu
|
|
|
23
23
|
|
|
24
24
|
## Prerequisites
|
|
25
25
|
|
|
26
|
-
- The dev server **must** be running (`
|
|
26
|
+
- The dev server **must** be running (`npm run dev`, or `storyboard dev` from the CLI directly)
|
|
27
27
|
- The target canvas must already exist
|
|
28
28
|
|
|
29
29
|
## Critical: Never Parse JSONL Directly
|
|
@@ -200,7 +200,7 @@ If clips was skipped in Step 3, skip this step too.
|
|
|
200
200
|
Run the dev server in the worktree so the user can immediately preview changes:
|
|
201
201
|
|
|
202
202
|
```bash
|
|
203
|
-
|
|
203
|
+
npm run dev
|
|
204
204
|
```
|
|
205
205
|
|
|
206
206
|
This is the **only** place the dev server starts during a ship workflow — the worktree skill skips its own dev server step when called from ship.
|
|
@@ -234,4 +234,4 @@ User says: "ship a feature to add canvas grid snapping"
|
|
|
234
234
|
8. Updates architecture docs, README, DOCS as needed, commits
|
|
235
235
|
9. Pushes `1.2.0--canvas-grid-snapping` to origin
|
|
236
236
|
10. Marks clips tasks as closed
|
|
237
|
-
11. Starts dev server (`
|
|
237
|
+
11. Starts dev server (`npm run dev`) in the worktree
|
|
@@ -19,7 +19,7 @@ When the user asks for a worktree named `<branch-name>`:
|
|
|
19
19
|
|
|
20
20
|
### Preferred: Use `npx storyboard dev <branch>`
|
|
21
21
|
|
|
22
|
-
The `storyboard` CLI handles the full worktree lifecycle in a single command
|
|
22
|
+
The `storyboard` CLI handles the full worktree lifecycle in a single command. (Plain `npm run dev` only starts a server for the current worktree — to target a different worktree from anywhere, use the CLI directly.)
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
npx storyboard dev <branch-name>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _prototype.jsx — wraps every prototype route in this project.
|
|
3
|
+
*
|
|
4
|
+
* Storyboard resolves this file via `import.meta.glob('/src/_prototype.{jsx,tsx}')`
|
|
5
|
+
* and wraps every prototype route's render with the default export — both in
|
|
6
|
+
* the workspace SPA and in the isolated `prototypes.html` iframe.
|
|
7
|
+
*
|
|
8
|
+
* By default, this is a pass-through (no providers, no CSS). Customize freely:
|
|
9
|
+
* - Add an `import './_prototype.css'` and import your design tokens / Tailwind / fonts
|
|
10
|
+
* - Wrap in your design system's ThemeProvider (Primer, Reshaped, Chakra, etc.)
|
|
11
|
+
*
|
|
12
|
+
* Delete this file entirely if you want prototypes to render with absolutely
|
|
13
|
+
* nothing inherited from storyboard.
|
|
14
|
+
*/
|
|
15
|
+
export default function PrototypeWrapper({ children }) {
|
|
16
|
+
return children
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _story.jsx — wraps every story render in this project.
|
|
3
|
+
*
|
|
4
|
+
* Covers: StoryPage routes, ComponentSetPage grid, InlineStoryRenderer
|
|
5
|
+
* (canvas widget), componentIsolate / componentSetIsolate (iframe entries).
|
|
6
|
+
*
|
|
7
|
+
* Pass-through default — customize like `src/_prototype.jsx` (often the two
|
|
8
|
+
* share the same providers; one common pattern is to re-export this file
|
|
9
|
+
* from `_prototype.jsx`).
|
|
10
|
+
*/
|
|
11
|
+
export default function StoryWrapper({ children }) {
|
|
12
|
+
return children
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# DO NOT EDIT FILES IN THIS DIRECTORY
|
|
2
|
+
|
|
3
|
+
`src/library/` contains storyboard's bootstrap boilerplate AND its workspace
|
|
4
|
+
pages (Workspace, Viewfinder, Create, the SPA landing index). These files
|
|
5
|
+
are managed by storyboard and may be overwritten by future
|
|
6
|
+
`storyboard update:version` runs.
|
|
7
|
+
|
|
8
|
+
The contents:
|
|
9
|
+
|
|
10
|
+
| File | What it does |
|
|
11
|
+
|---|---|
|
|
12
|
+
| `mount.jsx` | Vite SPA entry — `index.html` loads this |
|
|
13
|
+
| `prototypes-entry.jsx` | Vite iframe entry — `prototypes.html` loads this |
|
|
14
|
+
| `routes.jsx` | Generouted glue: scans `src/library/*.jsx` (workspace pages) and `src/prototypes/**` (your prototypes) |
|
|
15
|
+
| `_app.jsx`, `_app.module.css` | Workspace SPA shell — `StoryboardProvider`, suspense, error boundary, feature-flag banner |
|
|
16
|
+
| `workspace.jsx` | `/workspace` route — calls `<Workspace>` |
|
|
17
|
+
| `viewfinder.jsx` | `/viewfinder` redirect (kept for back-compat) |
|
|
18
|
+
| `create.jsx` | `/create` standalone artifact creator |
|
|
19
|
+
| `index.jsx` | `/` landing — `<SimpleWorkspace>` |
|
|
20
|
+
|
|
21
|
+
## How to customize storyboard
|
|
22
|
+
|
|
23
|
+
Almost every customization knob lives elsewhere:
|
|
24
|
+
|
|
25
|
+
| What you want to change | Edit |
|
|
26
|
+
|---|---|
|
|
27
|
+
| App title, theming, feature flags, surfaces | `storyboard.config.json` |
|
|
28
|
+
| Provider chain for every **prototype** (design system, fonts, Tailwind) | `src/_prototype.jsx` (optional — create it if you want it) |
|
|
29
|
+
| Provider chain for every **story** | `src/_story.jsx` (optional) |
|
|
30
|
+
| Add new routes the user can navigate to inside the SPA | Add files under `src/prototypes/` |
|
|
31
|
+
|
|
32
|
+
If you have a real reason to edit a file in this directory, just edit it —
|
|
33
|
+
storyboard will warn (but not block) on the next sync. You opt out of sync
|
|
34
|
+
by adding the file path to your `.storyboard-sync.ignore` file (planned).
|