Three independently ugly bugs that all fed the same log flood:
* Electron's `WebFrameMain.send` writes every "Render frame was disposed"
to stderr via `console.error`. When the worker fans a second
agent-event past a reloading renderer, we produced thousands of
identical lines and stalled the main loop on stderr I/O. Added a
`mainFrame.detached` guard so the send is short-circuited before
Electron's own catch block fires, and installed a targeted filter in
`suppress-warnings.ts` (now actually imported from the entry point)
so the specific `console.error("Error sending from webFrameMain:"…)`
noise never reaches the terminal. Any other payload still surfaces.
* `dispatchAgentMessage` accepted the human-reader sentinel as a wake
target when an agent replied to `__board__` — `wakeAgentIfPossible`
then called `db.getAgent("__board__")`, threw, and the dispatcher
kept repeating on every send. Strip `HUMAN_SENDER_ID` at
`resolveMessageWakeTargets`, and keep a defense-in-depth guard in the
heartbeat so a stray caller (future automation fan-out) cannot
reintroduce the crash.
* Pi's skills loader rejects any SKILL.md whose frontmatter `name`
diverges from its parent directory. The four bundled `my-writing-style`
copies declared `name: writing-style-skill`, so every install emitted
a warning and dropped the skill. They also lived as orphan gitlinks
(mode 160000 without .gitmodules), and the global `*.md` gitignore
hid every other SKILL.md from version control. Fixed the frontmatter
to match the dir, converted the dangling submodules to plain trees,
and allowlisted `builtin-skills/**/*.md` so a fresh clone carries the
catalogue instead of silently losing it.
8.4 KiB
8.4 KiB
Generation Guide
How to use a completed Design DNA JSON to generate designs in Phase 3. Covers all three dimensions.
Priority Order
When generating a design from DNA JSON + content:
- Color & Typography — define 80% of visual identity
- Spacing & Layout — structural rhythm
- Shape & Elevation — surface treatment
- Design Style qualitative fields — mood, personality, composition approach
- Visual Effects — special rendering layer (Canvas, WebGL, shaders, etc.)
- Motion & Interaction — enhance after static layout and effects are solid
Dimension 1: design_system → Code
Tailwind CSS / Utility-First
color.primary.hex → --color-primary / bg-[hex]
typography.font_families → font-family config
spacing.scale → spacing config values
shape.border_radius → rounded-{sm|md|lg|full}
elevation.levels → shadow-{sm|md|lg}
Plain CSS / CSS Variables
Generate a :root block with all design tokens:
:root {
--color-primary: {color.primary.hex};
--color-secondary: {color.secondary.hex};
--color-accent: {color.accent.hex};
--font-heading: {typography.font_families.heading};
--font-body: {typography.font_families.body};
--radius-sm: {shape.border_radius.small};
--radius-md: {shape.border_radius.medium};
--radius-lg: {shape.border_radius.large};
--shadow-low: {elevation.levels.low};
--shadow-med: {elevation.levels.medium};
--shadow-high: {elevation.levels.high};
--ease: {motion.easing};
--duration-micro: {motion.duration_scale.micro};
--duration-normal: {motion.duration_scale.normal};
--duration-macro: {motion.duration_scale.macro};
/* ... map all tokens */
}
Component Decisions
components.button_style→ button classes and variantscomponents.card_style→ card container treatmentcomponents.navigation_pattern→ nav component choiceinteraction_feel.hover_behavior→ :hover / :focus statesmotion.easing+motion.duration_scale→ transition properties
Dimension 2: design_style → Subjective Decisions
| DNA Field | Guides |
|---|---|
| aesthetic.mood | Overall emotional feeling — warm tones, cool precision, etc. |
| visual_language.whitespace_usage | padding/margin generosity |
| visual_language.contrast_level | How much elements pop vs. blend |
| composition.hierarchy_method | What tool to use for emphasis |
| composition.balance_type | Symmetric layout vs. dynamic asymmetry |
| imagery.graphic_elements | Decorative SVGs, gradients, patterns |
| brand_voice_in_ui.tone | Microcopy phrasing |
| interaction_feel.microinteraction_density | How many hover/click effects |
Dimension 3: visual_effects → Special Rendering
Technology Selection by Performance Tier
| Tier | Technologies | When to Use |
|---|---|---|
| lightweight | CSS animations, SVG SMIL, vanilla JS | overview.performance_tier = "lightweight" |
| medium | Canvas 2D, GSAP, Lottie, anime.js | overview.performance_tier = "medium" |
| heavy | Three.js, custom GLSL, Pixi.js, WebGL | overview.performance_tier = "heavy" |
Implementation Patterns
Background Effects
"none" → skip
"gradient-animation" → CSS @keyframes on linear-gradient or conic-gradient
"noise-field" → Canvas 2D with Perlin/simplex noise
"mesh-gradient" → SVG <mesh> or canvas interpolation
"video-bg" → <video autoplay muted loop> with poster fallback
"generative-art" → Canvas 2D or WebGL generative algorithms
Particle Systems
When particle_systems.enabled: true:
- For
count< 100 and no complex physics → vanilla JS + Canvas 2D - For
count>= 100 or complex interaction → consider Pixi.js or Three.js Points - Map
interaction("mouse-repel", "mouse-attract") to pointer event handlers - Use
requestAnimationFrameloop; include destroy/cleanup on unmount
3D Elements
When 3d_elements.enabled: true:
- Default to Three.js unless DNA specifies otherwise
- Apply
lighting,camera,materialsfrom params - Add
post_processingeffects via EffectComposer - Handle resize with
ResizeObserver - Load via CDN:
https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js
Shader Effects
When shader_effects.enabled: true:
- Create vertex/fragment shaders based on
type - Pass
uniformsfrom params (time, resolution, mouse position) - For "noise-distortion": use noise functions matching
noise_type - Animate via
requestAnimationFrameupdatingu_timeuniform
Scroll Effects
- Parallax: Use
transform: translateY()with scroll offset × layer speed - Scroll-triggered: Use
IntersectionObserverwiththresholdarray - Scrub behavior: If "scrubbed", animation progress = scroll progress. If "triggered", play once on enter.
Text Effects
"split-letter-animate" → Split text into <span> per char/word, stagger CSS animation
"typewriter" → CSS steps() or JS interval revealing chars
"glitch" → Layered clip-path + color offset animation
"gradient-fill" → background-clip: text with animated gradient
"3d-extrude" → text-shadow stack or WebGL text geometry
Cursor Effects
When cursor_effects.enabled: true:
- Hide default cursor:
cursor: none - Create custom cursor element following
pointermove - "magnetic-buttons": Apply transform pull on hover proximity
- "spotlight": Radial gradient mask following cursor
- "trail": Spawn fading elements on move
Glassmorphism / Neumorphism
"glass" → backdrop-filter: blur({blur_radius}); background: rgba(..., {transparency})
"neumorphic-light" → Dual box-shadow (light + dark offset) on light bg
"neumorphic-dark" → Dual box-shadow (inverted) on dark bg
"frosted-layers" → Stacked blur layers with varying opacity
Canvas Drawings
When canvas_drawings.enabled: true:
- Initialize canvas with
width/heightmatching container - Use
draw_methodto select rendering approach - Animate with
requestAnimationFrame - Handle
responsivenessvia ResizeObserver
SVG Animations
When svg_animations.enabled: true:
- "path-draw": Animate
stroke-dashoffsetfrom path length to 0 - "morph-shapes": Interpolate
dattribute between two paths - "stroke-animation": Animate stroke properties (dasharray, width, color)
Fallback Strategy
Always implement the fallback defined in overview.fallback_strategy:
// Example: reduce to CSS on low-end devices
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const isLowEnd = navigator.hardwareConcurrency <= 2;
if (prefersReduced || isLowEnd) {
// Apply fallback: static CSS version, disable canvas/WebGL
}
Output Format
Generate output as a single self-contained HTML file with inline CSS and JS (unless user specifies a framework). Include:
- CSS custom properties block from
design_systemtokens - Component styles from
design_system.components+design_style - Layout structure per
design_system.layout - Content populated from user-provided content
- Visual effects implemented per
visual_effectsspecification - Animations/transitions if
design_system.motion.philosophyis not "none" - Fallback handling for effects
For heavy effects requiring external libraries, load via CDN <script> tags:
<!-- Three.js -->
<script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js"}}</script>
<!-- GSAP -->
<script src="https://cdn.jsdelivr.net/npm/gsap@latest/dist/gsap.min.js"></script>
<!-- Lottie -->
<script src="https://cdn.jsdelivr.net/npm/lottie-web@latest/build/player/lottie.min.js"></script>
Quality Checks
Before delivering, verify:
- Every color in output traces back to DNA palette
- Font families match DNA specification
- Spacing rhythm matches DNA scale
- Border radius matches DNA shape tokens
- Overall mood matches
design_style.aesthetic.mood - Component patterns match DNA
componentsdescriptions - Contrast ratios meet WCAG AA minimum (4.5:1 body text, 3:1 large text)
- Visual effects match
visual_effectsspecification (type, technology, params) - Fallback strategy is implemented for effects
prefers-reduced-motionis respected- No effects render when their
enabledflag isfalse - Canvas/WebGL contexts are properly sized and handle resize
- Animation loops use
requestAnimationFrame(nosetInterval)