picasso-skill 1.0.0 → 1.2.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.
@@ -12,47 +12,174 @@
12
12
  ### Why Sound
13
13
  Sound provides confirmation that an action occurred, draws attention to important state changes, and adds personality to the interface. It is underused on the web but highly effective when applied with restraint.
14
14
 
15
- ### The Soundcn Pattern
16
- Use inline base64 audio data URIs with the Web Audio API. This avoids external file loading, CORS issues, and runtime fetching. Each sound is a self-contained TypeScript module.
15
+ ### Sourcing Sounds
16
+ - **Kenney.nl** -- free CC0 game/UI sound packs. High quality, no attribution required.
17
+ - **Freesound.org** -- filter by CC0 license for attribution-free use. Verify license on each clip.
18
+ - **Tone.js synthesis** -- generate procedural sounds at runtime. No files to load. Good for simple tones, chimes, and click sounds. Use `Tone.Synth`, `Tone.MembraneSynth`, or `Tone.NoiseSynth` for UI feedback.
19
+ - **Self-recorded** -- record short foley sounds and export as WAV/MP3 at 44.1kHz mono.
20
+
21
+ For inline embedding, convert sounds to base64 data URIs to avoid CORS issues and runtime fetching. Each sound becomes a self-contained TypeScript module.
17
22
 
18
23
  ```typescript
19
24
  // sounds/click-soft.ts
20
- export const clickSoftSound = "data:audio/wav;base64,UklGR..."; // base64 WAV
25
+ export const clickSoftSound = "data:audio/wav;base64,UklGR...";
26
+ ```
27
+
28
+ ### The useSound Hook (Production-Ready)
21
29
 
30
+ This hook handles AudioContext lifecycle (including the browser autoplay policy that blocks AudioContext until a user gesture), caches decoded buffers so each sound is fetched and decoded only once, and exposes volume control via a GainNode.
31
+
32
+ ```typescript
22
33
  // hooks/use-sound.ts
23
- import { useCallback, useRef } from 'react';
34
+ import { useCallback, useEffect, useRef } from "react";
24
35
 
25
- export function useSound(src: string) {
26
- const audioContextRef = useRef<AudioContext | null>(null);
36
+ // Shared AudioContext singleton -- one per page avoids resource waste.
37
+ let sharedCtx: AudioContext | null = null;
38
+ const bufferCache = new Map<string, AudioBuffer>();
27
39
 
28
- const play = useCallback(() => {
29
- if (!audioContextRef.current) {
30
- audioContextRef.current = new AudioContext();
40
+ function getAudioContext(): AudioContext {
41
+ if (!sharedCtx) {
42
+ sharedCtx = new AudioContext();
43
+ }
44
+ return sharedCtx;
45
+ }
46
+
47
+ // Resume AudioContext on first user gesture (required by Chrome, Safari, Firefox).
48
+ // Call this once at app root.
49
+ export function initAudioOnGesture(): void {
50
+ const resume = () => {
51
+ const ctx = getAudioContext();
52
+ if (ctx.state === "suspended") {
53
+ ctx.resume();
31
54
  }
32
- const ctx = audioContextRef.current;
33
- fetch(src)
34
- .then(r => r.arrayBuffer())
35
- .then(buf => ctx.decodeAudioData(buf))
36
- .then(decoded => {
37
- const source = ctx.createBufferSource();
38
- source.buffer = decoded;
39
- source.connect(ctx.destination);
40
- source.start(0);
41
- });
42
- }, [src]);
43
-
44
- return [play] as const;
55
+ };
56
+ const events = ["click", "touchstart", "keydown"] as const;
57
+ events.forEach((e) => document.addEventListener(e, resume, { once: false }));
45
58
  }
59
+
60
+ interface UseSoundOptions {
61
+ volume?: number; // 0 to 1, default 0.4
62
+ /** For sound sprites: start offset in seconds */
63
+ offset?: number;
64
+ /** For sound sprites: duration in seconds */
65
+ duration?: number;
66
+ }
67
+
68
+ export function useSound(src: string, options: UseSoundOptions = {}) {
69
+ const { volume = 0.4, offset, duration } = options;
70
+ const gainRef = useRef<GainNode | null>(null);
71
+
72
+ const play = useCallback(async () => {
73
+ const ctx = getAudioContext();
74
+
75
+ // Resume if suspended (covers edge cases where gesture init missed)
76
+ if (ctx.state === "suspended") {
77
+ await ctx.resume();
78
+ }
79
+
80
+ // Fetch + decode only on first play, then cache
81
+ let buffer = bufferCache.get(src);
82
+ if (!buffer) {
83
+ const response = await fetch(src);
84
+ const arrayBuf = await response.arrayBuffer();
85
+ buffer = await ctx.decodeAudioData(arrayBuf);
86
+ bufferCache.set(src, buffer);
87
+ }
88
+
89
+ // GainNode for volume control
90
+ const gain = ctx.createGain();
91
+ gain.gain.value = volume;
92
+ gain.connect(ctx.destination);
93
+ gainRef.current = gain;
94
+
95
+ const source = ctx.createBufferSource();
96
+ source.buffer = buffer;
97
+ source.connect(gain);
98
+
99
+ if (offset !== undefined && duration !== undefined) {
100
+ source.start(0, offset, duration);
101
+ } else {
102
+ source.start(0);
103
+ }
104
+ }, [src, volume, offset, duration]);
105
+
106
+ const setVolume = useCallback(
107
+ (v: number) => {
108
+ if (gainRef.current) {
109
+ gainRef.current.gain.value = Math.max(0, Math.min(1, v));
110
+ }
111
+ },
112
+ []
113
+ );
114
+
115
+ return { play, setVolume } as const;
116
+ }
117
+ ```
118
+
119
+ ### App Root Setup
120
+
121
+ ```tsx
122
+ // app/layout.tsx or app entry
123
+ import { initAudioOnGesture } from "@/hooks/use-sound";
124
+
125
+ // Call once on mount
126
+ useEffect(() => {
127
+ initAudioOnGesture();
128
+ }, []);
46
129
  ```
