@dfosco/storyboard 0.5.0-alpha.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/commandpalette.config.json +152 -0
- package/dist/storyboard-ui.css +1 -0
- package/dist/storyboard-ui.js +21328 -0
- package/dist/storyboard-ui.js.map +1 -0
- package/dist/tailwind.css +2 -0
- package/dist/tiny-canvas.css +1 -0
- package/dist/tiny-canvas.js +389 -0
- package/package.json +121 -0
- package/paste.config.json +67 -0
- package/scaffold/AGENTS.md +432 -0
- package/scaffold/agents/prompt-agent.agent.md +181 -0
- package/scaffold/agents/terminal-agent.agent.md +351 -0
- package/scaffold/codex/config.toml +246 -0
- package/scaffold/deploy.yml +103 -0
- package/scaffold/githooks/pre-push +114 -0
- package/scaffold/gitignore +64 -0
- package/scaffold/manifest.json +56 -0
- package/scaffold/preview.yml +181 -0
- package/scaffold/scripts/link.sh +26 -0
- package/scaffold/scripts/unlink.sh +10 -0
- package/scaffold/skills/agent-browser/SKILL.md +260 -0
- package/scaffold/skills/canvas/SKILL.md +364 -0
- package/scaffold/skills/create/SKILL.md +501 -0
- package/scaffold/skills/ship/SKILL.md +237 -0
- package/scaffold/skills/storyboard/SKILL.md +360 -0
- package/scaffold/skills/update-storyboard/SKILL.md +16 -0
- package/scaffold/skills/update-storyboard/update-storyboard-packages.sh +26 -0
- package/scaffold/skills/vitest/GENERATION.md +5 -0
- package/scaffold/skills/vitest/SKILL.md +52 -0
- package/scaffold/skills/vitest/references/advanced-environments.md +264 -0
- package/scaffold/skills/vitest/references/advanced-projects.md +300 -0
- package/scaffold/skills/vitest/references/advanced-type-testing.md +237 -0
- package/scaffold/skills/vitest/references/advanced-vi.md +249 -0
- package/scaffold/skills/vitest/references/core-cli.md +166 -0
- package/scaffold/skills/vitest/references/core-config.md +174 -0
- package/scaffold/skills/vitest/references/core-describe.md +193 -0
- package/scaffold/skills/vitest/references/core-expect.md +219 -0
- package/scaffold/skills/vitest/references/core-hooks.md +244 -0
- package/scaffold/skills/vitest/references/core-test-api.md +233 -0
- package/scaffold/skills/vitest/references/features-concurrency.md +250 -0
- package/scaffold/skills/vitest/references/features-context.md +238 -0
- package/scaffold/skills/vitest/references/features-coverage.md +207 -0
- package/scaffold/skills/vitest/references/features-filtering.md +211 -0
- package/scaffold/skills/vitest/references/features-mocking.md +265 -0
- package/scaffold/skills/vitest/references/features-snapshots.md +207 -0
- package/scaffold/skills/worktree/SKILL.md +93 -0
- package/scaffold/storyboard.config.json +44 -0
- package/src/canvas/Canvas.jsx +78 -0
- package/src/canvas/Draggable.jsx +235 -0
- package/src/canvas/index.d.ts +41 -0
- package/src/canvas/index.js +6 -0
- package/src/canvas/style.css +118 -0
- package/src/canvas/useResetCanvas.js +17 -0
- package/src/canvas/utils.js +136 -0
- package/src/core/assets/fonts/IoskeleyMono-Bold.woff2 +0 -0
- package/src/core/assets/fonts/IoskeleyMono-Italic.woff2 +0 -0
- package/src/core/assets/fonts/IoskeleyMono-Medium.woff2 +0 -0
- package/src/core/assets/fonts/IoskeleyMono-Regular.woff2 +0 -0
- package/src/core/assets/fonts/IoskeleyMono-SemiBold.woff2 +0 -0
- package/src/core/autosync/server.js +714 -0
- package/src/core/autosync/server.test.js +158 -0
- package/src/core/canvas/__tests__/agent-integration.test.js +596 -0
- package/src/core/canvas/__tests__/helpers/browser.js +95 -0
- package/src/core/canvas/__tests__/helpers/canvas-api.js +129 -0
- package/src/core/canvas/__tests__/helpers/perf.js +118 -0
- package/src/core/canvas/__tests__/helpers/setup.js +176 -0
- package/src/core/canvas/__tests__/helpers/tmux.js +130 -0
- package/src/core/canvas/__tests__/helpers/transcript.js +132 -0
- package/src/core/canvas/__tests__/terminal-integration.test.js +177 -0
- package/src/core/canvas/collision.js +292 -0
- package/src/core/canvas/collision.test.js +371 -0
- package/src/core/canvas/compact.js +83 -0
- package/src/core/canvas/deriveCanvasId.test.js +40 -0
- package/src/core/canvas/githubEmbeds.js +527 -0
- package/src/core/canvas/githubEmbeds.test.js +302 -0
- package/src/core/canvas/hot-pool.js +766 -0
- package/src/core/canvas/identity.js +107 -0
- package/src/core/canvas/identity.test.js +100 -0
- package/src/core/canvas/materializer.js +259 -0
- package/src/core/canvas/materializer.test.js +356 -0
- package/src/core/canvas/selectedWidgets.js +270 -0
- package/src/core/canvas/selectedWidgets.test.js +321 -0
- package/src/core/canvas/server.js +3134 -0
- package/src/core/canvas/server.test.js +379 -0
- package/src/core/canvas/terminal-config.js +330 -0
- package/src/core/canvas/terminal-registry.js +465 -0
- package/src/core/canvas/terminal-server.js +1436 -0
- package/src/core/canvas/writeGuard.js +53 -0
- package/src/core/cli/agent.js +85 -0
- package/src/core/cli/branch.js +386 -0
- package/src/core/cli/canvasAdd.js +241 -0
- package/src/core/cli/canvasBatch.js +98 -0
- package/src/core/cli/canvasBounds.js +160 -0
- package/src/core/cli/canvasRead.js +236 -0
- package/src/core/cli/canvasUpdate.js +179 -0
- package/src/core/cli/code.js +67 -0
- package/src/core/cli/compact.js +62 -0
- package/src/core/cli/create.js +674 -0
- package/src/core/cli/dev-helpers.js +53 -0
- package/src/core/cli/dev-helpers.test.js +53 -0
- package/src/core/cli/dev.js +430 -0
- package/src/core/cli/exit.js +38 -0
- package/src/core/cli/flags.js +174 -0
- package/src/core/cli/flags.test.js +155 -0
- package/src/core/cli/index.js +233 -0
- package/src/core/cli/intro.js +37 -0
- package/src/core/cli/proxy.js +319 -0
- package/src/core/cli/proxy.test.js +63 -0
- package/src/core/cli/schemas.js +223 -0
- package/src/core/cli/server.js +192 -0
- package/src/core/cli/serverUrl.js +61 -0
- package/src/core/cli/sessions.js +459 -0
- package/src/core/cli/setup.js +404 -0
- package/src/core/cli/terminal-commands.js +287 -0
- package/src/core/cli/terminal-messaging.js +231 -0
- package/src/core/cli/terminal-welcome.js +515 -0
- package/src/core/cli/updateVersion.js +124 -0
- package/src/core/comments/api.js +284 -0
- package/src/core/comments/api.test.js +282 -0
- package/src/core/comments/auth.js +151 -0
- package/src/core/comments/auth.test.js +167 -0
- package/src/core/comments/commentCache.js +109 -0
- package/src/core/comments/commentCache.test.js +48 -0
- package/src/core/comments/commentDrafts.js +68 -0
- package/src/core/comments/commentMode.js +63 -0
- package/src/core/comments/commentMode.test.js +90 -0
- package/src/core/comments/config.js +47 -0
- package/src/core/comments/config.test.js +77 -0
- package/src/core/comments/graphql.js +65 -0
- package/src/core/comments/graphql.test.js +95 -0
- package/src/core/comments/index.js +42 -0
- package/src/core/comments/metadata.js +52 -0
- package/src/core/comments/metadata.test.js +110 -0
- package/src/core/comments/queries.js +245 -0
- package/src/core/comments/ui/AuthModal.jsx +114 -0
- package/src/core/comments/ui/CommentOverlay.js +52 -0
- package/src/core/comments/ui/CommentWindow.jsx +329 -0
- package/src/core/comments/ui/CommentsDrawer.jsx +102 -0
- package/src/core/comments/ui/Composer.jsx +64 -0
- package/src/core/comments/ui/authModal.js +66 -0
- package/src/core/comments/ui/authModal.test.js +76 -0
- package/src/core/comments/ui/comment-cursor-dark.svg +1 -0
- package/src/core/comments/ui/comment-cursor.svg +1 -0
- package/src/core/comments/ui/comment-layout.css +142 -0
- package/src/core/comments/ui/commentWindow.js +121 -0
- package/src/core/comments/ui/comments.css +242 -0
- package/src/core/comments/ui/commentsDrawer.js +84 -0
- package/src/core/comments/ui/composer.js +136 -0
- package/src/core/comments/ui/index.js +14 -0
- package/src/core/comments/ui/mount.js +687 -0
- package/src/core/comments/ui/mount.test.js +336 -0
- package/src/core/data/dotPath.js +53 -0
- package/src/core/data/dotPath.test.js +114 -0
- package/src/core/data/loader.js +409 -0
- package/src/core/data/loader.test.js +599 -0
- package/src/core/data/viewfinder.js +363 -0
- package/src/core/data/viewfinder.test.js +456 -0
- package/src/core/devtools/devtools-consumer.js +28 -0
- package/src/core/devtools/devtools.js +144 -0
- package/src/core/devtools/devtools.test.js +75 -0
- package/src/core/devtools/sceneDebug.js +112 -0
- package/src/core/devtools/sceneDebug.test.js +141 -0
- package/src/core/index.js +124 -0
- package/src/core/inspector/fiberWalker.js +239 -0
- package/src/core/inspector/highlighter.js +275 -0
- package/src/core/inspector/mouseMode.js +259 -0
- package/src/core/lib/components/ui/alert/alert-action.jsx +11 -0
- package/src/core/lib/components/ui/alert/alert-description.jsx +11 -0
- package/src/core/lib/components/ui/alert/alert-title.jsx +11 -0
- package/src/core/lib/components/ui/alert/alert.jsx +25 -0
- package/src/core/lib/components/ui/alert/index.js +17 -0
- package/src/core/lib/components/ui/avatar/avatar-badge.jsx +22 -0
- package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
- package/src/core/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
- package/src/core/lib/components/ui/avatar/avatar-group.jsx +19 -0
- package/src/core/lib/components/ui/avatar/avatar-image.jsx +15 -0
- package/src/core/lib/components/ui/avatar/avatar.jsx +19 -0
- package/src/core/lib/components/ui/avatar/index.js +22 -0
- package/src/core/lib/components/ui/badge/badge.jsx +31 -0
- package/src/core/lib/components/ui/badge/index.js +2 -0
- package/src/core/lib/components/ui/button/button.jsx +100 -0
- package/src/core/lib/components/ui/button/index.js +12 -0
- package/src/core/lib/components/ui/card/card-action.jsx +11 -0
- package/src/core/lib/components/ui/card/card-content.jsx +11 -0
- package/src/core/lib/components/ui/card/card-description.jsx +11 -0
- package/src/core/lib/components/ui/card/card-footer.jsx +11 -0
- package/src/core/lib/components/ui/card/card-header.jsx +19 -0
- package/src/core/lib/components/ui/card/card-title.jsx +11 -0
- package/src/core/lib/components/ui/card/card.jsx +17 -0
- package/src/core/lib/components/ui/card/index.js +25 -0
- package/src/core/lib/components/ui/checkbox/checkbox.jsx +29 -0
- package/src/core/lib/components/ui/checkbox/index.js +6 -0
- package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
- package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
- package/src/core/lib/components/ui/collapsible/collapsible.jsx +7 -0
- package/src/core/lib/components/ui/collapsible/index.js +13 -0
- package/src/core/lib/components/ui/dialog/dialog-close.jsx +7 -0
- package/src/core/lib/components/ui/dialog/dialog-content.jsx +34 -0
- package/src/core/lib/components/ui/dialog/dialog-description.jsx +15 -0
- package/src/core/lib/components/ui/dialog/dialog-footer.jsx +23 -0
- package/src/core/lib/components/ui/dialog/dialog-header.jsx +11 -0
- package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
- package/src/core/lib/components/ui/dialog/dialog-portal.jsx +4 -0
- package/src/core/lib/components/ui/dialog/dialog-title.jsx +15 -0
- package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
- package/src/core/lib/components/ui/dialog/dialog.jsx +4 -0
- package/src/core/lib/components/ui/dialog/index.js +34 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
- package/src/core/lib/components/ui/dropdown-menu/index.js +54 -0
- package/src/core/lib/components/ui/input/index.js +7 -0
- package/src/core/lib/components/ui/input/input.jsx +19 -0
- package/src/core/lib/components/ui/label/index.js +7 -0
- package/src/core/lib/components/ui/label/label.jsx +19 -0
- package/src/core/lib/components/ui/panel/index.js +24 -0
- package/src/core/lib/components/ui/panel/panel-body.jsx +11 -0
- package/src/core/lib/components/ui/panel/panel-close.jsx +16 -0
- package/src/core/lib/components/ui/panel/panel-content.jsx +29 -0
- package/src/core/lib/components/ui/panel/panel-footer.jsx +11 -0
- package/src/core/lib/components/ui/panel/panel-header.jsx +11 -0
- package/src/core/lib/components/ui/panel/panel-title.jsx +12 -0
- package/src/core/lib/components/ui/panel/panel.jsx +4 -0
- package/src/core/lib/components/ui/popover/index.js +28 -0
- package/src/core/lib/components/ui/popover/popover-close.jsx +7 -0
- package/src/core/lib/components/ui/popover/popover-content.jsx +22 -0
- package/src/core/lib/components/ui/popover/popover-description.jsx +11 -0
- package/src/core/lib/components/ui/popover/popover-header.jsx +11 -0
- package/src/core/lib/components/ui/popover/popover-portal.jsx +4 -0
- package/src/core/lib/components/ui/popover/popover-title.jsx +11 -0
- package/src/core/lib/components/ui/popover/popover-trigger.jsx +8 -0
- package/src/core/lib/components/ui/popover/popover.jsx +4 -0
- package/src/core/lib/components/ui/searchable-list.jsx +160 -0
- package/src/core/lib/components/ui/select/index.js +37 -0
- package/src/core/lib/components/ui/select/select-content.jsx +30 -0
- package/src/core/lib/components/ui/select/select-group-heading.jsx +17 -0
- package/src/core/lib/components/ui/select/select-group.jsx +15 -0
- package/src/core/lib/components/ui/select/select-item.jsx +26 -0
- package/src/core/lib/components/ui/select/select-label.jsx +11 -0
- package/src/core/lib/components/ui/select/select-portal.jsx +4 -0
- package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
- package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
- package/src/core/lib/components/ui/select/select-separator.jsx +15 -0
- package/src/core/lib/components/ui/select/select-trigger.jsx +25 -0
- package/src/core/lib/components/ui/select/select.jsx +4 -0
- package/src/core/lib/components/ui/separator/index.js +7 -0
- package/src/core/lib/components/ui/separator/separator.jsx +22 -0
- package/src/core/lib/components/ui/sheet/index.js +34 -0
- package/src/core/lib/components/ui/sheet/sheet-close.jsx +7 -0
- package/src/core/lib/components/ui/sheet/sheet-content.jsx +35 -0
- package/src/core/lib/components/ui/sheet/sheet-description.jsx +15 -0
- package/src/core/lib/components/ui/sheet/sheet-footer.jsx +11 -0
- package/src/core/lib/components/ui/sheet/sheet-header.jsx +11 -0
- package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
- package/src/core/lib/components/ui/sheet/sheet-portal.jsx +4 -0
- package/src/core/lib/components/ui/sheet/sheet-title.jsx +15 -0
- package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
- package/src/core/lib/components/ui/sheet/sheet.jsx +4 -0
- package/src/core/lib/components/ui/textarea/index.js +7 -0
- package/src/core/lib/components/ui/textarea/textarea.jsx +18 -0
- package/src/core/lib/components/ui/toggle/index.js +8 -0
- package/src/core/lib/components/ui/toggle/toggle.jsx +36 -0
- package/src/core/lib/components/ui/toggle-group/index.js +10 -0
- package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
- package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
- package/src/core/lib/components/ui/tooltip/index.js +3 -0
- package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
- package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
- package/src/core/lib/components/ui/tooltip/tooltip.jsx +11 -0
- package/src/core/lib/components/ui/trigger-button/index.js +6 -0
- package/src/core/lib/components/ui/trigger-button/trigger-button.css +38 -0
- package/src/core/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
- package/src/core/lib/utils/index.js +6 -0
- package/src/core/logger/devLogger.js +238 -0
- package/src/core/logger/devLogger.test.js +193 -0
- package/src/core/modes/modes.css +98 -0
- package/src/core/modes/modes.js +492 -0
- package/src/core/modes/modes.test.js +562 -0
- package/src/core/mountStoryboardCore.js +478 -0
- package/src/core/rename-watcher/config.json +23 -0
- package/src/core/rename-watcher/watcher.js +531 -0
- package/src/core/scaffold.js +100 -0
- package/src/core/server/index.js +391 -0
- package/src/core/session/bodyClasses.js +128 -0
- package/src/core/session/bodyClasses.test.js +192 -0
- package/src/core/session/hashSubscribe.js +19 -0
- package/src/core/session/hashSubscribe.test.js +62 -0
- package/src/core/session/hideMode.js +424 -0
- package/src/core/session/hideMode.test.js +268 -0
- package/src/core/session/interceptHideParams.js +35 -0
- package/src/core/session/interceptHideParams.test.js +90 -0
- package/src/core/session/localStorage.js +134 -0
- package/src/core/session/localStorage.test.js +148 -0
- package/src/core/session/session.js +76 -0
- package/src/core/session/session.test.js +91 -0
- package/src/core/stores/canvasConfig.js +134 -0
- package/src/core/stores/canvasConfig.test.js +120 -0
- package/src/core/stores/commandActions.js +284 -0
- package/src/core/stores/commandPaletteConfig.js +31 -0
- package/src/core/stores/configSchema.js +232 -0
- package/src/core/stores/configSchema.test.js +72 -0
- package/src/core/stores/configStore.js +161 -0
- package/src/core/stores/customerModeConfig.js +30 -0
- package/src/core/stores/featureFlags.js +127 -0
- package/src/core/stores/paletteProviders.js +360 -0
- package/src/core/stores/paletteProviders.test.js +186 -0
- package/src/core/stores/plugins.js +40 -0
- package/src/core/stores/plugins.test.js +68 -0
- package/src/core/stores/recentArtifacts.js +68 -0
- package/src/core/stores/recentArtifacts.test.js +71 -0
- package/src/core/stores/sidePanelStore.ts +143 -0
- package/src/core/stores/themeStore.ts +291 -0
- package/src/core/stores/toolRegistry.js +227 -0
- package/src/core/stores/toolStateStore.js +183 -0
- package/src/core/stores/toolStateStore.test.js +220 -0
- package/src/core/stores/toolbarConfigStore.js +165 -0
- package/src/core/stores/uiConfig.js +64 -0
- package/src/core/stores/uiConfig.test.js +63 -0
- package/src/core/styles/tailwind.css +204 -0
- package/src/core/tools/handlers/autosync.js +12 -0
- package/src/core/tools/handlers/canvasAddWidget.js +11 -0
- package/src/core/tools/handlers/canvasAgents.js +20 -0
- package/src/core/tools/handlers/canvasToolbar.js +56 -0
- package/src/core/tools/handlers/commandPalette.js +9 -0
- package/src/core/tools/handlers/comments.js +16 -0
- package/src/core/tools/handlers/create.js +39 -0
- package/src/core/tools/handlers/devtools.js +122 -0
- package/src/core/tools/handlers/devtools.test.js +87 -0
- package/src/core/tools/handlers/featureFlags.js +21 -0
- package/src/core/tools/handlers/flows.js +68 -0
- package/src/core/tools/handlers/hideChrome.js +9 -0
- package/src/core/tools/handlers/hideToolbars.js +25 -0
- package/src/core/tools/handlers/inspector.js +19 -0
- package/src/core/tools/handlers/paletteTheme.js +35 -0
- package/src/core/tools/handlers/theme.js +9 -0
- package/src/core/tools/registry.js +26 -0
- package/src/core/tools/surfaces/canvasToolbar.js +10 -0
- package/src/core/tools/surfaces/commandList.js +10 -0
- package/src/core/tools/surfaces/mainToolbar.js +11 -0
- package/src/core/tools/surfaces/registry.js +19 -0
- package/src/core/ui/ActionMenuButton.jsx +114 -0
- package/src/core/ui/AutosyncMenuButton.css +67 -0
- package/src/core/ui/AutosyncMenuButton.jsx +242 -0
- package/src/core/ui/BranchSelect.jsx +29 -0
- package/src/core/ui/BranchSelect.module.css +30 -0
- package/src/core/ui/CanvasAgentsMenu.jsx +89 -0
- package/src/core/ui/CanvasCreateMenu.jsx +611 -0
- package/src/core/ui/CanvasSnap.css +27 -0
- package/src/core/ui/CanvasSnap.jsx +51 -0
- package/src/core/ui/CanvasUndoRedo.css +36 -0
- package/src/core/ui/CanvasUndoRedo.jsx +62 -0
- package/src/core/ui/CanvasZoomControl.css +53 -0
- package/src/core/ui/CanvasZoomControl.jsx +49 -0
- package/src/core/ui/CanvasZoomToFit.css +18 -0
- package/src/core/ui/CanvasZoomToFit.jsx +26 -0
- package/src/core/ui/CommandMenu.css +8 -0
- package/src/core/ui/CommandMenu.jsx +287 -0
- package/src/core/ui/CommandPalette.jsx +35 -0
- package/src/core/ui/CommandPaletteTrigger.jsx +25 -0
- package/src/core/ui/CommentsMenuButton.jsx +40 -0
- package/src/core/ui/CoreUIBar.css +47 -0
- package/src/core/ui/CoreUIBar.jsx +905 -0
- package/src/core/ui/CreateMenuButton.jsx +117 -0
- package/src/core/ui/HideChromeTrigger.jsx +48 -0
- package/src/core/ui/Icon.jsx +279 -0
- package/src/core/ui/InspectorPanel.css +109 -0
- package/src/core/ui/InspectorPanel.jsx +632 -0
- package/src/core/ui/PwaInstallBanner.css +42 -0
- package/src/core/ui/PwaInstallBanner.jsx +124 -0
- package/src/core/ui/SidePanel.jsx +261 -0
- package/src/core/ui/ThemeMenuButton.jsx +139 -0
- package/src/core/ui/core-ui-colors.css +129 -0
- package/src/core/ui/design-modes.ts +7 -0
- package/src/core/ui/sidepanel.css +301 -0
- package/src/core/ui/viewfinder.ts +7 -0
- package/src/core/ui-entry.js +30 -0
- package/src/core/utils/fuzzySearch.js +117 -0
- package/src/core/utils/fuzzySearch.test.js +119 -0
- package/src/core/utils/mobileViewport.js +57 -0
- package/src/core/utils/mobileViewport.test.js +68 -0
- package/src/core/utils/prodMode.js +38 -0
- package/src/core/utils/smoothCorners.js +20 -0
- package/src/core/vite/docs-handler.js +155 -0
- package/src/core/vite/server-plugin.js +797 -0
- package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
- package/src/core/workshop/features/createCanvas/index.js +14 -0
- package/src/core/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
- package/src/core/workshop/features/createFlow/index.js +19 -0
- package/src/core/workshop/features/createFlow/server.js +663 -0
- package/src/core/workshop/features/createPage/CreatePageForm.jsx +304 -0
- package/src/core/workshop/features/createPage/index.js +11 -0
- package/src/core/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
- package/src/core/workshop/features/createPrototype/index.js +19 -0
- package/src/core/workshop/features/createPrototype/server.js +433 -0
- package/src/core/workshop/features/createStory/CreateStoryForm.jsx +208 -0
- package/src/core/workshop/features/createStory/index.js +14 -0
- package/src/core/workshop/features/registry-server.js +22 -0
- package/src/core/workshop/features/registry.js +28 -0
- package/src/core/workshop/features/templateIndex.js +155 -0
- package/src/core/workshop/ui/WorkshopPanel.jsx +98 -0
- package/src/core/workshop/ui/mount.ts +6 -0
- package/src/core/worktree/port.js +268 -0
- package/src/core/worktree/port.test.js +222 -0
- package/src/core/worktree/serverRegistry.js +120 -0
- package/src/internals/AuthModal/AuthModal.jsx +132 -0
- package/src/internals/AuthModal/AuthModal.module.css +221 -0
- package/src/internals/BranchBar/BranchBar.jsx +87 -0
- package/src/internals/BranchBar/BranchBar.module.css +247 -0
- package/src/internals/BranchBar/useBranches.js +93 -0
- package/src/internals/BranchBar/useBranches.test.js +68 -0
- package/src/internals/CommandPalette/CommandPalette.jsx +1361 -0
- package/src/internals/CommandPalette/CreateDialog.jsx +219 -0
- package/src/internals/CommandPalette/command-palette.css +180 -0
- package/src/internals/FlowError.module.css +30 -0
- package/src/internals/Icon.jsx +279 -0
- package/src/internals/StoryboardContext.js +3 -0
- package/src/internals/Viewfinder.jsx +1479 -0
- package/src/internals/Viewfinder.module.css +1540 -0
- package/src/internals/Workspace.jsx +7 -0
- package/src/internals/__mocks__/virtual-storyboard-data-index.js +4 -0
- package/src/internals/canvas/CanvasControls.jsx +112 -0
- package/src/internals/canvas/CanvasControls.module.css +135 -0
- package/src/internals/canvas/CanvasPage.bridge.test.jsx +387 -0
- package/src/internals/canvas/CanvasPage.dragdrop.test.jsx +350 -0
- package/src/internals/canvas/CanvasPage.jsx +3092 -0
- package/src/internals/canvas/CanvasPage.module.css +187 -0
- package/src/internals/canvas/CanvasPage.multiselect.test.jsx +358 -0
- package/src/internals/canvas/CanvasToolbar.jsx +73 -0
- package/src/internals/canvas/CanvasToolbar.module.css +92 -0
- package/src/internals/canvas/ComponentErrorBoundary.jsx +50 -0
- package/src/internals/canvas/ConnectorLayer.jsx +208 -0
- package/src/internals/canvas/ConnectorLayer.module.css +129 -0
- package/src/internals/canvas/MarqueeOverlay.jsx +20 -0
- package/src/internals/canvas/PageSelector.jsx +587 -0
- package/src/internals/canvas/PageSelector.module.css +261 -0
- package/src/internals/canvas/PageSelector.test.jsx +113 -0
- package/src/internals/canvas/WebGLContextPool.jsx +292 -0
- package/src/internals/canvas/WebGLContextPool.test.jsx +165 -0
- package/src/internals/canvas/canvasApi.js +164 -0
- package/src/internals/canvas/canvasReloadGuard.js +37 -0
- package/src/internals/canvas/canvasReloadGuard.test.js +27 -0
- package/src/internals/canvas/canvasTheme.js +118 -0
- package/src/internals/canvas/componentIsolate.jsx +165 -0
- package/src/internals/canvas/componentSetIsolate.jsx +257 -0
- package/src/internals/canvas/computeCanvasBounds.test.js +121 -0
- package/src/internals/canvas/connectorGeometry.js +132 -0
- package/src/internals/canvas/hotPoolDevLogs.js +25 -0
- package/src/internals/canvas/textSelection.js +10 -0
- package/src/internals/canvas/textSelection.test.js +26 -0
- package/src/internals/canvas/useCanvas.js +126 -0
- package/src/internals/canvas/useCanvas.test.js +26 -0
- package/src/internals/canvas/useMarqueeSelect.js +213 -0
- package/src/internals/canvas/useMarqueeSelect.test.js +78 -0
- package/src/internals/canvas/useUndoRedo.js +86 -0
- package/src/internals/canvas/useUndoRedo.test.js +231 -0
- package/src/internals/canvas/widgets/CodePenEmbed.jsx +293 -0
- package/src/internals/canvas/widgets/CodePenEmbed.module.css +161 -0
- package/src/internals/canvas/widgets/ComponentSetWidget.jsx +2 -0
- package/src/internals/canvas/widgets/ComponentSetWidget.module.css +89 -0
- package/src/internals/canvas/widgets/ComponentWidget.jsx +14 -0
- package/src/internals/canvas/widgets/ComponentWidget.module.css +0 -0
- package/src/internals/canvas/widgets/CropOverlay.jsx +179 -0
- package/src/internals/canvas/widgets/CropOverlay.module.css +154 -0
- package/src/internals/canvas/widgets/ExpandedPane.jsx +474 -0
- package/src/internals/canvas/widgets/ExpandedPane.module.css +179 -0
- package/src/internals/canvas/widgets/ExpandedPane.test.jsx +240 -0
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +111 -0
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.module.css +59 -0
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.test.jsx +45 -0
- package/src/internals/canvas/widgets/FigmaEmbed.jsx +296 -0
- package/src/internals/canvas/widgets/FigmaEmbed.module.css +222 -0
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +151 -0
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +83 -0
- package/src/internals/canvas/widgets/ImageWidget.jsx +287 -0
- package/src/internals/canvas/widgets/ImageWidget.module.css +81 -0
- package/src/internals/canvas/widgets/LinkPreview.jsx +439 -0
- package/src/internals/canvas/widgets/LinkPreview.module.css +585 -0
- package/src/internals/canvas/widgets/LinkPreview.test.jsx +193 -0
- package/src/internals/canvas/widgets/MarkdownBlock.jsx +354 -0
- package/src/internals/canvas/widgets/MarkdownBlock.module.css +377 -0
- package/src/internals/canvas/widgets/MarkdownBlock.test.jsx +92 -0
- package/src/internals/canvas/widgets/PromptWidget.jsx +428 -0
- package/src/internals/canvas/widgets/PromptWidget.module.css +273 -0
- package/src/internals/canvas/widgets/PrototypeEmbed.jsx +463 -0
- package/src/internals/canvas/widgets/PrototypeEmbed.module.css +579 -0
- package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +10 -0
- package/src/internals/canvas/widgets/ResizeHandle.jsx +67 -0
- package/src/internals/canvas/widgets/ResizeHandle.module.css +29 -0
- package/src/internals/canvas/widgets/StickyNote.jsx +92 -0
- package/src/internals/canvas/widgets/StickyNote.module.css +70 -0
- package/src/internals/canvas/widgets/StickyNote.test.jsx +116 -0
- package/src/internals/canvas/widgets/StorySetWidget.jsx +208 -0
- package/src/internals/canvas/widgets/StorySetWidget.module.css +89 -0
- package/src/internals/canvas/widgets/StoryWidget.jsx +334 -0
- package/src/internals/canvas/widgets/StoryWidget.module.css +211 -0
- package/src/internals/canvas/widgets/TerminalReadWidget.jsx +146 -0
- package/src/internals/canvas/widgets/TerminalReadWidget.module.css +94 -0
- package/src/internals/canvas/widgets/TerminalWidget.jsx +704 -0
- package/src/internals/canvas/widgets/TerminalWidget.module.css +444 -0
- package/src/internals/canvas/widgets/TilesWidget.jsx +300 -0
- package/src/internals/canvas/widgets/TilesWidget.module.css +133 -0
- package/src/internals/canvas/widgets/WidgetChrome.jsx +580 -0
- package/src/internals/canvas/widgets/WidgetChrome.module.css +421 -0
- package/src/internals/canvas/widgets/WidgetWrapper.jsx +15 -0
- package/src/internals/canvas/widgets/WidgetWrapper.module.css +25 -0
- package/src/internals/canvas/widgets/codepenUrl.js +75 -0
- package/src/internals/canvas/widgets/codepenUrl.test.js +76 -0
- package/src/internals/canvas/widgets/embedInteraction.test.jsx +173 -0
- package/src/internals/canvas/widgets/embedOverlay.module.css +35 -0
- package/src/internals/canvas/widgets/embedTheme.js +148 -0
- package/src/internals/canvas/widgets/expandUtils.js +559 -0
- package/src/internals/canvas/widgets/expandUtils.test.js +155 -0
- package/src/internals/canvas/widgets/figmaUrl.js +118 -0
- package/src/internals/canvas/widgets/figmaUrl.test.js +139 -0
- package/src/internals/canvas/widgets/githubUrl.js +82 -0
- package/src/internals/canvas/widgets/githubUrl.test.js +74 -0
- package/src/internals/canvas/widgets/iframeDevLogs.js +49 -0
- package/src/internals/canvas/widgets/iframeDevLogs.test.jsx +81 -0
- package/src/internals/canvas/widgets/index.js +42 -0
- package/src/internals/canvas/widgets/pasteRules.js +295 -0
- package/src/internals/canvas/widgets/pasteRules.test.js +474 -0
- package/src/internals/canvas/widgets/snapshotDisplay.test.jsx +211 -0
- package/src/internals/canvas/widgets/tilePool.js +23 -0
- package/src/internals/canvas/widgets/tiles/diagonal-bl.png +0 -0
- package/src/internals/canvas/widgets/tiles/diagonal-br.png +0 -0
- package/src/internals/canvas/widgets/tiles/diagonal-tl.png +0 -0
- package/src/internals/canvas/widgets/tiles/leaf.png +0 -0
- package/src/internals/canvas/widgets/tiles/quarter-tl.png +0 -0
- package/src/internals/canvas/widgets/tiles/quarter-tr.png +0 -0
- package/src/internals/canvas/widgets/tiles/solid-a.png +0 -0
- package/src/internals/canvas/widgets/tiles/solid-b.png +0 -0
- package/src/internals/canvas/widgets/widgetConfig.js +291 -0
- package/src/internals/canvas/widgets/widgetConfig.test.js +68 -0
- package/src/internals/canvas/widgets/widgetIcons.jsx +190 -0
- package/src/internals/canvas/widgets/widgetProps.js +133 -0
- package/src/internals/context/FormContext.js +13 -0
- package/src/internals/context/FormContext.test.js +48 -0
- package/src/internals/context.jsx +481 -0
- package/src/internals/context.test.jsx +296 -0
- package/src/internals/hashPreserver.js +73 -0
- package/src/internals/hashPreserver.test.js +107 -0
- package/src/internals/hooks/useConfig.js +14 -0
- package/src/internals/hooks/useFeatureFlag.js +14 -0
- package/src/internals/hooks/useFlows.js +50 -0
- package/src/internals/hooks/useFlows.test.js +134 -0
- package/src/internals/hooks/useHideMode.js +31 -0
- package/src/internals/hooks/useHideMode.test.js +43 -0
- package/src/internals/hooks/useLocalStorage.js +57 -0
- package/src/internals/hooks/useLocalStorage.test.js +75 -0
- package/src/internals/hooks/useMode.js +43 -0
- package/src/internals/hooks/useObject.js +101 -0
- package/src/internals/hooks/useObject.test.js +74 -0
- package/src/internals/hooks/useOverride.js +84 -0
- package/src/internals/hooks/useOverride.test.js +71 -0
- package/src/internals/hooks/usePrototypeReloadGuard.js +64 -0
- package/src/internals/hooks/useRecord.js +158 -0
- package/src/internals/hooks/useRecord.test.js +221 -0
- package/src/internals/hooks/useScene.js +38 -0
- package/src/internals/hooks/useScene.test.js +66 -0
- package/src/internals/hooks/useSceneData.js +108 -0
- package/src/internals/hooks/useSceneData.test.js +136 -0
- package/src/internals/hooks/useSession.js +4 -0
- package/src/internals/hooks/useSession.test.js +8 -0
- package/src/internals/hooks/useThemeState.js +61 -0
- package/src/internals/hooks/useThemeState.test.js +66 -0
- package/src/internals/hooks/useUndoRedo.js +28 -0
- package/src/internals/hooks/useUndoRedo.test.js +64 -0
- package/src/internals/index.js +58 -0
- package/src/internals/story/ComponentSetPage.jsx +198 -0
- package/src/internals/story/ComponentSetPage.module.css +129 -0
- package/src/internals/story/StoryPage.jsx +147 -0
- package/src/internals/story/StoryPage.module.css +18 -0
- package/src/internals/test-utils.js +45 -0
- package/src/internals/vite/data-plugin.js +1508 -0
- package/src/internals/vite/data-plugin.test.js +1223 -0
- package/src/test-utils.js +44 -0
- package/toolbar.config.json +271 -0
- package/widgets.config.json +1537 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ship
|
|
3
|
+
description: End-to-end feature shipping workflow — worktree, plan, implement, simplification review, adversarial review, and push to a remote branch.
|
|
4
|
+
metadata:
|
|
5
|
+
author: Daniel Fosco
|
|
6
|
+
version: "2026.4.15"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Ship Skill
|
|
10
|
+
|
|
11
|
+
> Triggered by: "ship", "ship this", "ship a feature", "ship it", "ship a change"
|
|
12
|
+
>
|
|
13
|
+
> **⚠️ This skill MUST be invoked whenever the user says "ship". Do NOT implement changes directly — always go through this workflow. Every step is mandatory and sequential.**
|
|
14
|
+
|
|
15
|
+
## What This Does
|
|
16
|
+
|
|
17
|
+
Runs an end-to-end feature shipping workflow: creates a worktree, plans the feature, implements it, validates with an adversarial rubber-duck review, and pushes to a remote branch. All work happens in an isolated worktree — never on `main`.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
|
|
23
|
+
No optional parameters.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## How to Execute
|
|
28
|
+
|
|
29
|
+
### Step 1: Create a worktree
|
|
30
|
+
|
|
31
|
+
Invoke the **worktree** skill to create a git worktree for the feature branch.
|
|
32
|
+
|
|
33
|
+
- Derive a kebab-case branch name from the user's feature description (e.g., "add dark mode toggle" → `add-dark-mode-toggle`), appended to the version number of the base branch if applicable (e.g., `4.0.0` -> `4.0.0--add-dark-mode-toggle`).
|
|
34
|
+
- If the user provided an explicit branch name, use that instead.
|
|
35
|
+
- Use `ask_user` to confirm the branch name before creating the worktree.
|
|
36
|
+
|
|
37
|
+
After the worktree is created, all subsequent work happens inside `worktrees/<branch-name>` **at the repository root** (use `git rev-parse --show-toplevel` to find the root). Never create worktrees nested inside other worktrees.
|
|
38
|
+
|
|
39
|
+
### Step 2: Plan the feature
|
|
40
|
+
|
|
41
|
+
Generate an implementation plan for the requested feature:
|
|
42
|
+
|
|
43
|
+
1. Explore the codebase to understand the relevant areas.
|
|
44
|
+
2. **Define clear goals** — extract 1–3 concrete, measurable goals from the user's request. Each goal should be a single sentence stating what the change achieves from the user's perspective. These goals are the contract — everything in the plan must serve at least one goal.
|
|
45
|
+
3. Write a structured plan to `.github/plans/<branch-name>.md` (inside the worktree).
|
|
46
|
+
4. The plan must include:
|
|
47
|
+
- **Goals** — the clear goals defined in step 2 above, numbered
|
|
48
|
+
- **Problem statement** — what the feature does and why
|
|
49
|
+
- **Approach** — high-level strategy
|
|
50
|
+
- **Files to change** — list of files to create, modify, or delete
|
|
51
|
+
- **Steps** — ordered implementation steps with enough detail to execute without referring back to the user's prompt
|
|
52
|
+
- **Edge cases & risks** — anything that could go wrong
|
|
53
|
+
5. Present a summary of the plan to the user.
|
|
54
|
+
6. Use `ask_user` to confirm:
|
|
55
|
+
> Does this plan look good? Should I proceed with implementation?
|
|
56
|
+
|
|
57
|
+
Do NOT proceed to Step 3 until the user confirms.
|
|
58
|
+
|
|
59
|
+
### Step 3: Create clips goal/tasks
|
|
60
|
+
|
|
61
|
+
**If the `clips` skill is available** (check for `.clips/` directory or `clips` CLI), create tracking issues before implementation begins:
|
|
62
|
+
|
|
63
|
+
1. Run `clips view` to check for a relevant existing goal.
|
|
64
|
+
2. If a matching goal exists, create tasks under it for the planned work.
|
|
65
|
+
3. If no matching goal exists, create a new goal with tasks derived from the plan.
|
|
66
|
+
4. Save the goal ID and issue number for closure tracking in Step 10.
|
|
67
|
+
|
|
68
|
+
If clips is not available, skip this step silently.
|
|
69
|
+
|
|
70
|
+
### Step 4: Implement and commit
|
|
71
|
+
|
|
72
|
+
Execute the plan:
|
|
73
|
+
|
|
74
|
+
1. Implement the changes following the plan.
|
|
75
|
+
2. Run existing linters and tests (`npm run lint`, `npm run build`, `npm run test`) to validate the changes.
|
|
76
|
+
3. Fix any issues that arise.
|
|
77
|
+
4. Stage and commit with a descriptive message:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git add -A
|
|
81
|
+
git commit -m "<type>: <description>
|
|
82
|
+
|
|
83
|
+
<body if needed>
|
|
84
|
+
|
|
85
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use conventional commit types (`feat`, `fix`, `refactor`, `docs`, `chore`, etc.).
|
|
89
|
+
|
|
90
|
+
### Step 5: Write tests
|
|
91
|
+
|
|
92
|
+
**Invoke the `vitest` skill** to write tests for the implementation:
|
|
93
|
+
|
|
94
|
+
1. Identify all new or changed logic that is testable (utilities, data transformations, hooks, state management, etc.).
|
|
95
|
+
2. Write tests using Vitest, following existing test patterns in the codebase.
|
|
96
|
+
3. Run `npm run test` to verify all tests pass (new and existing).
|
|
97
|
+
4. Fix any failures.
|
|
98
|
+
5. Stage and commit tests separately:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
git add -A
|
|
102
|
+
git commit -m "test: add tests for <feature>
|
|
103
|
+
|
|
104
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Skip this step only if** the change is purely documentation, configuration, or markup with no testable logic.
|
|
108
|
+
|
|
109
|
+
### Step 6: Adversarial rubber-duck review
|
|
110
|
+
|
|
111
|
+
Launch a single `rubber-duck` agent with an adversarial framing. Include the plan from Step 2, the diff of all changes (`git diff HEAD~1`), and the feature requirements from the user's original prompt.
|
|
112
|
+
|
|
113
|
+
**For each changed file**, check if architecture documentation exists at `.agents/architecture/path/to/file/filename.ext.md` and include it as context in the review prompt. This gives the reviewer the documented intent, invariants, and patterns for that file.
|
|
114
|
+
|
|
115
|
+
The prompt must include:
|
|
116
|
+
|
|
117
|
+
> You are an adversarial code reviewer. Your job is to BREAK this implementation. Assume nothing works correctly until proven otherwise. Specifically:
|
|
118
|
+
>
|
|
119
|
+
> 1. **Find bugs** — race conditions, off-by-one errors, null/undefined access, missing error handling
|
|
120
|
+
> 2. **Find security issues** — injection, XSS, data leaks, unsafe defaults
|
|
121
|
+
> 3. **Find logic errors** — incorrect assumptions, missing edge cases, broken invariants
|
|
122
|
+
> 4. **Find integration issues** — does this break existing behavior? Are imports/exports correct? Are types consistent?
|
|
123
|
+
> 5. **Find missing tests** — what scenarios are NOT covered?
|
|
124
|
+
>
|
|
125
|
+
> For each finding, rate severity as CRITICAL (must fix), HIGH (should fix), or LOW (nice to fix).
|
|
126
|
+
> Only report CRITICAL and HIGH findings. Ignore style, formatting, and naming.
|
|
127
|
+
|
|
128
|
+
#### Process findings
|
|
129
|
+
|
|
130
|
+
1. Apply all CRITICAL fixes immediately.
|
|
131
|
+
2. Apply HIGH fixes unless they significantly complicate the implementation without clear benefit.
|
|
132
|
+
3. Discard LOW findings.
|
|
133
|
+
4. If any changes were made, run lint/build/test again and commit:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git add -A
|
|
137
|
+
git commit -m "fix: address review findings
|
|
138
|
+
|
|
139
|
+
<summary of what was fixed>
|
|
140
|
+
|
|
141
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
5. If no findings required changes, skip the commit.
|
|
145
|
+
|
|
146
|
+
#### Process findings
|
|
147
|
+
|
|
148
|
+
1. For each SIGNIFICANT finding, evaluate whether the simplification still achieves all stated goals.
|
|
149
|
+
2. Apply simplifications that clearly reduce complexity without sacrificing goals.
|
|
150
|
+
3. Discard suggestions that would compromise a goal or introduce fragility.
|
|
151
|
+
4. If any changes were made, run lint/build/test again and commit:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
git add -A
|
|
155
|
+
git commit -m "refactor: simplify <area>
|
|
156
|
+
|
|
157
|
+
<summary of what was simplified>
|
|
158
|
+
|
|
159
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
5. If no findings required changes, skip the commit.
|
|
163
|
+
|
|
164
|
+
### Step 7: Update documentation
|
|
165
|
+
|
|
166
|
+
1. **Invoke the `architecture-scanner` skill** to scan and update architecture docs for any files changed in this feature.
|
|
167
|
+
2. Review and update `README.md`, `DOCS.md`, and any other relevant documentation files to reflect the changes made.
|
|
168
|
+
3. If any docs were updated, stage and commit:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git add -A
|
|
172
|
+
git commit -m "docs: update documentation for <feature>
|
|
173
|
+
|
|
174
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Skip this step only if** the change is trivial (typo fix, config tweak) with no user-facing or architectural impact.
|
|
178
|
+
|
|
179
|
+
### Step 8: Push to remote
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
git push -u origin <branch-name>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
If the push fails due to permissions or remote issues, inform the user and suggest manual steps.
|
|
186
|
+
|
|
187
|
+
After pushing, inform the user: "Branch pushed to `origin/<branch-name>`."
|
|
188
|
+
|
|
189
|
+
### Step 9: Close clips tasks
|
|
190
|
+
|
|
191
|
+
After the branch is pushed, mark clips tasks as closed:
|
|
192
|
+
|
|
193
|
+
1. Run `clips view` to find the goal/tasks created in Step 3.
|
|
194
|
+
2. Mark them as closed (`clips task status ... closed` / `clips goal status ... closed`).
|
|
195
|
+
|
|
196
|
+
If clips was skipped in Step 3, skip this step too.
|
|
197
|
+
|
|
198
|
+
### Step 10: Start dev server
|
|
199
|
+
|
|
200
|
+
Run the dev server in the worktree so the user can immediately preview changes:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npx storyboard dev
|
|
204
|
+
```
|
|
205
|
+
|
|
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.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Rules
|
|
211
|
+
|
|
212
|
+
- **Always create a worktree first** — invoke the worktree skill as Step 1, before any exploration or implementation. Never commit to `main`. Never create a branch from `main` after the fact. The worktree IS the branch.
|
|
213
|
+
- **Never skip the reviews** — both the simplification review and the adversarial rubber-duck review are mandatory quality gates.
|
|
214
|
+
- **Always run lint/build/test** before committing — at minimum `npm run lint && npm run build && npm run test`.
|
|
215
|
+
- **Always use `ask_user`** for confirmations — branch name and plan approval.
|
|
216
|
+
- **Conventional commits** — use `feat:`, `fix:`, `refactor:`, `docs:`, `chore:` prefixes.
|
|
217
|
+
- **Co-authored-by trailer** — every commit must include the Copilot co-author trailer.
|
|
218
|
+
- **If any step fails**, stop and inform the user with the error and suggested next steps. Do not silently continue.
|
|
219
|
+
- **Context inference** — if the user's prompt already provides the branch name, feature description, or other details, skip the corresponding `ask_user` question and use the provided value directly.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Example Usage
|
|
224
|
+
|
|
225
|
+
User says: "ship a feature to add canvas grid snapping"
|
|
226
|
+
|
|
227
|
+
1. Creates worktree `1.2.0--canvas-grid-snapping`
|
|
228
|
+
2. Plans the implementation with clear goals (explores codebase, writes plan)
|
|
229
|
+
3. Creates clips goal + tasks for the work
|
|
230
|
+
4. Implements grid snapping, commits
|
|
231
|
+
5. Writes tests using vitest skill, commits
|
|
232
|
+
6. Runs adversarial rubber-duck review, fixes findings, commits
|
|
233
|
+
7. Runs adversarial simplification review, simplifies if needed, commits
|
|
234
|
+
8. Updates architecture docs, README, DOCS as needed, commits
|
|
235
|
+
9. Pushes `1.2.0--canvas-grid-snapping` to origin
|
|
236
|
+
10. Marks clips tasks as closed
|
|
237
|
+
11. Starts dev server (`npx storyboard dev`) in the worktree
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: storyboard
|
|
3
|
+
description: Storyboard data structuring and management system. Use when creating flow data, setting up storyboard data, creating data objects, or structuring data for a prototype page.
|
|
4
|
+
metadata:
|
|
5
|
+
author: Daniel Fosco
|
|
6
|
+
version: "2026.3.09"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Storyboard
|
|
10
|
+
|
|
11
|
+
> Triggered by: when building a new page or route in storyboard, "create flow data", "set up storyboard data", "create data objects", "create new page", "create new route", when structuring data for a prototype page
|
|
12
|
+
|
|
13
|
+
## What This Does
|
|
14
|
+
|
|
15
|
+
Guides the creation of data objects, flow files, and record collections for pages being built. Determines what data should be externalized into the Storyboard data system vs. hardcoded in the component.
|
|
16
|
+
|
|
17
|
+
## Data File Types
|
|
18
|
+
|
|
19
|
+
Storyboard uses **suffix-based naming** for data files. Files can live anywhere in the repo — a Vite plugin discovers them automatically at dev/build time.
|
|
20
|
+
|
|
21
|
+
| Suffix | Purpose | Example |
|
|
22
|
+
|--------|---------|---------|
|
|
23
|
+
| `.flow.json` | Page data context | `default.flow.json` |
|
|
24
|
+
| `.object.json` | Reusable data fragment | `jane-doe.object.json` |
|
|
25
|
+
| `.record.json` | Parameterized collection (array with `id` per entry) | `posts.record.json` |
|
|
26
|
+
|
|
27
|
+
**Rules:**
|
|
28
|
+
- Every name+suffix must be unique across the entire repo (build fails on duplicates)
|
|
29
|
+
- Files can be organized into any subdirectory structure
|
|
30
|
+
- JSONC (comments) is supported — use `.jsonc` extension if preferred
|
|
31
|
+
- `$ref` and `$global` use **name-based** references (not paths): `{ "$ref": "jane-doe" }` finds `jane-doe.object.json` anywhere
|
|
32
|
+
|
|
33
|
+
## When This Applies
|
|
34
|
+
|
|
35
|
+
- After the primer-builder skill has identified the page structure and components (Steps 1–3)
|
|
36
|
+
- Replaces the primer-builder's Step 4 (Plan Data) with a more structured approach
|
|
37
|
+
- When refactoring an existing page to use flow data
|
|
38
|
+
- When creating dynamic route pages with records
|
|
39
|
+
|
|
40
|
+
## Navigation Anti-Pattern
|
|
41
|
+
|
|
42
|
+
**DO NOT use React Router's `<Link>` component for internal navigation.** Use plain `<a href="...">` tags instead.
|
|
43
|
+
|
|
44
|
+
The storyboard hash preserver intercepts `<a>` clicks to preserve URL hash params and handle client-side routing. React Router `<Link>` bypasses this by calling `navigate()` directly, which creates a duplicate browser history entry (one from `<Link>`, one from the hash preserver's click handler). This causes a "double back" bug where the user must press back twice to actually navigate back.
|
|
45
|
+
|
|
46
|
+
```jsx
|
|
47
|
+
// ❌ BAD — creates double history entries
|
|
48
|
+
<Link to="/Overview">Overview</Link>
|
|
49
|
+
|
|
50
|
+
// ✅ GOOD — intercepted by hash preserver for client-side navigation
|
|
51
|
+
<a href="/Overview">Overview</a>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## The Core Rule: What Goes in Data vs. What's Hardcoded
|
|
55
|
+
|
|
56
|
+
### Externalize as data objects
|
|
57
|
+
|
|
58
|
+
**Content and business model data** — anything that represents "what" the page displays:
|
|
59
|
+
|
|
60
|
+
- User profiles (name, avatar, bio, role)
|
|
61
|
+
- Repository / project metadata (name, description, language, stars, forks)
|
|
62
|
+
- Issue / PR items (title, state, author, labels, timestamps)
|
|
63
|
+
- Organization info (name, avatar, member count)
|
|
64
|
+
- Lists of entities (repos, issues, teams, packages, people)
|
|
65
|
+
|
|
66
|
+
**Navigation** — always externalize because it has repeated elements with many labels that benefit from easy bulk adjustment:
|
|
67
|
+
|
|
68
|
+
- Top navigation tabs (label, icon, counter, url, current state)
|
|
69
|
+
- Sidebar filter lists
|
|
70
|
+
- Settings section navigation
|
|
71
|
+
- Breadcrumb paths
|
|
72
|
+
|
|
73
|
+
**Important**: This will more usually be slotted in existing Template components from the repository, not generated code.
|
|
74
|
+
|
|
75
|
+
### Hardcode in the component
|
|
76
|
+
|
|
77
|
+
**UI chrome and microcopy** — anything that describes "how" the page works:
|
|
78
|
+
|
|
79
|
+
- Button labels: `"New repository"`, `"Save changes"`, `"Cancel"`
|
|
80
|
+
- Placeholder text: `"Find a repository..."`
|
|
81
|
+
- Section headings that are structural: `"Pinned repositories"`, `"Activity"`
|
|
82
|
+
- Empty state messages: `"No results found"`
|
|
83
|
+
- Filter dropdown labels: `"Type"`, `"Language"`, `"Sort"`
|
|
84
|
+
- Dropdown option labels: `"All"`, `"Public"`, `"Private"`
|
|
85
|
+
- Static instructional text
|
|
86
|
+
|
|
87
|
+
### Gray area — use judgment
|
|
88
|
+
|
|
89
|
+
- **Counters on tabs** — externalize if they represent real data counts; hardcode if decorative
|
|
90
|
+
- **Metadata labels** (e.g., "Updated 3 days ago") — externalize the date, hardcode the label format
|
|
91
|
+
- **Card/list item structure** — externalize the items array, hardcode the card template
|
|
92
|
+
|
|
93
|
+
## Workflow
|
|
94
|
+
|
|
95
|
+
### Step 1: Inventory the data needs
|
|
96
|
+
|
|
97
|
+
From the page description (primer-builder Step 1), list every piece of dynamic content:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Navigation:
|
|
101
|
+
- topnav: 9 tabs with icons, labels, counters, active state
|
|
102
|
+
- sidenav: 10 filter options with active state
|
|
103
|
+
|
|
104
|
+
Content:
|
|
105
|
+
- org name, avatar
|
|
106
|
+
- 6 repository items, each with: name, description, language, stars, updated date
|
|
107
|
+
- filter query string
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Step 2: Design the data objects
|
|
111
|
+
|
|
112
|
+
Create one object file per logical entity:
|
|
113
|
+
|
|
114
|
+
| Data type | File name pattern | Example |
|
|
115
|
+
|-----------|------------------|---------|
|
|
116
|
+
| User/person | `{name}.object.json` | `jane-doe.object.json` |
|
|
117
|
+
| Navigation | `{context}-navigation.object.json` | `org-navigation.object.json` |
|
|
118
|
+
| Entity list | `{entity-plural}.object.json` | `repositories.object.json` |
|
|
119
|
+
| Org/team | `{org-name}.object.json` | `primer-org.object.json` |
|
|
120
|
+
|
|
121
|
+
**Object structure rules:**
|
|
122
|
+
- **The object file's top-level structure IS the value that `$ref` resolves to.** If the flow has `"repositories": { "$ref": "repositories" }`, the object file should be a bare array `[...]`, not `{ "repositories": [...] }` — otherwise the data double-nests as `repositories.repositories`.
|
|
123
|
+
- Same rule for single-entity objects: if the flow has `"user": { "$ref": "jane-doe" }`, the object file should contain the user fields directly at root (`{ "name": "Jane", ... }`), not wrapped in `{ "user": { "name": "Jane", ... } }`.
|
|
124
|
+
- Keep objects flat where possible — avoid deep nesting
|
|
125
|
+
- Use arrays for lists of items
|
|
126
|
+
- Include all fields that the UI needs — don't make the component compute derived data
|
|
127
|
+
- Use realistic placeholder data (real GitHub avatar URLs, plausible repo names, etc.)
|
|
128
|
+
|
|
129
|
+
### Step 3: Compose the flow
|
|
130
|
+
|
|
131
|
+
Create a flow file that composes the objects:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
// default.flow.json
|
|
135
|
+
{
|
|
136
|
+
"$global": ["org-navigation"],
|
|
137
|
+
"user": { "$ref": "jane-doe" },
|
|
138
|
+
"org": {
|
|
139
|
+
"name": "my-org",
|
|
140
|
+
"avatar": "https://avatars.githubusercontent.com/u/9919?v=4"
|
|
141
|
+
},
|
|
142
|
+
"repositories": { "$ref": "repositories" }
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**flow composition rules:**
|
|
147
|
+
- Use `$global` for navigation — it merges at the root level, making nav data available at the top
|
|
148
|
+
- Use `$ref` for entity objects — keeps them reusable across flows
|
|
149
|
+
- `$ref` and `$global` use **names**, not paths: `"jane-doe"` not `"../objects/jane-doe"`
|
|
150
|
+
- Inline small, flow-specific data directly (org name, settings, filter state)
|
|
151
|
+
- Name the flow after the page/flow: `org-repos.flow.json`, `issue-detail.flow.json`
|
|
152
|
+
- Rule of thumb: a flow can be named after its corresponding page
|
|
153
|
+
|
|
154
|
+
### Step 4: Wire up the component
|
|
155
|
+
|
|
156
|
+
In the page component, use `useflowData()` with dot-notation paths:
|
|
157
|
+
|
|
158
|
+
```jsx
|
|
159
|
+
import { useflowData, useflowLoading } from '../storyboard'
|
|
160
|
+
|
|
161
|
+
function ReposPage() {
|
|
162
|
+
const topnav = useflowData('topnav') // from $global navigation
|
|
163
|
+
const sidenav = useflowData('sidenav') // from $global navigation
|
|
164
|
+
const org = useflowData('org')
|
|
165
|
+
const repos = useflowData('repositories')
|
|
166
|
+
const loading = useflowLoading()
|
|
167
|
+
|
|
168
|
+
if (loading) return <Spinner />
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<Application title={org.name} topnav={topnav} sidenav={sidenav}>
|
|
172
|
+
{/* Hardcoded UI chrome */}
|
|
173
|
+
<h2>All repositories</h2>
|
|
174
|
+
<Button variant="primary">New repository</Button>
|
|
175
|
+
<TextInput placeholder="Find a repository..." />
|
|
176
|
+
|
|
177
|
+
{/* Data-driven content */}
|
|
178
|
+
{repos.map(repo => (
|
|
179
|
+
<article key={repo.name}>
|
|
180
|
+
<h3><a href={repo.url}>{repo.name}</a></h3>
|
|
181
|
+
<p>{repo.description}</p>
|
|
182
|
+
</article>
|
|
183
|
+
))}
|
|
184
|
+
</Application>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Records & Dynamic Routes
|
|
190
|
+
|
|
191
|
+
Records power **parameterized pages** — the same page template renders different content based on the URL.
|
|
192
|
+
|
|
193
|
+
### Creating a record
|
|
194
|
+
|
|
195
|
+
A record file is a **collection** — an array of entries, each with a unique `id`:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
// posts.record.json
|
|
199
|
+
[
|
|
200
|
+
{
|
|
201
|
+
"id": "welcome-to-storyboard",
|
|
202
|
+
"title": "Welcome to Storyboard",
|
|
203
|
+
"date": "2026-02-14",
|
|
204
|
+
"author": "Jane Doe",
|
|
205
|
+
"body": "..."
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "another-post",
|
|
209
|
+
"title": "Another Post",
|
|
210
|
+
"date": "2026-02-13",
|
|
211
|
+
"author": "Jane Doe",
|
|
212
|
+
"body": "..."
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Creating a dynamic route page
|
|
218
|
+
|
|
219
|
+
The filename convention `[field].jsx` determines which record field the route matches against:
|
|
220
|
+
|
|
221
|
+
- `pages/issues/[id].jsx` → `useRecord('issues')` matches `entry.id`
|
|
222
|
+
- `pages/posts/[permalink].jsx` → `useRecord('posts', 'permalink')` matches `entry.permalink`
|
|
223
|
+
|
|
224
|
+
The second argument to `useRecord` defaults to `'id'`, so `useRecord('issues')` is equivalent to `useRecord('issues', 'id')`.
|
|
225
|
+
|
|
226
|
+
In the component, use `useRecord()`:
|
|
227
|
+
|
|
228
|
+
```jsx
|
|
229
|
+
import { useRecord } from '../../storyboard'
|
|
230
|
+
|
|
231
|
+
function BlogPost() {
|
|
232
|
+
// 'posts' = record file name, 'id' = route param matched against entry.id
|
|
233
|
+
const post = useRecord('posts', 'id')
|
|
234
|
+
// URL /posts/welcome-to-storyboard → entry with id "welcome-to-storyboard"
|
|
235
|
+
|
|
236
|
+
if (!post) return <p>Post not found</p>
|
|
237
|
+
return <h1>{post.title}</h1>
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Listing all records
|
|
242
|
+
|
|
243
|
+
Use `useRecords()` for index/listing pages:
|
|
244
|
+
|
|
245
|
+
```jsx
|
|
246
|
+
import { useRecords } from '../../storyboard'
|
|
247
|
+
|
|
248
|
+
function PostsIndex() {
|
|
249
|
+
const posts = useRecords('posts')
|
|
250
|
+
return posts.map(post => (
|
|
251
|
+
<a key={post.id} href={`/posts/${post.id}`}>{post.title}</a>
|
|
252
|
+
))
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Records + flows
|
|
257
|
+
|
|
258
|
+
A page can use both a flow (for page-level data like navigation) and a record (for parameterized content). Pass `recordName` and `recordParam` to `StoryboardProvider` to merge record data under the `record` key:
|
|
259
|
+
|
|
260
|
+
```jsx
|
|
261
|
+
<StoryboardProvider recordName="posts" recordParam="slug">
|
|
262
|
+
{/* useflowData('record.title') works here */}
|
|
263
|
+
</StoryboardProvider>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### No `useState` in pages or components
|
|
267
|
+
|
|
268
|
+
All state management must happen through storyboard hooks. Storyboard state lives in the URL hash — not in React component state.
|
|
269
|
+
|
|
270
|
+
**Use these hooks instead:**
|
|
271
|
+
|
|
272
|
+
| Hook | Purpose |
|
|
273
|
+
|------|---------|
|
|
274
|
+
| `useflowData(path?)` | Read flow data by dot-notation path |
|
|
275
|
+
| `useOverride(path)` | Read/write hash-param overrides on flow or object data. Works with or without `<StoryboardProvider>`. |
|
|
276
|
+
| `useObject(name, path?)` | Load an object data file directly by name, without a flow. Supports dot-notation path and hash overrides (`object.{name}.{field}`). |
|
|
277
|
+
| `useRecord(name, param?)` | Load a single record entry matched by URL param (defaults to `'id'`) |
|
|
278
|
+
| `useRecords(name)` | Load all entries from a record collection |
|
|
279
|
+
| `useflowLoading()` | Returns true while flow is loading |
|
|
280
|
+
|
|
281
|
+
**Why:** Storyboard is a prototyping framework where all data flows through the URL hash. This makes every state change shareable via URL, inspectable in the address bar, and framework-portable. Using `useState` breaks this contract — the state becomes invisible, unshareable, and tied to React.
|
|
282
|
+
|
|
283
|
+
## Common Pitfall: Double-Nesting with `$ref`
|
|
284
|
+
|
|
285
|
+
The most frequent data bug is double-nesting. This happens when an object file wraps its data in a key that matches the flow's `$ref` key:
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
// ❌ WRONG — causes double-nesting (advisory.advisory)
|
|
289
|
+
|
|
290
|
+
// flow: { "advisory": { "$ref": "advisory" } }
|
|
291
|
+
// advisory.object.json:
|
|
292
|
+
{ "advisory": { "title": "Bug", "severity": "High" } }
|
|
293
|
+
// Result: flow.advisory = { "advisory": { "title": "Bug", ... } }
|
|
294
|
+
|
|
295
|
+
// ✅ CORRECT — object file is the raw value
|
|
296
|
+
|
|
297
|
+
// flow: { "advisory": { "$ref": "advisory" } }
|
|
298
|
+
// advisory.object.json:
|
|
299
|
+
{ "title": "Bug", "severity": "High" }
|
|
300
|
+
// Result: flow.advisory = { "title": "Bug", "severity": "High" }
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Rule of thumb:** The `$ref` key in the flow IS the namespace. The object file provides the value.
|
|
304
|
+
|
|
305
|
+
## Hash Param Preservation (CRITICAL)
|
|
306
|
+
|
|
307
|
+
URL hash params are the foundation of the override system. They carry user-set and session-set values across navigations. **Never write code that drops them.**
|
|
308
|
+
|
|
309
|
+
### How it works
|
|
310
|
+
|
|
311
|
+
`installHashPreserver(router)` in `src/index.jsx` patches both `<a>` click interception and `router.navigate()` so that hash params automatically carry forward on every navigation — including programmatic `navigate('/SomePage')` calls.
|
|
312
|
+
|
|
313
|
+
### Rules
|
|
314
|
+
|
|
315
|
+
1. **Never manually strip or omit the hash.** The global preserver handles it. Plain `navigate('/Page')` works — the hash carries forward automatically.
|
|
316
|
+
2. **Never bypass the router.** Using `window.location.href = '/Page'` or `window.location.assign()` will drop the hash. Always use React Router's `navigate()` or `<Link>`.
|
|
317
|
+
3. **If a page reads overrides, it must use the hooks.** `useflowData(path)` automatically merges hash overrides. `useOverride(path)` gives read/write access.
|
|
318
|
+
4. **If a page writes overrides, downstream pages get them for free.** The Signup→Dashboard flow works because Signup writes via `useOverride`, navigation carries the hash, and Dashboard reads via `useflowData` — no manual plumbing needed.
|
|
319
|
+
5. **To intentionally clear overrides**, use `clearValue` from `useOverride` or `removeParam` from `session.js`. Never clear by navigating without the hash.
|
|
320
|
+
|
|
321
|
+
## Checklist
|
|
322
|
+
|
|
323
|
+
Before finishing data structuring, verify:
|
|
324
|
+
|
|
325
|
+
- [ ] **No double-nesting:** Object files referenced via `$ref` contain raw values, not wrapped in a key
|
|
326
|
+
- [ ] Every navigation array is in a data object (not hardcoded in the component)
|
|
327
|
+
- [ ] Every list of content items is in a data object
|
|
328
|
+
- [ ] User/org profile data is in a data object
|
|
329
|
+
- [ ] Button labels, placeholder text, and section headings are hardcoded
|
|
330
|
+
- [ ] The flow file uses `$global` for navigation and `$ref` for entities
|
|
331
|
+
- [ ] `$ref` and `$global` use **names** (not relative paths)
|
|
332
|
+
- [ ] Data files use the correct suffix: `.flow.json`, `.object.json`, `.record.json`
|
|
333
|
+
- [ ] The component uses `useflowData()` for all externalized data
|
|
334
|
+
- [ ] Shared data objects use `useObject()` when not part of a flow
|
|
335
|
+
- [ ] Dynamic route pages use `useRecord()` for parameterized content
|
|
336
|
+
- [ ] Data objects use realistic placeholder values
|
|
337
|
+
- [ ] The flow name matches the page name or flow
|
|
338
|
+
- [ ] **Hash params are never dropped** — see "Hash Param Preservation" above
|
|
339
|
+
|
|
340
|
+
## Final Step: Provide the URL
|
|
341
|
+
|
|
342
|
+
After creating the flow and wiring up the component, **always provide the full dev URL** so the user can immediately preview the page.
|
|
343
|
+
|
|
344
|
+
**Page-flow matching:** If the flow file name matches the page file name exactly (e.g. `Repositories.flow.json` for `pages/Repositories.jsx`), the flow loads automatically — no `?flow=` param needed:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
http://localhost:1234/Repositories
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
If the flow name differs from the page name, add the `?flow=` parameter:
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
http://localhost:1234/Repositories?flow=heron-silver
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
For dynamic routes, use the record entry's `id` as the URL slug:
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
http://localhost:1234/posts/welcome-to-storyboard
|
|
360
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Update Storyboard Packages
|
|
2
|
+
|
|
3
|
+
Updates all `@dfosco/storyboard-*` packages together to the same version and runs the scaffold sync.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run update # Update to latest stable
|
|
9
|
+
npm run update:beta # Update to latest beta
|
|
10
|
+
npm run update:alpha # Update to latest alpha
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
1. Updates all `@dfosco/storyboard-*` packages to the specified tag
|
|
16
|
+
2. Runs `npx storyboard-scaffold` to sync skills and scripts from the latest version
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Update all @dfosco/storyboard-* packages and sync scaffold files.
|
|
3
|
+
# Run from storyboard client root: npm run update
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
TAG="${1:-latest}"
|
|
7
|
+
|
|
8
|
+
PACKAGES=(
|
|
9
|
+
"@dfosco/storyboard-core"
|
|
10
|
+
"@dfosco/storyboard-react"
|
|
11
|
+
"@dfosco/storyboard-react-primer"
|
|
12
|
+
"@dfosco/storyboard-react-reshaped"
|
|
13
|
+
"@dfosco/tiny-canvas"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
echo "Updating @dfosco/* packages to @${TAG}..."
|
|
17
|
+
for pkg in "${PACKAGES[@]}"; do
|
|
18
|
+
npm install "${pkg}@${TAG}" --save
|
|
19
|
+
done
|
|
20
|
+
|
|
21
|
+
echo ""
|
|
22
|
+
echo "Running scaffold sync..."
|
|
23
|
+
npx storyboard-scaffold
|
|
24
|
+
|
|
25
|
+
echo ""
|
|
26
|
+
echo "✔ All packages updated to @${TAG} and scaffold synced."
|