dreative 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dist/cli/index.js +169 -0
- package/dist/server/agentQueue.js +70 -0
- package/dist/server/ai.js +177 -0
- package/dist/server/diff.js +97 -0
- package/dist/server/index.js +328 -0
- package/dist/server/jobs.js +31 -0
- package/dist/server/preview.js +110 -0
- package/dist/server/store.js +71 -0
- package/dist/shared/design.js +163 -0
- package/dist/shared/types.js +1 -0
- package/dist/ui/assets/index--vztc_MR.js +71 -0
- package/dist/ui/assets/index-y0gVjC7u.css +1 -0
- package/dist/ui/index.html +13 -0
- package/package.json +44 -0
- package/skill/dreative/DESIGN.md +358 -0
- package/skill/dreative/SKILL.md +108 -0
- package/skill/dreative/skills/3d.md +131 -0
- package/skill/dreative/skills/interaction.md +126 -0
- package/skill/dreative/skills/motion.md +125 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{font-family:ui-sans-serif,system-ui,Segoe UI,sans-serif;background:#0f1117;color:#e6e8ee;font-size:14px}.app{display:flex;flex-direction:column;height:100%}.topbar{display:flex;align-items:center;gap:12px;padding:10px 16px;border-bottom:1px solid #23262f;background:#14161d}.topbar .logo{font-weight:700;letter-spacing:.5px;color:#a5b4fc}.topbar input{flex:1;max-width:560px;background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 12px;outline:none}.topbar input:focus{border-color:#6366f1}button{background:#6366f1;color:#fff;border:0;border-radius:8px;padding:8px 14px;cursor:pointer;font-weight:600;font-size:13px}button:hover{background:#575ae0}button:disabled{opacity:.5;cursor:default}button.ghost{background:transparent;border:1px solid #2c2f3a;color:#c7cad4}button.ghost:hover{border-color:#6366f1;color:#fff}button.danger{background:#3a2030;color:#f7a6b8}.main{flex:1;display:flex;min-height:0}.workspace{flex:1;min-width:0;position:relative}.inspector{width:320px;border-left:1px solid #23262f;background:#14161d;padding:16px;overflow-y:auto;display:flex;flex-direction:column;gap:12px}.inspector h3{margin:0;font-size:13px;text-transform:uppercase;letter-spacing:1px;color:#8b8fa3}.inspector textarea,.inspector input[type=text]{width:100%;background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 10px;outline:none;resize:vertical;font-family:inherit}.inspector textarea:focus,.inspector input:focus{border-color:#6366f1}.inspector .hint{color:#8b8fa3;font-size:12px;line-height:1.5}.inspector .intent{background:#1c1f29;border-radius:6px;padding:6px 10px;font-size:12px;color:#c4b5fd;display:flex;align-items:center;gap:6px}.inspector .intent .intent-x{margin-left:auto;cursor:pointer;color:#8b8fa3;font-weight:700}.inspector .intent .intent-x:hover{color:#f87171}.inspector .btn-row{display:flex;gap:8px}.inspector .btn-row>*{flex:1}.inspector select{background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 10px;outline:none}.hint-inline{color:#8b8fa3;font-size:12px}.inspector .steps{margin:0;padding-left:18px;color:#c7cad4;font-size:13px;line-height:1.7}.inspector kbd{background:#23262f;border-radius:4px;padding:1px 5px;font-size:11px}.empty-state{height:100%;display:flex;align-items:center;justify-content:center}.empty-card{max-width:520px;text-align:center;padding:32px}.empty-logo{font-size:40px;color:#6366f1;margin-bottom:8px}.empty-card h1{margin:0 0 10px;font-size:24px}.empty-card p{color:#9aa0b4;line-height:1.6}.empty-examples{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:18px}.breadcrumb{display:flex;gap:4px;align-items:center;font-size:12px;color:#8b8fa3;margin-left:8px}.breadcrumb .crumb{cursor:pointer;padding:2px 6px;border-radius:4px}.breadcrumb .crumb:hover{background:#23262f;color:#fff}.breadcrumb .crumb.current{color:#a5b4fc;font-weight:600}.crumb-sep{color:#3b3f4d}.wf-block.has-ref:before{content:"๐ผ";position:absolute;top:3px;right:20px;font-size:10px;z-index:2}.page-node header .open-btn{padding:3px 10px;font-size:11px;background:#2c2f3a;color:#c7cad4;opacity:0;transition:opacity .12s}.page-node:hover header .open-btn{opacity:1}.page-node header .open-btn:hover{background:#6366f1;color:#fff}.statusbar{position:fixed;bottom:16px;left:50%;transform:translate(-50%);background:#1c1f29;border:1px solid #6366f1;border-radius:999px;padding:8px 20px;z-index:50;display:flex;gap:10px;align-items:center}.statusbar .spinner{width:14px;height:14px;border:2px solid #6366f1;border-top-color:transparent;border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.errorbar{position:fixed;bottom:16px;left:50%;transform:translate(-50%);background:#2a1420;border:1px solid #e11d48;color:#fda4af;border-radius:8px;padding:8px 16px;z-index:50;max-width:70vw;cursor:pointer}.page-node{width:420px;background:#171a22;border:1px solid #2c2f3a;border-radius:12px;overflow:hidden;box-shadow:0 8px 30px #00000059}.page-node.selected{border-color:#6366f1}.page-node header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#1c1f29;cursor:grab}.page-node header .name{font-weight:600}.page-node header .badge{font-size:11px;padding:2px 8px;border-radius:999px;background:#2c2f3a;color:#8b8fa3}.page-node header .badge.designed{background:#14321f;color:#6ee7a0}.page-node .mini{padding:10px;pointer-events:none}.wf-paper{--fg: var(--wfp-fg, #35507a);--accent: var(--wfp-accent, #4f6ef7);background:var(--wfp-bg, linear-gradient(180deg, #f4f8ff, #e9f0fc));color:var(--fg);border:1px solid color-mix(in srgb,var(--fg) 25%,transparent);border-radius:14px;padding:14px;box-shadow:0 10px 40px #1e40af1f}.wf-block{position:relative;border-radius:10px;padding:10px;display:flex;flex-direction:column;gap:8px;background:color-mix(in srgb,var(--fg) 7%,transparent);border:1.5px solid transparent;min-height:30px}.wf-block.leaf{background:transparent;padding:4px;justify-content:center}.wf-children{display:flex;gap:10px;flex:1;min-width:0}.wf-children>.wf-block,.wf-children>.wf-sortable{flex:1;min-width:0}.wf-block.selected{border-color:#4f6ef7;background:#6366f11f}.wf-block.has-intents:after{content:"โก";position:absolute;top:3px;right:6px;font-size:10px;z-index:2}.wf-tag{position:absolute;top:-8px;left:8px;z-index:2;font-size:9px;font-weight:700;letter-spacing:.4px;background:#4f6ef7;color:#fff;border-radius:4px;padding:1px 6px;opacity:0;transition:opacity .12s;pointer-events:none}.wf-block:hover>.wf-tag,.wf-block.selected>.wf-tag{opacity:1}.wf-block:hover{outline:1px dashed rgba(79,110,247,.5);outline-offset:-1px}.g-line{height:5px;border-radius:3px;background:color-mix(in srgb,var(--fg) 40%,transparent);margin:3px 0}.g-real{font-size:10px;line-height:1.35;color:color-mix(in srgb,var(--fg) 92%,transparent);overflow-wrap:anywhere}.g-real-lg{font-size:13px;font-weight:700}.g-hero-text{font-size:19px;font-weight:800;letter-spacing:-.3px;margin-bottom:8px;color:var(--fg)}.g-text{display:flex;flex-direction:column;justify-content:center}.g-button{width:96px;max-width:70%;height:22px;border-radius:7px;background:var(--accent)}.g-image{width:100%;min-height:64px;flex:1;border-radius:8px;background:color-mix(in srgb,var(--fg) 22%,transparent)}.g-button-labeled{width:auto;padding:0 12px;display:inline-flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:600;white-space:nowrap}.g-nav{display:flex;align-items:center;gap:10px;width:100%;background:color-mix(in srgb,var(--accent) 85%,#1c1c22);border-radius:8px;padding:8px 12px}.g-nav-dot{width:18px;height:18px;border-radius:5px;background:#ffffffd9}.g-nav-links{display:flex;gap:8px;flex:1;justify-content:center}.g-nav-links span{width:34px;height:6px;border-radius:3px;background:#ffffffa6}.g-nav-cta{width:46px;height:16px;border-radius:6px;background:#ffffffe6}.g-hero{width:100%;min-height:110px;border-radius:10px;padding:18px;background:color-mix(in srgb,var(--fg) 10%,transparent);display:flex;flex-direction:column;justify-content:center}.g-hero-title{width:60%;height:16px;border-radius:6px;background:color-mix(in srgb,var(--fg) 45%,transparent);margin-bottom:8px}.g-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%}.g-card{background:color-mix(in srgb,var(--fg) 8%,transparent);border:1px solid color-mix(in srgb,var(--fg) 18%,transparent);border-radius:9px;padding:8px;display:flex;flex-direction:column}.g-card-media{height:34px;border-radius:6px;background:color-mix(in srgb,var(--accent) 35%,transparent);margin-bottom:7px}.g-list{display:flex;flex-direction:column;gap:8px;width:100%}.g-list-row{display:flex;gap:10px;align-items:center;background:color-mix(in srgb,var(--fg) 8%,transparent);border-radius:8px;padding:7px 9px}.g-list-thumb{width:30px;height:30px;border-radius:6px;background:color-mix(in srgb,var(--accent) 40%,transparent);flex:none}.g-form{display:flex;flex-direction:column;gap:8px;width:100%}.g-input{height:22px;border-radius:6px;background:color-mix(in srgb,var(--fg) 6%,transparent);border:1px solid color-mix(in srgb,var(--fg) 25%,transparent)}.g-footer{width:100%;border-radius:8px;padding:12px;background:color-mix(in srgb,var(--accent) 85%,#1c1c22);display:flex;align-items:center;justify-content:space-between;gap:16px}.g-footer .g-line{background:#fff9}.g-footer .g-nav-links{flex:none}.editor-view{height:100%;display:flex;flex-direction:column}.editor-toolbar{display:flex;gap:8px;padding:10px 16px;border-bottom:1px solid #23262f;align-items:center}.editor-scroll{flex:1;overflow:auto;padding:24px;display:flex;justify-content:center}.editor-page{width:760px}.preview-frame{flex:1;border:0;width:100%;background:#fff}.drop-ref{border:1.5px dashed #2c2f3a;border-radius:8px;padding:14px;text-align:center;color:#8b8fa3;cursor:pointer}.drop-ref:hover{border-color:#6366f1}.drop-ref img{max-width:100%;border-radius:6px}.dial{display:flex;flex-direction:column;gap:2px;margin-bottom:6px;font-size:12px;color:#8b8fa3}.dial span{display:flex;justify-content:space-between}.dial em{font-style:normal;color:#c9cbe0}.dial input[type=range]{width:100%;accent-color:#6366f1}.lint{font-size:12px;color:#fbbf24;background:#fbbf2414;border:1px solid rgba(251,191,36,.25);border-radius:6px;padding:6px 8px;margin:4px 0}.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Dreative</title>
|
|
7
|
+
<script type="module" crossorigin src="/assets/index--vztc_MR.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-y0gVjC7u.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dreative",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Layout-first visual editor skill for coding CLIs: extract your app's UI into editable wireframes, tweak with drag-drop + ref images, then the agent applies the diff back to your code.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"dreative": "dist/cli/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"skill"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "npm run build:server && npm run build:ui",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"build:server": "tsc -p tsconfig.json",
|
|
17
|
+
"build:ui": "vite build",
|
|
18
|
+
"dev": "concurrently \"tsx watch src/cli/index.ts --no-open\" \"vite\"",
|
|
19
|
+
"start": "node dist/cli/index.js"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"esbuild": "^0.24.0",
|
|
23
|
+
"express": "^4.21.0",
|
|
24
|
+
"open": "^10.1.0",
|
|
25
|
+
"react": "^18.3.1",
|
|
26
|
+
"react-dom": "^18.3.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@dnd-kit/core": "^6.3.1",
|
|
30
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
31
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
32
|
+
"@types/express": "^4.17.21",
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"@types/react": "^18.3.0",
|
|
35
|
+
"@types/react-dom": "^18.3.0",
|
|
36
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
37
|
+
"@xyflow/react": "^12.3.0",
|
|
38
|
+
"concurrently": "^9.0.0",
|
|
39
|
+
"tsx": "^4.19.0",
|
|
40
|
+
"typescript": "^5.6.0",
|
|
41
|
+
"vite": "^5.4.0",
|
|
42
|
+
"zustand": "^5.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Dreative Design Doctrine
|
|
2
|
+
|
|
3
|
+
You MUST read this file before servicing any `propose-skeletons`, `propose-variants`,
|
|
4
|
+
`design-page`, or `edit-element` request, and run ยง12 before every respond. It exists
|
|
5
|
+
because LLM-designed UIs converge on one templated look. Every rule corrects a known
|
|
6
|
+
model default; none is a suggestion. Requests may carry a `plan` (Dreative's
|
|
7
|
+
pre-computed decision: dials, per-section layout families, budgets, lints) โ execute
|
|
8
|
+
the plan, apply this doctrine to everything the plan doesn't specify. When
|
|
9
|
+
`plan.skills` names specialist skills (`motion`, `3d`, `interaction`), the matching
|
|
10
|
+
`skills/<name>.md` files extend this doctrine for that request โ read them first;
|
|
11
|
+
where they go deeper than a section here, they win.
|
|
12
|
+
|
|
13
|
+
## 1. Register: the first decision
|
|
14
|
+
|
|
15
|
+
Every page is one of two registers. Misclassifying it is the biggest single error.
|
|
16
|
+
|
|
17
|
+
**BRAND** (design IS the product): landing pages, marketing, portfolios, campaign
|
|
18
|
+
pages, about pages, long-form content. Bar = distinctiveness. A visitor should ask
|
|
19
|
+
"how was this made?", not "which AI made this?". Average is no longer findable;
|
|
20
|
+
restraint without intent reads as mediocre. Go big or go home.
|
|
21
|
+
|
|
22
|
+
**PRODUCT** (design SERVES the product): app UI, dashboards, settings, tables, tools,
|
|
23
|
+
authenticated surfaces. Bar = earned familiarity. Would a user fluent in Linear,
|
|
24
|
+
Figma, Notion, Stripe trust this instantly, or pause at every subtly-off component?
|
|
25
|
+
Failure mode is not flatness, it is strangeness without purpose. The tool should
|
|
26
|
+
disappear into the task.
|
|
27
|
+
|
|
28
|
+
Pick by the page's job, not the project. One app can hold both registers.
|
|
29
|
+
|
|
30
|
+
## 2. The design read and the slop tests
|
|
31
|
+
|
|
32
|
+
Before generating, state a one-line read: "<page kind> for <audience>, <vibe>
|
|
33
|
+
language, leaning <aesthetic family>". If the request carries a `brief`, obey it โ
|
|
34
|
+
it is the user's explicit direction.
|
|
35
|
+
|
|
36
|
+
Then run three tests on your intended output; restart if any fails:
|
|
37
|
+
|
|
38
|
+
1. **First-order reflex**: could someone guess your palette + theme from the category
|
|
39
|
+
alone ("cookware โ cream + brass", "devtool โ dark + mono")? That's the
|
|
40
|
+
training-data default. Rework. The three most-shipped default aesthetics: warm
|
|
41
|
+
cream + high-contrast serif + terracotta accent; near-black + acid-green/vermilion;
|
|
42
|
+
broadsheet hairline-rules-and-columns. Where the brief leaves an axis free, never
|
|
43
|
+
spend that freedom on one of these.
|
|
44
|
+
2. **Second-order reflex**: could someone guess it from category + anti-reference
|
|
45
|
+
("fintech that's not navy โ terminal-dark", "SaaS that's not cream โ editorial
|
|
46
|
+
serif + mono labels")? The trap one tier deeper. Rework again.
|
|
47
|
+
3. **Competitor sentence**: describe what you're about to build as a competitor would
|
|
48
|
+
describe theirs. If the sentence fits the modal page in the category, restart.
|
|
49
|
+
|
|
50
|
+
### The working process: commit before code
|
|
51
|
+
|
|
52
|
+
Never design by accretion. Two passes:
|
|
53
|
+
|
|
54
|
+
1. **Commit** โ before any code, write a compact spec: 4-6 named colors (hex/OKLCH),
|
|
55
|
+
2+ type roles with actual font names, a one-sentence layout description per
|
|
56
|
+
section, and ONE **signature element** โ the single memorable move (an
|
|
57
|
+
interaction, a typographic device, a composition) that carries the page's
|
|
58
|
+
distinctiveness. Spend your boldness there; keep everything around it disciplined
|
|
59
|
+
and quiet. Ground choices in the subject's world: its materials, instruments,
|
|
60
|
+
artifacts, and vernacular ("a coffee brand's world: burlap, roast curves,
|
|
61
|
+
thermometers, cupping notes") โ not in web-design tropes.
|
|
62
|
+
2. **Review** โ test the spec against the slop tests below. If any part could apply
|
|
63
|
+
to any similar project, revise that part. Only then build.
|
|
64
|
+
|
|
65
|
+
**Hero thesis:** open with the most characteristic thing in the subject's world โ
|
|
66
|
+
a headline, an image, a live demo, an interactive moment. Whatever form fits.
|
|
67
|
+
|
|
68
|
+
### Aesthetic presets (brief.aesthetic)
|
|
69
|
+
|
|
70
|
+
- `minimal` โ Linear-clean: restrained neutrals, one accent, generous space.
|
|
71
|
+
- `editorial` โ magazine: strong type hierarchy, asymmetric grid, real imagery.
|
|
72
|
+
NOTE: editorial is ONE lane, not the default "tasteful" answer. The
|
|
73
|
+
serif-italic + mono-labels + ruled-columns look is now saturated AI grammar.
|
|
74
|
+
- `premium` โ confident type, rich imagery, refined motion, zero clutter.
|
|
75
|
+
- `playful` โ bold committed color, springy motion, asymmetry, still disciplined.
|
|
76
|
+
- `brutalist` โ raw 1px borders, mono, flat color, radius 0, no shadows/gradients.
|
|
77
|
+
- `dark-tech` โ off-black surfaces, restrained neon, terminal cues used sparingly.
|
|
78
|
+
- `trust` โ public-sector/regulated: symmetric, motion โค2, maximum legibility.
|
|
79
|
+
|
|
80
|
+
### The three dials (1-10, resolved in `plan.dials`)
|
|
81
|
+
|
|
82
|
+
- `variance` โ 1 symmetry โ 10 masonry/offsets/20vw empty zones. >4 forbids the
|
|
83
|
+
centered-hero default. Any asymmetry collapses to clean single-column < 768px.
|
|
84
|
+
- `motion` โ 1 static โ 10 scroll choreography. >3 requires reduced-motion fallbacks.
|
|
85
|
+
- `density` โ 1 art-gallery (py-32+) โ 10 cockpit (hairlines, tabular-nums, no cards).
|
|
86
|
+
|
|
87
|
+
## 3. Typography
|
|
88
|
+
|
|
89
|
+
**Font selection procedure (brand register, never skip):**
|
|
90
|
+
1. Write three physical-object brand-voice words ("warm, mechanical, opinionated" โ
|
|
91
|
+
never "modern" or "elegant").
|
|
92
|
+
2. List the three fonts you'd reach for by reflex. Reject any on the ban list below.
|
|
93
|
+
3. Pick for the brand as a physical object (museum caption, 1970s terminal manual,
|
|
94
|
+
concert poster, mid-century receipt). Reject the first thing that "looks designy".
|
|
95
|
+
4. If the final pick matches the original reflex, start over.
|
|
96
|
+
|
|
97
|
+
**Reflex-reject fonts (training-data defaults, banned as defaults):** Fraunces,
|
|
98
|
+
Newsreader, Lora, Crimson (all), Playfair Display, Cormorant (all), Syne, IBM Plex
|
|
99
|
+
(all), Space Mono, Space Grotesk, Inter, DM Sans/Serif, Outfit, Plus Jakarta Sans,
|
|
100
|
+
Instrument Sans/Serif. Inter/system stacks ARE legitimate in the product register
|
|
101
|
+
and for trust briefs. When an existing app already uses one, identity-preservation
|
|
102
|
+
wins โ keep it.
|
|
103
|
+
|
|
104
|
+
**Serif discipline:** "creative/premium brief = serif" is the most-tested AI tell.
|
|
105
|
+
Default is sans display. Serif only when the brief is genuinely editorial/luxury/
|
|
106
|
+
publication AND you can articulate why this serif fits this brand. Emphasis inside a
|
|
107
|
+
headline = italic/bold of the SAME family, never a serif word dropped into a sans
|
|
108
|
+
headline. Italic display words with descenders (y g j p q) need `leading-[1.1]`+ and
|
|
109
|
+
bottom padding reserve.
|
|
110
|
+
|
|
111
|
+
**Scale โ pick by register:**
|
|
112
|
+
- Brand: fluid `clamp()` headings, ratio โฅ1.25 between steps, clamp max โค 6rem and
|
|
113
|
+
โค 2.5ร its min. Display tracking floor โ0.04em (tighter = letters touch).
|
|
114
|
+
- Product: fixed rem scale, ratio 1.125โ1.2, one family in 3-4 weights is usually
|
|
115
|
+
right. No fluid type in app UI โ no major design system uses it.
|
|
116
|
+
- Both: body โฅ 16px and fixed; 45โ75ch measure (`max-width: 65ch`); headings
|
|
117
|
+
`text-wrap: balance`, prose `text-wrap: pretty`; โค 2-3 families total; never pair
|
|
118
|
+
two similar sans โ contrast on a real axis (serif+sans, geometric+humanist) or use
|
|
119
|
+
one family.
|
|
120
|
+
|
|
121
|
+
**Details that read as craft:** line-height 1.1โ1.2 headings, 1.5โ1.7 body; ALL-CAPS
|
|
122
|
+
labels get `letter-spacing: 0.05โ0.12em`; `tabular-nums` on data columns; vertical
|
|
123
|
+
rhythm = spacing in multiples of the body line-box (16px ร 1.5 โ 24px grid);
|
|
124
|
+
light-on-dark text compensates on three axes: +0.05โ0.1 line-height, +0.01โ0.02em
|
|
125
|
+
tracking, one weight step down (400โ350 effect). `font-display: swap`, preload only
|
|
126
|
+
the critical weight, variable font when using 3+ weights.
|
|
127
|
+
|
|
128
|
+
## 4. Color
|
|
129
|
+
|
|
130
|
+
**Use OKLCH.** `oklch(L C H)` is perceptually uniform. Build ramps by holding
|
|
131
|
+
chroma+hue and varying lightness; reduce chroma near white/black. The hue is a brand
|
|
132
|
+
decision โ never blue-250 or warm-60 by reflex.
|
|
133
|
+
|
|
134
|
+
**Pick a color strategy before picking colors:**
|
|
135
|
+
- **Restrained** โ tinted neutrals + one accent โค10% visual weight. Product floor.
|
|
136
|
+
- **Committed** โ one saturated color carries 30-60% of the surface. Brand default
|
|
137
|
+
for identity-driven pages.
|
|
138
|
+
- **Full palette** โ 3-4 named roles used deliberately. Campaigns, data viz.
|
|
139
|
+
- **Drenched** โ the surface IS the color. Brand heroes.
|
|
140
|
+
|
|
141
|
+
Name a real reference before committing ("Stripe purple-on-white restraint", "Klim
|
|
142
|
+
#ff4500 drench", "Vercel pure-black monochrome"). Unnamed ambition becomes beige.
|
|
143
|
+
On brand surfaces, palette IS voice โ don't hedge a Committed palette with neutral
|
|
144
|
+
edges. On product surfaces, accent = primary action + selection + state, never
|
|
145
|
+
decoration, with a full semantic state vocabulary (hover/focus/active/disabled/
|
|
146
|
+
selected/loading/error/warning/success/info) and a second neutral layer for
|
|
147
|
+
sidebars/panels.
|
|
148
|
+
|
|
149
|
+
**Mechanics:**
|
|
150
|
+
- Tinted neutrals: chroma 0.005โ0.015 toward THIS brand's hue. Pure gray is dead;
|
|
151
|
+
reflex-warm or reflex-cool tinting is the monoculture move.
|
|
152
|
+
- 60-30-10 by visual weight: 60% neutral surface, 30% text/borders, 10% accent.
|
|
153
|
+
Accents work because they are rare.
|
|
154
|
+
- One accent, one neutral family, locked page-wide and project-wide. No blue CTA
|
|
155
|
+
appearing in section 7 of a warm-gray page.
|
|
156
|
+
- Contrast: body 4.5:1 (AAA 7:1 target for hero copy), large text 3:1, UI components
|
|
157
|
+
3:1, placeholders 4.5:1. Gray text on colored backgrounds looks washed out โ use a
|
|
158
|
+
darker shade of the background's own hue or alpha of the text color. Audit every
|
|
159
|
+
CTA and form before responding.
|
|
160
|
+
- No pure #000/#fff. Dark mode is not inverted light mode: depth from a 3-step
|
|
161
|
+
surface-lightness scale (โ15/20/25% L, brand hue, chroma constant), desaturate
|
|
162
|
+
accents slightly, reduce body weight. Redefine only semantic tokens for dark.
|
|
163
|
+
- Heavy alpha usage = incomplete palette. Define explicit overlay colors.
|
|
164
|
+
|
|
165
|
+
**Banned palettes as default reaches:** AI-purple/violet gradients + glow; the
|
|
166
|
+
premium-artisan cream/sand/beige bg (#f5f1ea family, OKLCH L .84-.97 C<.06 hue
|
|
167
|
+
40-100) + brass/clay/oxblood accents + espresso text โ token names like --cream,
|
|
168
|
+
--sand, --bone are tells in themselves. Alternatives to rotate: cold luxury
|
|
169
|
+
(silver/chrome/smoke), forest + bone + amber, true black + tan, cobalt + cream,
|
|
170
|
+
terracotta + slate, olive + brick + paper, monochrome + one saturated pop. "Warmth"
|
|
171
|
+
is carried by accent, type, and imagery โ not by a beige body background.
|
|
172
|
+
Override: a palette is fine when the existing brand or explicit brief names it.
|
|
173
|
+
When redesigning an extracted app, its `theme` colors are the brand โ preserve.
|
|
174
|
+
|
|
175
|
+
## 5. Layout
|
|
176
|
+
|
|
177
|
+
**Hard rules (failing any = broken work):**
|
|
178
|
+
- Hero fits the initial viewport: headline โค 2 lines, subtext โค 20 words, CTA visible
|
|
179
|
+
without scroll, top padding โค pt-24. 4-line headline is a font-size error. Max 4
|
|
180
|
+
text elements (one eyebrow OR brand strip, headline, subtext, CTAs 1+1). Trust
|
|
181
|
+
strips, pricing teasers, feature bullets, avatar rows: all move below the hero.
|
|
182
|
+
- Hero needs a real visual. Text + gradient blob is a placeholder, not a hero.
|
|
183
|
+
- variance > 4 forbids centered-hero-over-gradient: split 50/50, left-content/
|
|
184
|
+
right-asset, or asymmetric whitespace. Centered is fine for manifesto/launch copy.
|
|
185
|
+
- Nav: one line at desktop, height 64โ72px (cap 80px).
|
|
186
|
+
- A layout family appears at most ONCE per page; 8 sections need โฅ 4 families. Max 2
|
|
187
|
+
consecutive image+text zigzags. No 3-identical-cards row, ever โ asymmetric grid,
|
|
188
|
+
2-col, bento, or horizontal scroll instead.
|
|
189
|
+
- Bento: exactly as many cells as content (no filler tiles); 2-3 cells carry real
|
|
190
|
+
visual variation (image/tint/pattern), never all white-on-white text.
|
|
191
|
+
- Cards only when elevation = hierarchy; otherwise border-t/divide-y/whitespace.
|
|
192
|
+
Nested cards are always wrong. Tint shadows to the background hue.
|
|
193
|
+
- Lists > 5 items: group into chunks, 2-col card grid, tabs, or marquee โ never one
|
|
194
|
+
hairline-divided stack, never border-t AND border-b per row.
|
|
195
|
+
- Split-header pattern (big left headline + small floating right paragraph) banned
|
|
196
|
+
as default; stack vertically at 65ch.
|
|
197
|
+
- Grid over flex-math (`grid-cols-3 gap-6`, never `w-[calc(33%-1rem)]`);
|
|
198
|
+
`repeat(auto-fit, minmax(280px, 1fr))` for breakpoint-free card grids;
|
|
199
|
+
`min-h-[100dvh]` never `h-screen`; explicit mobile collapse per section; contain
|
|
200
|
+
at `max-w-7xl mx-auto`; semantic z-index scale, no z-[999].
|
|
201
|
+
- ONE radius system: all-sharp, all-soft (12-16px), or documented mixed rule
|
|
202
|
+
("buttons pill, cards 16, inputs 8"). Cards never above 16px radius.
|
|
203
|
+
- Spacing has rhythm: vary generous separations against tight groupings on a
|
|
204
|
+
consistent base unit; brand surfaces use fluid `clamp()` spacing that breathes.
|
|
205
|
+
- Structure encodes truth, never decoration: numbering, eyebrows, dividers, and
|
|
206
|
+
labels appear only when they say something true about the content (a real
|
|
207
|
+
sequence, a real category). If removing the device loses nothing, remove it.
|
|
208
|
+
- Product register: responsive behavior is structural (collapse sidebar, responsive
|
|
209
|
+
table), not fluid type.
|
|
210
|
+
|
|
211
|
+
## 6. Motion
|
|
212
|
+
|
|
213
|
+
Every animation answers "what does this communicate?" โ hierarchy, storytelling,
|
|
214
|
+
feedback, or state change. "It looked cool" = delete it.
|
|
215
|
+
|
|
216
|
+
**The 100/300/500 rule:** 100-150ms instant feedback (press, toggle) ยท 200-300ms
|
|
217
|
+
state changes (menu, tooltip, hover) ยท 300-500ms layout changes (accordion, modal)
|
|
218
|
+
ยท 500-800ms entrances (hero reveal, brand only). Exits run ~75% of enter duration.
|
|
219
|
+
Feedback over 500ms feels laggy. Micro-interactions target the 80ms "feels instant"
|
|
220
|
+
threshold.
|
|
221
|
+
|
|
222
|
+
**Easing:** ease-out exponential only โ `cubic-bezier(0.25,1,0.5,1)` quart,
|
|
223
|
+
`cubic-bezier(0.22,1,0.36,1)` quint, `cubic-bezier(0.16,1,0.3,1)` expo. Bounce and
|
|
224
|
+
elastic are dated; banned.
|
|
225
|
+
|
|
226
|
+
**Register:** brand = one well-orchestrated hero entrance beats scattered
|
|
227
|
+
micro-interactions; the uniform fade-and-rise on every scrolled section is the
|
|
228
|
+
saturated AI tell. Some brands skip entrance motion entirely โ restraint as voice.
|
|
229
|
+
Product = 150-250ms, state-conveying only, zero page-load choreography.
|
|
230
|
+
|
|
231
|
+
**Mechanics:** animate transform/opacity by default; blur/backdrop-filter/clip-path/
|
|
232
|
+
masks/shadow allowed when they materially improve the effect, bounded to small areas,
|
|
233
|
+
verified smooth. Never casually animate width/height/top/left/margins (use FLIP or
|
|
234
|
+
grid-template-rows). Sibling stagger `calc(var(--i) * 50ms)` capped at ~500ms total.
|
|
235
|
+
IntersectionObserver (unobserve after firing), CSS scroll-driven animations, or
|
|
236
|
+
Motion/GSAP scroll tools โ `window.addEventListener("scroll")` is a hard ban. Reveals
|
|
237
|
+
enhance an already-visible default; never gate content visibility on a JS-triggered
|
|
238
|
+
class (hidden tabs and headless renderers ship blank sections). Max one marquee per
|
|
239
|
+
page. `prefers-reduced-motion: reduce` alternative for everything. Optimistic UI for
|
|
240
|
+
low-stakes actions; never for payments or destructive ops.
|
|
241
|
+
|
|
242
|
+
## 7. Imagery
|
|
243
|
+
|
|
244
|
+
When the brief implies imagery (restaurant, hotel, product, travel, fashion,
|
|
245
|
+
portfolio), zero images is a bug, not restraint. Even a minimalist page needs 2-3
|
|
246
|
+
real images. Priority: (1) image-gen tool if available in your environment, at the
|
|
247
|
+
section's aspect ratio; (2) real photography โ
|
|
248
|
+
`https://picsum.photos/seed/<descriptive-seed>/<w>/<h>` always resolves; Unsplash
|
|
249
|
+
only with verified photo IDs (guessed IDs 404 into broken placeholders); (3)
|
|
250
|
+
clearly-labeled placeholder slots + tell the user what's needed. Search for the
|
|
251
|
+
brand's physical object ("hand-cut pasta on a scratched wooden table"), not the
|
|
252
|
+
category ("Italian food"). One decisive photo beats five mediocre ones. Alt text
|
|
253
|
+
carries voice.
|
|
254
|
+
|
|
255
|
+
Banned: div-built fake screenshots/terminals/dashboards (the #1 AI tell), hand-drawn
|
|
256
|
+
"sketchy" SVG illustrations, `feTurbulence` paper-grain, repeating-gradient stripe
|
|
257
|
+
backgrounds, decorative grid-line overlays, hand-rolled icon paths. Icons from ONE
|
|
258
|
+
library (Phosphor/Radix/Tabler/HugeIcons; Lucide only on request), one strokeWidth
|
|
259
|
+
globally. Logo walls: real SVG marks (`https://cdn.simpleicons.org/<slug>`) or
|
|
260
|
+
generated monograms โ logos only, no category captions, below the hero.
|
|
261
|
+
|
|
262
|
+
## 8. Content and copy
|
|
263
|
+
|
|
264
|
+
โค 8-word section headlines, โค 25-word subtext, one copy register per page, quotes
|
|
265
|
+
โค 3 lines with name + role attribution. No filler verbs (elevate, seamless, unleash,
|
|
266
|
+
revolutionize). No fake-precise numbers unless real or labeled mock; use believable
|
|
267
|
+
messy data ("47.2%", not "99.99%"). No "Jane Doe"/"Acme"/generic avatars โ realistic
|
|
268
|
+
locale-appropriate names, credible invented brands. Re-read every visible string
|
|
269
|
+
before responding; rewrite anything grammatically broken, cutely meta, or
|
|
270
|
+
performative-craftsman ("From the field", "We respect the French ones"). Plain
|
|
271
|
+
beats clever. Data-dump tables on marketing pages โ top 3-5 + "view all".
|
|
272
|
+
|
|
273
|
+
**UX writing:** write from the user's side of the screen โ name things by what
|
|
274
|
+
people control and recognize, never by how the system is built. Active voice ("Save
|
|
275
|
+
changes", not "Submit"). Action names stay consistent through the flow (button
|
|
276
|
+
"Publish" โ toast "Published"). Errors and empty states are direction, not mood:
|
|
277
|
+
say what happened and what to do next; never apologize vaguely. Sentence case,
|
|
278
|
+
plain verbs, no filler.
|
|
279
|
+
|
|
280
|
+
## 9. States and interaction (product floor)
|
|
281
|
+
|
|
282
|
+
Every interactive component ships default/hover/focus/active/disabled/loading/error.
|
|
283
|
+
Skeletons shaped like the final layout, not centered spinners. Empty states teach
|
|
284
|
+
the interface. Errors inline for forms, toasts only for transient events. Labels
|
|
285
|
+
above inputs; placeholder-as-label never; helper text present. `:active` gives
|
|
286
|
+
tactile press (`scale-[0.98]`). Same button shape, form vocabulary, and icon style
|
|
287
|
+
on every screen โ if "save" looks different in two places, one is wrong. Modals are
|
|
288
|
+
usually laziness; exhaust inline/progressive first. Dropdowns escape
|
|
289
|
+
overflow-hidden ancestors via popover API/position-fixed/portal. Touch targets
|
|
290
|
+
โฅ 44px. Never disable zoom.
|
|
291
|
+
|
|
292
|
+
## 10. Banned AI tells (match-and-refuse)
|
|
293
|
+
|
|
294
|
+
- **Em-dash (โ) and en-dash separators (โ): zero anywhere visible.** Periods,
|
|
295
|
+
commas, colons, plain hyphens.
|
|
296
|
+
- Eyebrow kickers (small caps tracked labels above headings) on every section โ max
|
|
297
|
+
1 per 3 sections, and only as a deliberate system. Numbered section markers
|
|
298
|
+
(`01 ยท About`) unless the content is a real sequence.
|
|
299
|
+
- Side-stripe borders (border-left > 1px as accent) โ full hairline border, 4-8%
|
|
300
|
+
background tint, or leading glyph instead.
|
|
301
|
+
- Gradient text (background-clip). Glassmorphism as default. Hero-metric template
|
|
302
|
+
(big number + label + gradient accent). Identical icon+heading+text card grids.
|
|
303
|
+
- 1px border + soft โฅ16px drop shadow on the same element ("ghost card") โ pick one.
|
|
304
|
+
- Hero version labels (BETA, V0.6), scroll cues ("โ scroll to explore"),
|
|
305
|
+
locale/weather strips, decoration strips (`DESIGN ยท BUILD ยท SHIP`), vertical
|
|
306
|
+
rotated text, custom cursors, decorative status dots, pills overlaid on photos,
|
|
307
|
+
fake photo credits, version footers on marketing pages, "Quietly trusted by".
|
|
308
|
+
- Duplicate CTA intent: one label per intent per page ("Get in touch" + "Let's
|
|
309
|
+
talk" = fail). CTA labels never wrap at desktop; 1-3 words.
|
|
310
|
+
- Middle-dot separators rationed to 1 per line. Never hover-scale on `<img>`
|
|
311
|
+
elements (animate the card's border/background/shadow instead).
|
|
312
|
+
- Headline text that overflows its container at any breakpoint โ test the actual
|
|
313
|
+
copy; the viewport is part of the design.
|
|
314
|
+
|
|
315
|
+
## 11. Redesign and preservation (extracted apps)
|
|
316
|
+
|
|
317
|
+
Dreative pages usually come FROM a real app. Detect the mode: preserve (evolve the
|
|
318
|
+
existing brand) vs overhaul (new language, same content/IA). When preserving: keep
|
|
319
|
+
route slugs, nav labels, form field names, logo, legal copy; extract brand tokens
|
|
320
|
+
before applying ยง4 (a purple brand stays purple); apply modernisation levers in
|
|
321
|
+
order โ typography โ spacing/rhythm โ color recalibration โ motion layer โ hero
|
|
322
|
+
recomposition โ full replacement only when unsalvageable. Honor existing
|
|
323
|
+
accessibility wins and analytics hooks. Preserve prior element-level edits when
|
|
324
|
+
`previousFile` is set.
|
|
325
|
+
|
|
326
|
+
## 12. Pre-flight checklist (run before EVERY respond)
|
|
327
|
+
|
|
328
|
+
Mentally verify; fix failures, then respond. If a box cannot be honestly ticked,
|
|
329
|
+
the output is not done.
|
|
330
|
+
|
|
331
|
+
0. Commit pass done: named palette, named fonts, one signature element, subject-
|
|
332
|
+
grounded. The quality floor (responsive to mobile, visible keyboard focus,
|
|
333
|
+
reduced motion) is built silently โ never announced in copy or comments.
|
|
334
|
+
1. Register named (brand/product); design read stated; brief and plan obeyed.
|
|
335
|
+
2. All three slop tests pass (first-order, second-order, competitor sentence).
|
|
336
|
+
3. Zero em/en-dashes visible. Zero banned tells from ยง10.
|
|
337
|
+
4. One accent + one tinted-neutral family + one theme + one radius system + one
|
|
338
|
+
icon family, locked page-wide; matches sibling pages of this project.
|
|
339
|
+
5. Fonts: not on the reflex-reject list (or justified by existing brand); scale
|
|
340
|
+
ratio committed; body โฅ16px at 45-75ch; caps tracked; data tabular.
|
|
341
|
+
6. Every CTA/form/placeholder passes WCAG AA; no CTA wraps; no duplicate CTA intent.
|
|
342
|
+
7. Hero: โค2-line headline, โค20-word subtext, โค4 elements, real visual, CTA above
|
|
343
|
+
fold; centered only if variance โค 4 or manifesto brief.
|
|
344
|
+
8. Eyebrows โค ceil(sections/3); no two sections share a layout family; โค2
|
|
345
|
+
consecutive zigzags; no 3-identical-cards; bento cells = content count.
|
|
346
|
+
9. Real images or labeled slots; no div fake-screenshots; no sketchy SVG; logos are
|
|
347
|
+
real marks.
|
|
348
|
+
10. Motion: each animation justified in one sentence; durations per 100/300/500;
|
|
349
|
+
ease-out curves; exits faster; reduced-motion safe; content visible without JS;
|
|
350
|
+
โค1 marquee; no scroll-listener.
|
|
351
|
+
11. States complete (loading/empty/error/disabled); labels above inputs; tactile
|
|
352
|
+
:active.
|
|
353
|
+
12. Mobile collapse explicit; 100dvh; no text overflow at any breakpoint; semantic
|
|
354
|
+
z-index.
|
|
355
|
+
13. Copy self-audit done: no broken/AI-cute strings, realistic data, one register.
|
|
356
|
+
14. Every block id from the layout appears as `data-dreative-id` (design-page only).
|
|
357
|
+
15. Dark mode (when in scope): semantic-token swap, surface-lightness depth,
|
|
358
|
+
desaturated accents, tested both modes.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dreative
|
|
3
|
+
description: Frontend design skill + optional visual round-trip editor. Use for ANY frontend design work โ redesign/restyle/build pages, landing pages, animations, motion, 3D, micro-interactions, "make my UI look good" โ and for visual editing when the user says "open dreative" or "let me edit the layout visually". Default is direct design: apply the design doctrine straight to the codebase. The browser editor (extract โ wireframes โ edit โ apply diff) is an optional mode the user can ask for.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dreative โ frontend design skill (+ optional visual editor)
|
|
7
|
+
|
|
8
|
+
You (the coding agent) are the intelligence. Dreative has **two modes**:
|
|
9
|
+
|
|
10
|
+
- **Mode A โ Direct design (default).** The user asks you to design, redesign, restyle, animate, or build UI. Read `DESIGN.md` (and any specialist `skills/<name>.md` the work calls for โ motion, 3d, interaction), then design/edit the real code directly. No server, no extraction, no wireframes. When you finish, add one closing note: *"Tip: run `dreative start` / say 'open dreative' if you want to tweak this visually โ I'll extract the pages into an editable canvas."* That's the only place the editor should come up; never force the round-trip on a plain design request.
|
|
11
|
+
- **Mode B โ Visual round-trip (only when asked).** The user explicitly wants the visual editor ("open dreative", "let me edit visually"). Flow: **extract โ baseline โ serve requests โ finish โ apply**. Be token-frugal at every step: read only the files you need, never re-read the whole app, and keep JSON compact.
|
|
12
|
+
|
|
13
|
+
Everything below ยง0 describes Mode B; the design doctrine paragraphs apply to both modes.
|
|
14
|
+
|
|
15
|
+
**Design quality is a hard requirement.** `DESIGN.md` (same folder as this file) is the design doctrine. Read it ONCE before servicing the first `propose-skeletons`, `propose-variants`, `design-page`, or `edit-element` request, keep it in mind for all later ones, and run its pre-flight checklist (ยง12) before every respond. Requests may carry a `brief` object (aesthetic preset + vibe + dials set by the user in the UI); when present it is the user's explicit direction and overrides doctrine defaults. Before writing any `design-page` code, state (to yourself, one line) the register, the design read, and the signature element โ if you cannot name all three, you are about to produce the generic default; stop and commit first.
|
|
16
|
+
|
|
17
|
+
**Specialist skills.** The `skills/` folder next to this file holds expert playbooks for advanced work: `motion.md` (animation & scroll choreography), `3d.md` (WebGL/three.js/shaders), `interaction.md` (micro-interactions & effect craft). When a request's `plan.skills` lists names, read each listed `skills/<name>.md` ONCE before writing code (then keep it in mind, like DESIGN.md); when `plan.sections[].skills` tags a section, that section gets that treatment (e.g. "this hero has 3d"). If the brief/prompt clearly calls for one of these but the plan missed it, read it anyway. If a listed file isn't installed, proceed on DESIGN.md alone and note it to the user (`dreative install-skill` installs all).
|
|
18
|
+
|
|
19
|
+
## 0. Setup
|
|
20
|
+
|
|
21
|
+
Requires `dreative` on PATH (`npm i -g dreative` or `npx dreative`). All commands run from the user's project root. State lives in `.dreative/` (paths in payloads are relative to `.dreative/`).
|
|
22
|
+
|
|
23
|
+
## 1. Extract (code โ layout + replica)
|
|
24
|
+
|
|
25
|
+
Goal: replicate the app's current UI **view-by-view** so the user recognizes every screen. Do this **one page at a time** โ find the routes/pages first (router config, pages/ dir, app/ dir), then open only each page's component files. **Single pass per page:** while the source is in front of you, produce all three outputs at once (layout JSON, replica file, summaries) โ never revisit a file for a second output.
|
|
26
|
+
|
|
27
|
+
**One Dreative page per VIEW, not per route file.** If a route renders mutually-exclusive views โ tab panels, admin vs viewer modes, auth states, wizard steps, a modal that fills the screen โ each view becomes its own Dreative page. A page's layout must show exactly what the user sees at one moment; never stack multiple tab panels' content into one layout. Name split views `"<Screen> โ <View>"` (e.g. "Admin Studio โ Library", "Admin Studio โ Ranking Board"), give them the same `source`, the same `group` (e.g. `"group": "Admin Studio"`), and cluster them on the canvas. Shared chrome (header, tab bar) repeats in each view's layout, with the active tab noted in its `text`.
|
|
28
|
+
|
|
29
|
+
**Expose hidden UI.** UI that exists but isn't visible by default must still surface, or the user gets a wrong picture of their app:
|
|
30
|
+
- *Full-screen or view-sized* hidden UI (modals, dialogs, drawers, overlay panels with real content) โ its own Dreative page, grouped with its parent screen (e.g. "Library โ Edit Show modal").
|
|
31
|
+
- *Small* hidden UI (dropdown menus, tooltips-with-actions, hover-revealed buttons, expandable rows) โ model it as a block **inside its trigger's parent**, labeled for what it is (e.g. label "Sort dropdown (opens on click)"), with a `summary` saying when it appears. Don't invent open-state visuals in the replica โ the replica shows the default state; the layout is where hidden things are enumerated.
|
|
32
|
+
|
|
33
|
+
**Fidelity is the whole point.** The wireframe and replica must be recognizable as *that* page at a glance. Model every visible major section in order โ hero/banner, search+filter bars, stat/KPI rows, each shelf/carousel with its cards, footers. A real page with 8 visible sections must yield ~8 top-level children, not 3 generic boxes. Card grids get realistic counts (a shelf showing 7 posters โ a card-grid the user reads as a row of posters, with real show titles in `text`). Before moving on, self-check: *would the user, seeing only this wireframe, name which page of their app it is?* If not, you under-extracted โ fix it before the next page.
|
|
34
|
+
|
|
35
|
+
Per page, produce:
|
|
36
|
+
|
|
37
|
+
1. **Layout** โ the block tree in `project.json` (schema below).
|
|
38
|
+
2. **Replica** โ `.dreative/replica/<pageId>.tsx`: a stripped, non-functional **1:1 visual copy** of the real page. Single file, default export, no imports beyond react, Tailwind classes (translate other styling to Tailwind or inline styles). Strip everything behavioral: no handlers, no hooks, no data fetching; replace dynamic state/props with representative literal values (the ones a real user would see). It only needs to LOOK identical, not work. Every block id from the layout appears as `data-dreative-id="<id>"` on the matching element. Set `replicaFile` on the page.
|
|
39
|
+
3. **Summaries** โ on each meaningful block, `summary`: one plain line of what it shows or does ("Submits the signup form and redirects to /dashboard", "Lists the 6 most recent orders from the API"). These render as hover tooltips in the replica so the user understands behavior without you re-reading code later, and they are your own re-entry notes at apply time. Keep each under ~120 chars.
|
|
40
|
+
|
|
41
|
+
Write `.dreative/project.json`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{ "version": 1, "brief": { "aesthetic": "minimal", "vibe": "", "audience": "", "variance": 7, "motion": 5, "density": 4, "notes": "" }, "pages": [ {
|
|
45
|
+
"id": "pg_home", "name": "Home", "canvasPos": {"x": 40, "y": 40},
|
|
46
|
+
"theme": { "bg": "#0d0d0f", "fg": "#e8e8ea", "accent": "#f59e0b" },
|
|
47
|
+
"status": "skeleton", "source": "src/pages/Home.tsx",
|
|
48
|
+
"layout": { "id": "blk_root", "type": "section", "label": "Home", "direction": "column", "children": [ โฆ ] }
|
|
49
|
+
} ] }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
(page objects also take `"replicaFile": "replica/pg_home.tsx"` and `"group": "Admin Studio"` for split views of one screen)
|
|
53
|
+
|
|
54
|
+
Block: `{ id, type, label, text?, summary?, direction?, sizeHint?, source?, children? }`
|
|
55
|
+
- `type`: section | row | column | nav | hero | card-grid | list | form | footer | text | image | button
|
|
56
|
+
- `label`: short recognizable name (shown on hover/inspector).
|
|
57
|
+
- `text`: the **actual visible copy** (heading text, button caption, first ~80 chars of a paragraph) โ set it on every text/button/hero leaf; it renders verbatim in the wireframe so the user recognizes the page.
|
|
58
|
+
- Page `theme` `{bg, fg, accent}`: pull the real CSS colors (page background, main text color, brand accent) so the wireframe card matches the app's look. Set it on every page.
|
|
59
|
+
- `source`: the real file that owns this block (component path). Set it on every block whose owner differs from its parent's โ this is what lets you apply the diff later without re-searching.
|
|
60
|
+
- Keep depth sensible (3โ5 levels); every meaningful visible element should exist, but don't model every span.
|
|
61
|
+
- Ids must be unique and stable; prefix `pg_`/`blk_` plus a slug.
|
|
62
|
+
- Space pages on the canvas: x += 480 per page.
|
|
63
|
+
- Top-level `brief` is optional at extraction time (the user edits it in the UI); if the app has an obvious existing aesthetic, seed it so redesigns preserve the brand.
|
|
64
|
+
|
|
65
|
+
Then snapshot the baseline: `dreative baseline` (start the server first, step 2, if not running).
|
|
66
|
+
|
|
67
|
+
## 2. Launch
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
dreative start # serves http://localhost:4820, opens browser (background this)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Tell the user the UI is open: they can view the **Replica** tab (1:1 copy of their real page, hover shows your summaries), drag elements in **Layout**, add/remove blocks, set the **Design brief** (preset + dials), attach reference images and prompts, hit **๐จ Design all**, and click **Finish** when done.
|
|
74
|
+
|
|
75
|
+
## 3. Service requests (the wait loop)
|
|
76
|
+
|
|
77
|
+
Repeat until finish:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
dreative wait # blocks up to ~8 min; prints ONE event as JSON
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `{"kind":"none"}` โ just run `dreative wait` again.
|
|
84
|
+
- `{"kind":"request","id","type","payload"}` โ handle per table below, then
|
|
85
|
+
`dreative respond <id> <resultFile>` (write the result JSON to a temp file) or `dreative respond <id> --error "why"`.
|
|
86
|
+
- `{"kind":"finish","diff":โฆ}` โ go to step 4.
|
|
87
|
+
|
|
88
|
+
| type | payload | result to respond with |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `propose-skeletons` | `{prompt, brief?}` | Array of 1โ3 `{name, layout}` page proposals (block schema above), structured per DESIGN.md layout rules |
|
|
91
|
+
| `propose-variants` | `{pageName, layout, brief?}` | Array of 1โ3 `{name, layout}` variants |
|
|
92
|
+
| `edit-block` | `{block, instruction}` | The updated block JSON (same id) |
|
|
93
|
+
| `design-page` | `{pageName, layout, brief?, plan?, refImage?, blockRefs, designPrompt?, previousFile?, siblingPages, outFile}` | Write a single-file React+Tailwind component (default export, no imports beyond react) to `.dreative/<outFile>`; every block id in layout must appear as `data-dreative-id="<id>"`. **`plan` is Dreative's pre-computed design decision โ execute it, don't re-decide:** it carries resolved dials, a layout family per section (`plan.sections`, sections may carry `skills` tags like `["3d"]`), spacing/motion budgets (`plan.directives`), doctrine violations to fix (`plan.lints`), and required specialist skills (`plan.skills` โ read `skills/<name>.md` first). DESIGN.md still governs everything the plan doesn't specify. Read `refImage`/`blockRefs[].refImage` (paths under `.dreative/`) with your image tools; if `previousFile` set, read it and preserve prior element edits. Respond `{"ok":true}` |
|
|
94
|
+
| `edit-element` | `{file, elementId, instruction, refImage?}` | Edit `.dreative/<file>` in place, only the element with `data-dreative-id=elementId`, keeping DESIGN.md rules intact. Respond `{"ok":true}` |
|
|
95
|
+
|
|
96
|
+
A "Design all pages" click in the UI arrives as one `design-page` request per page, back to back: keep visual consistency across them (same accent, type scale, radius system โ the first page you design sets the system for the rest).
|
|
97
|
+
|
|
98
|
+
Token rules: only read ref images when a request names them; never dump whole files into responses; for edits, edit files directly instead of returning code.
|
|
99
|
+
|
|
100
|
+
## 4. Apply (finish)
|
|
101
|
+
|
|
102
|
+
The finish event's `diff` (also saved at `.dreative/finish.json`) contains only what changed vs the baseline:
|
|
103
|
+
|
|
104
|
+
- `pagesAdded` โ full layouts; create real pages/components for them.
|
|
105
|
+
- `pagesRemoved` โ confirm with the user before deleting real code.
|
|
106
|
+
- `pagesChanged` โ per page: `blocksMoved` (reorder in the source), `blocksAdded`, `blocksRemoved`, `blocksChanged` (only differing props listed; `refImage` = style reference to match, `intents` = behavior notes), plus page-level `refImage`/`designPrompt`.
|
|
107
|
+
|
|
108
|
+
Use each block's/page's `source` pointer to open **only the owning files**, and each block's `summary` to recall what an element does **without re-reading unrelated code**. Read annotated ref images now (paths relative to `.dreative/`). Make the real code match the final layout and annotations, run the project's checks, and summarize what you changed.
|