47
130
 
48
- ### Usage
131
+ ### Basic Usage
132
+
49
133
  ```tsx
50
134
  import { useSound } from "@/hooks/use-sound";
51
135
  import { clickSoftSound } from "@/sounds/click-soft";
52
136
 
53
- function Button() {
54
- const [play] = useSound(clickSoftSound);
55
- return <button onClick={() => { play(); handleAction(); }}>Save</button>;
137
+ function SaveButton() {
138
+ const { play } = useSound(clickSoftSound, { volume: 0.3 });
139
+ return (
140
+ <button onClick={() => { play(); handleSave(); }}>
141
+ Save
142
+ </button>
143
+ );
144
+ }
145
+ ```
146
+
147
+ ### Sound Sprite Pattern
148
+
149
+ Pack multiple short sounds into a single audio file to reduce HTTP requests and simplify asset management. Reference each sound by its offset and duration within the file.
150
+
151
+ ```typescript
152
+ // sounds/ui-sprite.ts
153
+ export const uiSprite = "data:audio/wav;base64,UklGR...";
154
+
155
+ // Offsets in seconds within the sprite file
156
+ export const SPRITE_MAP = {
157
+ click: { offset: 0.0, duration: 0.08 },
158
+ success: { offset: 0.1, duration: 0.15 },
159
+ error: { offset: 0.3, duration: 0.12 },
160
+ toggle: { offset: 0.5, duration: 0.06 },
161
+ whoosh: { offset: 0.6, duration: 0.20 },
162
+ } as const;
163
+ ```
164
+
165
+ ```tsx
166
+ import { useSound } from "@/hooks/use-sound";
167
+ import { uiSprite, SPRITE_MAP } from "@/sounds/ui-sprite";
168
+
169
+ function ToggleSwitch({ checked, onChange }: ToggleProps) {
170
+ const { play } = useSound(uiSprite, {
171
+ volume: 0.35,
172
+ offset: SPRITE_MAP.toggle.offset,
173
+ duration: SPRITE_MAP.toggle.duration,
174
+ });
175
+
176
+ return (
177
+ <button
178
+ role="switch"
179
+ aria-checked={checked}
180
+ onClick={() => { play(); onChange(!checked); }}
181
+ />
182
+ );
56
183
  }
57
184
  ```
58
185
 
@@ -70,27 +197,62 @@ function Button() {
70
197
  - Use the Web Audio API, not `<audio>` elements (lower latency)
71
198
  - Sound volume should be subtle by default (0.3-0.5 of max)
72
199
  - Never auto-play sounds on page load
73
- - Source sounds from CC0 collections (Kenney, Freesound)
200
+ - Gate behind a user preference stored in localStorage or app settings
201
+ - Pre-decode buffers when possible; never decode on every play
74
202
 
75
203
  ---
76
204
 
77
205
  ## 2. Haptic Feedback
78
206
 
79
- ### The Vibration API
80
- ```javascript
81
- // Check support
82
- if ('vibrate' in navigator) {
83
- // Simple tap (10ms pulse)
84
- navigator.vibrate(10);
207
+ ### The Vibration API (Android, some desktop browsers)
208
+
209
+ ```typescript
210
+ // utils/haptics.ts
211
+ export function hapticTap() {
212
+ navigator.vibrate?.(10);
213
+ }
214
+
215
+ export function hapticSuccess() {
216
+ navigator.vibrate?.([10, 50, 10]);
217
+ }
218
+
219
+ export function hapticError() {
220
+ navigator.vibrate?.(30);
221
+ }
222
+
223
+ export function hapticWarning() {
224
+ navigator.vibrate?.([10, 30, 10, 30, 10]);
225
+ }
226
+ ```
227
+
228
+ ### iOS Haptic Considerations
229
+
230
+ The Vibration API is not supported on iOS Safari. For web apps, iOS has no standard haptic API. Strategies for iOS haptic feedback:
231
+
232
+ 1. **Native bridge (Capacitor/React Native)** -- If the app runs in a native wrapper, call `UIImpactFeedbackGenerator` through the bridge. This provides the best haptics on iOS with three intensity levels: `.light`, `.medium`, `.heavy`.
233
+
234
+ ```typescript
235
+ // For Capacitor-based apps
236
+ import { Haptics, ImpactStyle } from "@capacitor/haptics";
237
+
238
+ export async function hapticTapIOS() {
239
+ await Haptics.impact({ style: ImpactStyle.Light });
240
+ }
85
241
 
86
- // Success pattern (two short pulses)
87
- navigator.vibrate([10, 50, 10]);
242
+ export async function hapticSuccessIOS() {
243
+ await Haptics.notification({ type: "success" });
244
+ }
245
+ ```
88
246
 
89
- // Error pattern (one longer pulse)
90
- navigator.vibrate(30);
247
+ 2. **Graceful degradation** -- For pure web apps on iOS, accept that haptics are unavailable. Never show broken behavior. Wrap all haptic calls behind a safe helper:
91
248
 
92
- // Warning (three quick pulses)
93
- navigator.vibrate([10, 30, 10, 30, 10]);
249
+ ```typescript
250
+ export function haptic(pattern: number | number[]) {
251
+ if (typeof navigator !== "undefined" && "vibrate" in navigator) {
252
+ navigator.vibrate(pattern);
253
+ }
254
+ // On iOS Safari this is a no-op. The visual and audio
255
+ // feedback channels carry the interaction.
94
256
  }
95
257
  ```
96
258
 
@@ -102,24 +264,106 @@ if ('vibrate' in navigator) {
102
264
  - **Drag and drop**: 10ms pulse on pickup and drop
103
265
 
104
266
  ### Rules
105
- - Gate behind feature detection (`'vibrate' in navigator`)
267
+ - Gate behind feature detection (`'vibrate' in navigator` or Capacitor availability)
106
268
  - Respect `prefers-reduced-motion` by disabling haptics when motion is reduced
107
269
  - Keep durations very short (10-30ms for taps, never longer than 100ms)
108
270
  - Do not use haptics for every interaction, only pivotal moments
109
- - Mobile only: haptics have no effect on desktop
110
-
111
- ### iOS Considerations
112
- The Vibration API has limited support on iOS Safari. For broader iOS support, use the experimental Haptic Feedback API or accept that haptics are Android-primary.
271
+ - Test on real hardware; emulators do not produce haptic feedback
113
272
 
114
273
  ---
115
274
 
116
275
  ## 3. Multi-Sensory Integration
117
276
 
118
- The strongest UI moments combine visual, auditory, and haptic feedback simultaneously:
277
+ The strongest UI moments combine visual, auditory, and haptic feedback simultaneously. This triple feedback creates a moment of certainty that a single visual change cannot match. Reserve it for milestone moments: order placed, task completed, level achieved, payment confirmed.
278
+
279
+ ### Integration Principles
280
+ 1. **Synchronize channels** -- sound, haptic, and animation should fire at the same instant. Do not stagger them.
281
+ 2. **Match intensity** -- a subtle visual pulse pairs with a quiet click and a light tap. A big celebration pairs with a brighter chime and stronger vibration.
282
+ 3. **Degrade gracefully** -- if sound is muted, the visual and haptic still work. If haptics are unavailable, sound and visual carry it. Each channel must stand on its own.
283
+ 4. **Respect preferences** -- check `prefers-reduced-motion`, sound toggle state, and haptic toggle state independently.
284
+
285
+ ### Complete Example: Task Completion Feedback
286
+
287
+ ```tsx
288
+ import { useCallback } from "react";
289
+ import { motion, AnimatePresence } from "framer-motion";
290
+ import { useSound } from "@/hooks/use-sound";
291
+ import { uiSprite, SPRITE_MAP } from "@/sounds/ui-sprite";
292
+ import { hapticSuccess, haptic } from "@/utils/haptics";
293
+ import { CheckIcon } from "lucide-react";
294
+
295
+ interface TaskCompleteButtonProps {
296
+ completed: boolean;
297
+ onComplete: () => void;
298
+ soundEnabled?: boolean;
299
+ }
300
+
301
+ export function TaskCompleteButton({
302
+ completed,
303
+ onComplete,
304
+ soundEnabled = true,
305
+ }: TaskCompleteButtonProps) {
306
+ const { play } = useSound(uiSprite, {
307
+ volume: 0.4,
308
+ offset: SPRITE_MAP.success.offset,
309
+ duration: SPRITE_MAP.success.duration,
310
+ });
311
+
312
+ const prefersReducedMotion =
313
+ typeof window !== "undefined" &&
314
+ window.matchMedia("(prefers-reduced-motion: reduce)").matches;
315
+
316
+ const handleComplete = useCallback(() => {
317
+ if (completed) return;
318
+
319
+ // Fire all three channels simultaneously
320
+ onComplete();
321
+ if (soundEnabled) play();
322
+ hapticSuccess();
323
+ }, [completed, onComplete, soundEnabled, play]);
324
+
325
+ return (
326
+ <button
327
+ onClick={handleComplete}
328
+ className="relative flex items-center gap-2 rounded-lg bg-zinc-900
329
+ px-4 py-2 text-sm font-medium text-white
330
+ transition-colors hover:bg-zinc-800
331
+ disabled:opacity-50"
332
+ disabled={completed}
333
+ >
334
+ <AnimatePresence mode="wait">
335
+ {completed ? (
336
+ <motion.span
337
+ key="done"
338
+ initial={prefersReducedMotion ? {} : { scale: 0, opacity: 0 }}
339
+ animate={{ scale: 1, opacity: 1 }}
340
+ transition={{ type: "spring", stiffness: 500, damping: 25 }}
341
+ className="flex items-center gap-2 text-emerald-400"
342
+ >
343
+ <CheckIcon className="h-4 w-4" />
344
+ Done
345
+ </motion.span>
346
+ ) : (
347
+ <motion.span
348
+ key="complete"
349
+ exit={prefersReducedMotion ? {} : { scale: 0.8, opacity: 0 }}
350
+ transition={{ duration: 0.1 }}
351
+ >
352
+ Mark Complete
353
+ </motion.span>
354
+ )}
355
+ </AnimatePresence>
356
+ </button>
357
+ );
358
+ }
359
+ ```
360
+
361
+ ### Timeline of a Multi-Sensory Moment
119
362
 
120
- 1. User taps "Complete" button
121
- 2. **Visual**: checkmark animation scales in with a satisfying bounce
122
- 3. **Sound**: soft success chime (100ms)
123
- 4. **Haptic**: double-pulse pattern (10ms, 50ms gap, 10ms)
363
+ | Time | Visual | Sound | Haptic |
364
+ |------|--------|-------|--------|
365
+ | 0ms | Button state changes, checkmark scales in with spring animation | Success chime begins (100-150ms clip) | Double-pulse fires: 10ms on, 50ms gap, 10ms on |
366
+ | 150ms | Spring animation settles, color transition to emerald completes | Sound fades out naturally | Haptic complete |
367
+ | 300ms | Final resting state | Silent | Idle |
124
368
 
125
- This triple feedback creates a moment of certainty that a single visual change cannot match. Use it sparingly, for milestone moments (order placed, task completed, level achieved).
369
+ All three channels start at t=0 and resolve independently. The user perceives them as a single unified moment.
package/SKILL.md DELETED
@@ -1,202 +0,0 @@
1
- ---
2
- name: picasso
3
- description: >
4
- The ultimate frontend design and UI engineering skill. Use this whenever the user asks to build, design, style, or improve any web interface, component, page, application, dashboard, landing page, artifact, poster, or visual output. Covers typography, color systems, spatial design, motion/animation, interaction design, responsive layouts, sound design, haptic feedback, icon systems, generative art, theming, React best practices, and DESIGN.md system generation. Also use when the user asks to audit, critique, polish, simplify, animate, or normalize a frontend. Triggers on any mention of "make it look good," "fix the design," "UI," "UX," "frontend," "component," "landing page," "dashboard," "artifact," "poster," "design system," "theme," "animation," "responsive," or any request to improve visual quality. Use this skill even when the user does not explicitly ask for design help but the task involves producing a visual interface.
5
- ---
6
-
7
- # Picasso
8
-
9
- The ultimate design skill for producing distinctive, production-grade frontend interfaces, visual artifacts, and design systems. This skill consolidates best practices from Anthropic's frontend-design, canvas-design, algorithmic-art, and theme-factory skills, Impeccable's 7-domain reference system, VoltAgent's DESIGN.md format, Vercel's React and typography standards, and specialized libraries for sound, haptics, icons, and text animation.
10
-
11
- Every output should look like it was built by a senior design engineer who spent days refining it, not generated by an AI in seconds.
12
-
13
- ---
14
-
15
- ## Configurable Settings
16
-
17
- These three dials (1-10) control the overall character of the output. Adjust based on what is being built. The user can set these explicitly or they can be inferred from context.
18
-
19
- - **DESIGN_VARIANCE** (default: 6) — How experimental the layout is. 1-3: clean, centered, conventional. 4-6: considered asymmetry, intentional breaks. 7-10: avant-garde, overlapping elements, unconventional grids.
20
- - **MOTION_INTENSITY** (default: 5) — How much animation is present. 1-3: hover states and fades only. 4-6: staggered reveals, scroll-triggered, text morphing. 7-10: magnetic cursors, parallax, complex choreography.
21
- - **VISUAL_DENSITY** (default: 5) — How much content fits on one screen. 1-3: spacious, luxury, breathing room. 4-6: balanced, structured whitespace. 7-10: dense dashboards, data-heavy, compact.
22
-
23
- When the user says "make it premium" or "luxury feel," drop VISUAL_DENSITY to 2-3 and MOTION_INTENSITY to 4-5. When they say "dashboard" or "admin panel," raise VISUAL_DENSITY to 7-8. When they say "make it pop" or "wow factor," raise DESIGN_VARIANCE and MOTION_INTENSITY to 7-8.
24
-
25
- ---
26
-
27
- ## Step 0: Read the Right References
28
-
29
- Before writing any code, read the reference files relevant to the task. Each covers a domain in depth with rules, examples, and anti-patterns. Load only what you need.
30
-
31
- | Reference File | When to Read |
32
- |---|---|
33
- | `references/typography.md` | Any task involving text, fonts, headings, or type hierarchy |
34
- | `references/color-and-contrast.md` | Color palettes, dark mode, accessibility, tinted neutrals |
35
- | `references/spatial-design.md` | Layout, spacing, grids, visual hierarchy, whitespace |
36
- | `references/motion-and-animation.md` | Transitions, scroll effects, text morphing, micro-interactions |
37
- | `references/interaction-design.md` | Forms, focus states, loading, empty states, error handling |
38
- | `references/responsive-design.md` | Mobile-first, fluid, container queries, touch targets |
39
- | `references/sensory-design.md` | UI sound effects, haptic feedback, multi-sensory interfaces |
40
- | `references/react-patterns.md` | React/Next.js component architecture, hooks, performance |
41
- | `references/anti-patterns.md` | Explicit list of what NOT to do (the most important reference) |
42
- | `references/design-system.md` | Generating DESIGN.md files, theming, systematic tokens |
43
- | `references/generative-art.md` | Algorithmic art, p5.js, seeded randomness, flow fields |
44
- | `references/component-patterns.md` | Standard component naming, taxonomy, and state patterns |
45
-
46
- ---
47
-
48
- ## Step 1: Design Thinking
49
-
50
- Before writing a single line of code, answer these questions internally:
51
-
52
- **Purpose.** What problem does this interface solve? Who uses it? What is the single most important action?
53
-
54
- **Tone.** Commit to a specific aesthetic direction. Not "clean and modern" (that is meaningless). Pick something with teeth: brutalist, editorial, retro-terminal, luxury serif, toy-like, industrial, organic, Swiss grid, art deco, vaporwave, newspaper broadsheet, scientific journal, or something entirely original. The direction should be informed by the content, not applied generically.
55
-
56
- **Differentiation.** What makes this unforgettable? What is the one thing someone will remember after closing the tab? If there is no answer, the design is not ready.
57
-
58
- **Constraints.** Framework requirements, accessibility targets, performance budgets, existing design tokens.
59
-
60
- ---
61
-
62
- ## Step 2: Aesthetic Execution
63
-
64
- ### Typography
65
-
66
- Choose fonts that are distinctive, not default. Never use Inter, Roboto, Arial, or system fonts as primary choices. Pair a display font with a body font. Use a modular type scale (1.25 or 1.333 ratio). Set line heights between 1.4 and 1.6 for body text. Use OpenType features (ligatures, tabular numbers, small caps) when the font supports them. See `references/typography.md` for the full system.
67
-
68
- ### Color
69
-
70
- Build palettes with intention. Use OKLCH for perceptually uniform color manipulation. Always tint neutrals (never use pure gray or pure black). Dominant color with sharp accent outperforms evenly distributed palettes. Test contrast ratios: 4.5:1 minimum for body text, 3:1 for large text and UI elements. See `references/color-and-contrast.md`.
71
-
72
- ### Spatial Composition
73
-
74
- Use a spacing scale (4px base: 4, 8, 12, 16, 24, 32, 48, 64, 96). Asymmetric layouts, overlapping elements, diagonal flow, and grid-breaking moments create visual interest. Generous negative space communicates confidence. Dense layouts need careful rhythm. See `references/spatial-design.md`.
75
-
76
- ### Backgrounds and Visual Depth
77
-
78
- Never default to flat solid colors. Create atmosphere with gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, grain overlays, or subtle backdrop filters. Depth comes from elevation systems: consistent shadow scales, surface hierarchy, and z-index discipline.
79
-
80
- ### Motion
81
-
82
- One well-orchestrated page load with staggered reveals (using animation-delay) creates more impact than scattered micro-interactions. Use CSS transitions for simple state changes. Use `framer-motion` or the Motion library for React when choreography matters. Never use bounce or elastic easing (it looks dated). Respect `prefers-reduced-motion`. See `references/motion-and-animation.md`.
83
-
84
- ### Text Animation
85
-
86
- For text morphing effects (counters, status changes, tab labels), use `torph` (dependency-free, works with React/Vue/Svelte). Import as `import { TextMorph } from 'torph/react'` and wrap any text that changes dynamically.
87
-
88
- ### Sound
89
-
90
- For UI sound feedback (clicks, notifications, transitions), use the soundcn pattern: inline base64 audio data URIs with a `useSound` hook via Web Audio API. Zero dependencies. See `references/sensory-design.md`.
91
-
92
- ### Haptics
93
-
94
- For mobile web, use the WebHaptics pattern via the Vibration API (`navigator.vibrate()`) to provide tactile feedback on button presses, toggles, and destructive actions. Always gate behind feature detection and user preference. See `references/sensory-design.md`.
95
-
96
- ### Icons
97
-
98
- Use Lucide React as the default icon library (`lucide-react`). For broader searches across 200K+ icons from 150+ collections, use the `better-icons` CLI pattern: search by keyword, retrieve SVG, sync to project. Prefer outline style for UI, solid for emphasis.
99
-
100
- ### Avatars and Identity
101
-
102
- For deterministic avatar generation from strings (usernames, emails, UUIDs), use the Facehash pattern: a React component that generates unique face avatars. Same input always produces the same face. Zero external assets.
103
-
104
- ---
105
-
106
- ## Step 3: Implementation Standards
107
-
108
- ### Single-File Artifacts
109
-
110
- When building for claude.ai artifacts (HTML or React), everything goes in one file. No external CSS files, no separate JS. Inline everything. For HTML artifacts, import external scripts only from `https://cdnjs.cloudflare.com`. For React artifacts, use only available libraries (lucide-react, recharts, d3, Three.js r128, Tone, shadcn/ui, Tailwind core utilities, lodash, mathjs, papaparse, Chart.js).
111
-
112
- ### React Best Practices
113
-
114
- Follow these rules (see `references/react-patterns.md` for details):
115
-
116
- - Server Components by default, `'use client'` only when needed
117
- - Colocate state with the component that uses it
118
- - Prefer composition over prop drilling
119
- - Use `Suspense` boundaries with meaningful fallbacks
120
- - Never store derived state, compute it during render
121
- - Use semantic HTML elements, not `div` soup
122
- - Memoize expensive computations, not everything
123
- - Default export for page/route components, named exports for utilities
124
-
125
- ### CSS Variables for Theming
126
-
127
- Always define a CSS variable system for colors, spacing, typography, and shadows. This makes themes swappable and dark mode trivial.
128
-
129
- ```css
130
- :root {
131
- --color-surface: #fafaf9;
132
- --color-text: #1c1917;
133
- --color-accent: #dc2626;
134
- --radius: 8px;
135
- --shadow-sm: 0 1px 2px oklch(0% 0 0 / 0.05);
136
- }
137
- ```
138
-
139
- ### Accessibility Defaults
140
-
141
- Every interface must include: visible focus indicators (never `outline: none` without replacement), sufficient color contrast, keyboard navigability, ARIA labels on interactive elements without visible text, and `alt` text on meaningful images. Do not treat accessibility as optional.
142
-
143
- ---
144
-
145
- ## Step 4: Audit and Polish
146
-
147
- Before delivering any interface, run this mental checklist:
148
-
149
- 1. **Typography audit.** Is there a clear type hierarchy? Are fonts loaded and rendering? Is body text readable at default zoom?
150
- 2. **Color audit.** Does the palette feel cohesive? Do accents draw the eye to the right places? Does it work in both light and dark contexts?
151
- 3. **Spatial audit.** Is spacing consistent? Are elements aligned to an invisible grid? Is there breathing room?
152
- 4. **Interaction audit.** Do all interactive elements have hover, focus, and active states? Are transitions smooth? Is there loading feedback?
153
- 5. **Responsive audit.** Does it work on 375px wide screens? Does it scale gracefully to ultrawide?
154
- 6. **Motion audit.** Does the page load feel choreographed? Are transitions purposeful? Does `prefers-reduced-motion` disable non-essential animation?
155
- 7. **Accessibility audit.** Can you tab through the entire interface? Are contrast ratios sufficient? Do screen readers make sense of the structure?
156
-
157
- ---
158
-
159
- ## Step 5: Design System Generation
160
-
161
- When asked to create a design system or DESIGN.md, follow the VoltAgent/Stitch format. See `references/design-system.md` for the complete template covering: visual theme and atmosphere, color palette with semantic roles, typography hierarchy, component styling (buttons, cards, inputs, navigation with states), layout principles, depth and elevation system, explicit dos and don'ts, responsive behavior, and an agent prompt guide.
162
-
163
- ---
164
-
165
- ## Step 6: Generative and Canvas Art
166
-
167
- When the task involves algorithmic art, generative visuals, or static poster/print design, see `references/generative-art.md`. The process: write an algorithmic philosophy (4-6 paragraphs), then express it through p5.js code with seeded randomness, parameter controls, and seed navigation.
168
-
169
- ---
170
-
171
- ## Commands
172
-
173
- These optional directives can be used to steer design refinement:
174
-
175
- | Command | Effect |
176
- |---|---|
177
- | `/audit` | Technical quality check: accessibility, performance, responsive |
178
- | `/critique` | UX design review: hierarchy, clarity, emotional resonance |
179
- | `/polish` | Final pass: refine spacing, transitions, copy |
180
- | `/simplify` | Strip to essence, remove visual noise |
181
- | `/animate` | Add purposeful motion and transitions |
182
- | `/bolder` | Amplify timid designs with stronger visual choices |
183
- | `/quieter` | Tone down overly aggressive designs |
184
- | `/normalize` | Align with design system standards |
185
- | `/theme` | Generate or apply a color/font theme |
186
- | `/sound` | Add UI sound effects to interactions |
187
- | `/haptics` | Add haptic feedback for mobile web |
188
- | `/redesign` | Audit an existing project, identify design problems, fix them systematically |
189
- | `/soft` | Apply premium soft aesthetic: generous whitespace, depth, smooth spring animations |
190
- | `/minimalist` | Apply editorial minimalism: monochrome, crisp borders, inspired by Linear/Notion |
191
- | `/brutalist` | Apply raw mechanical aesthetic: Swiss typography meets CRT terminal |
192
- | `/stitch` | Generate a Google Stitch-compatible DESIGN.md for the current project |
193
-
194
- ---
195
-
196
- ## The Non-Negotiables
197
-
198
- 1. No design should ever look like "AI made this." No purple gradients on white. No Inter font. No centered everything. No cards nested in cards. No gray text on colored backgrounds.
199
- 2. Every design must have a clear aesthetic point of view. If it could belong to any product, it belongs to none.
200
- 3. Match implementation complexity to vision. Maximalist designs need elaborate code. Minimalist designs need surgical precision. Both require the same level of care.
201
- 4. Text is always a design element, never an afterthought.
202
- 5. Every detail matters. The shadow radius, the letter spacing, the hover transition duration, the border color in dark mode. These are not small decisions.