dreative 0.5.0 → 0.5.2

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.
Files changed (48) hide show
  1. package/README.md +49 -27
  2. package/dist/cli/audit.js +206 -0
  3. package/dist/cli/audit.test.js +79 -0
  4. package/dist/cli/docsCheck.js +163 -0
  5. package/dist/cli/docsCheck.test.js +8 -0
  6. package/dist/cli/index.js +81 -8
  7. package/dist/server/preview.js +73 -73
  8. package/dist/server/store.js +11 -0
  9. package/dist/shared/artifacts.js +162 -0
  10. package/dist/shared/design.js +42 -22
  11. package/dist/shared/ruleSystem.js +130 -0
  12. package/dist/shared/ruleSystem.test.js +187 -0
  13. package/dist/shared/skillSystem.js +173 -0
  14. package/dist/shared/skillSystem.test.js +110 -0
  15. package/dist/ui/assets/{index--vztc_MR.js → index-CKwmbx2j.js} +13 -13
  16. package/dist/ui/index.html +12 -12
  17. package/package.json +5 -3
  18. package/skill/dreative/DESIGN.md +290 -95
  19. package/skill/dreative/PLAN.md +462 -71
  20. package/skill/dreative/SKILL.md +230 -126
  21. package/skill/dreative/frameworks/nextjs.md +13 -0
  22. package/skill/dreative/frameworks/react-vite.md +12 -0
  23. package/skill/dreative/frameworks/styling.md +14 -0
  24. package/skill/dreative/frameworks/sveltekit.md +10 -0
  25. package/skill/dreative/frameworks/vue-nuxt.md +12 -0
  26. package/skill/dreative/recipes/3d-recipes.md +44 -0
  27. package/skill/dreative/recipes/cinematic-recipes.md +19 -0
  28. package/skill/dreative/recipes/immersive-recipes.md +18 -0
  29. package/skill/dreative/recipes/media-recipes.md +60 -0
  30. package/skill/dreative/recipes/motion-recipes.md +44 -0
  31. package/skill/dreative/references/ARTIFACTS.md +180 -0
  32. package/skill/dreative/references/REFLEX_FONTS.json +44 -0
  33. package/skill/dreative/references/RULES.json +186 -0
  34. package/skill/dreative/references/SKILL_CONTRACT.md +30 -0
  35. package/skill/dreative/references/TIERS.md +42 -0
  36. package/skill/dreative/schemas/plan.schema.json +241 -0
  37. package/skill/dreative/schemas/verify.schema.json +61 -0
  38. package/skill/dreative/skills/3d.md +94 -157
  39. package/skill/dreative/skills/cinematic.md +56 -232
  40. package/skill/dreative/skills/experimental.md +111 -0
  41. package/skill/dreative/skills/immersive.md +61 -223
  42. package/skill/dreative/skills/interaction.md +9 -1
  43. package/skill/dreative/skills/media.md +135 -216
  44. package/skill/dreative/skills/mobile.md +128 -117
  45. package/skill/dreative/skills/motion.md +89 -229
  46. package/skill/dreative/skills/refined.md +116 -102
  47. package/skill/dreative/skills/ux.md +155 -144
  48. package/dist/server/ai.js +0 -177
@@ -0,0 +1,241 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://dreative.local/schemas/plan.schema.json",
4
+ "title": "Dreative Multi-Page Direct Design Plan",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "request", "createdAt", "tier", "depth", "skills", "skillPolicy", "designRead", "pages", "preservationManifest", "decisionLedger"],
8
+ "properties": {
9
+ "version": { "const": 2 },
10
+ "doctrineVersion": { "const": 2 },
11
+ "request": { "type": "string", "minLength": 1 },
12
+ "createdAt": { "type": "string", "format": "date-time" },
13
+ "tier": { "enum": ["solid", "premium", "expressive", "award"] },
14
+ "depth": { "enum": ["restyle", "relayout", "restructure", "reimagine"] },
15
+ "skills": { "$ref": "#/$defs/skillList" },
16
+ "skillPolicy": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["mode", "global", "routingApproved", "userAssignments"],
20
+ "properties": {
21
+ "mode": { "const": "hybrid" },
22
+ "global": { "$ref": "#/$defs/skillList" },
23
+ "routingApproved": { "const": true },
24
+ "userAssignments": {
25
+ "type": "array",
26
+ "items": {
27
+ "type": "object",
28
+ "additionalProperties": false,
29
+ "required": ["pageId", "skills"],
30
+ "properties": {
31
+ "pageId": { "type": "string", "minLength": 1 },
32
+ "skills": { "$ref": "#/$defs/treatmentList" }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ },
38
+ "designRead": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["register", "concept", "signature"],
42
+ "properties": {
43
+ "register": { "type": "string", "minLength": 1 },
44
+ "concept": { "type": "string", "minLength": 1 },
45
+ "signature": { "type": "string", "minLength": 1 }
46
+ }
47
+ },
48
+ "implementationStartedAt": { "type": "string", "format": "date-time" },
49
+ "ruleExceptions": { "type": "array", "items": { "$ref": "#/$defs/ruleException" } },
50
+ "creativeStrategy": { "$ref": "#/$defs/creativeStrategy" },
51
+ "fontDecision": { "$ref": "#/$defs/fontDecision" },
52
+ "experimentalPlan": { "$ref": "#/$defs/experimentalPlan" },
53
+ "conceptExploration": { "$ref": "#/$defs/conceptExploration" },
54
+ "recipeAccess": { "type": "array", "items": { "$ref": "#/$defs/recipeAccess" } },
55
+ "pages": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/page" } },
56
+ "preservationManifest": { "type": "string", "minLength": 1 },
57
+ "decisionLedger": { "type": "string", "minLength": 1 }
58
+ },
59
+ "$defs": {
60
+ "skill": { "enum": ["ux", "mobile", "refined", "motion", "interaction", "media", "3d", "immersive", "cinematic", "experimental"] },
61
+ "skillList": {
62
+ "type": "array",
63
+ "uniqueItems": true,
64
+ "allOf": [{ "contains": { "const": "ux" } }, { "contains": { "const": "mobile" } }],
65
+ "items": { "$ref": "#/$defs/skill" }
66
+ },
67
+ "treatmentList": {
68
+ "type": "array",
69
+ "uniqueItems": true,
70
+ "items": { "$ref": "#/$defs/skill" }
71
+ },
72
+ "status": { "enum": ["planned", "shipped", "fallback", "cut"] },
73
+ "ruleException": {
74
+ "type": "object",
75
+ "additionalProperties": false,
76
+ "required": ["ruleId", "decision", "declaredAt", "reason", "alternative", "successCriteria", "evidenceIds"],
77
+ "properties": {
78
+ "ruleId": { "type": "string", "minLength": 1 },
79
+ "decision": { "const": "substituted" },
80
+ "declaredAt": { "type": "string", "format": "date-time" },
81
+ "reason": { "type": "string", "minLength": 20 },
82
+ "alternative": { "type": "string", "minLength": 30 },
83
+ "successCriteria": { "type": "array", "minItems": 2, "items": { "type": "string", "minLength": 12 } },
84
+ "evidenceIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
85
+ }
86
+ },
87
+ "creativeStrategy": {
88
+ "oneOf": [
89
+ {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "required": ["path", "mechanisms", "drivers"],
93
+ "properties": {
94
+ "path": { "const": "diversity" },
95
+ "mechanisms": { "type": "array", "minItems": 4, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
96
+ "drivers": { "type": "array", "minItems": 3, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
97
+ }
98
+ },
99
+ {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": ["path", "signatureMechanism", "states", "secondaryMechanisms", "drivers"],
103
+ "properties": {
104
+ "path": { "const": "development" },
105
+ "signatureMechanism": { "type": "string", "minLength": 1 },
106
+ "states": { "type": "array", "minItems": 3, "uniqueItems": true, "items": { "type": "string", "minLength": 12 } },
107
+ "secondaryMechanisms": { "type": "array", "minItems": 2, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
108
+ "drivers": { "type": "array", "minItems": 2, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
109
+ }
110
+ }
111
+ ]
112
+ },
113
+ "fontDecision": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "required": ["selected", "candidates", "recentDisplayFonts"],
117
+ "properties": {
118
+ "selected": { "type": "string", "minLength": 1 },
119
+ "candidates": {
120
+ "type": "array",
121
+ "minItems": 3,
122
+ "items": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["name", "reflex", "rationale"],
126
+ "properties": {
127
+ "name": { "type": "string", "minLength": 1 },
128
+ "reflex": { "type": "boolean" },
129
+ "rationale": { "type": "string", "minLength": 12 }
130
+ }
131
+ }
132
+ },
133
+ "recentDisplayFonts": { "type": "array", "maxItems": 3, "items": { "type": "string" } },
134
+ "reasonKinds": {
135
+ "type": "array",
136
+ "uniqueItems": true,
137
+ "items": {
138
+ "enum": ["existing-brand", "design-system-metrics", "product-register", "supplied-reference", "language-coverage", "variable-font-capability", "performance", "physical-editorial-historical-reference"]
139
+ }
140
+ },
141
+ "justification": { "type": "string", "minLength": 20 },
142
+ "repeatJustification": { "type": "string", "minLength": 20 }
143
+ }
144
+ },
145
+ "experimentalPlan": {
146
+ "type": "object",
147
+ "additionalProperties": false,
148
+ "required": ["majorSectionIds", "candidates"],
149
+ "properties": {
150
+ "majorSectionIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
151
+ "candidates": {
152
+ "type": "array",
153
+ "items": {
154
+ "type": "object",
155
+ "additionalProperties": false,
156
+ "required": ["id", "sectionId", "idea", "selected"],
157
+ "properties": {
158
+ "id": { "type": "string", "minLength": 1 },
159
+ "sectionId": { "type": "string", "minLength": 1 },
160
+ "idea": { "type": "string", "minLength": 20 },
161
+ "selected": { "type": "boolean" }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ },
167
+ "conceptExploration": {
168
+ "type": "object",
169
+ "additionalProperties": false,
170
+ "required": ["recordedAt", "concepts"],
171
+ "properties": {
172
+ "recordedAt": { "type": "string", "format": "date-time" },
173
+ "concepts": {
174
+ "type": "array",
175
+ "minItems": 3,
176
+ "items": {
177
+ "type": "object",
178
+ "additionalProperties": false,
179
+ "required": ["name", "concept", "brandConnection"],
180
+ "properties": {
181
+ "name": { "type": "string", "minLength": 1 },
182
+ "concept": { "type": "string", "minLength": 20 },
183
+ "brandConnection": { "type": "string", "minLength": 20 }
184
+ }
185
+ }
186
+ }
187
+ }
188
+ },
189
+ "recipeAccess": {
190
+ "type": "object",
191
+ "additionalProperties": false,
192
+ "required": ["file", "loadedAt", "purpose"],
193
+ "properties": {
194
+ "file": { "type": "string", "minLength": 1 },
195
+ "loadedAt": { "type": "string", "format": "date-time" },
196
+ "purpose": { "enum": ["feasibility", "implementation", "performance", "fallback", "concept-repair"] }
197
+ }
198
+ },
199
+ "asset": {
200
+ "type": "object",
201
+ "additionalProperties": false,
202
+ "required": ["id", "path", "purpose", "status"],
203
+ "properties": {
204
+ "id": { "type": "string", "minLength": 1 },
205
+ "path": { "type": "string", "minLength": 1 },
206
+ "purpose": { "type": "string", "minLength": 1 },
207
+ "status": { "$ref": "#/$defs/status" },
208
+ "reason": { "type": "string", "minLength": 1 }
209
+ }
210
+ },
211
+ "section": {
212
+ "type": "object",
213
+ "additionalProperties": false,
214
+ "required": ["id", "name", "layoutFamily", "skills", "interactions", "mobile", "fallback", "verification", "assets", "status"],
215
+ "properties": {
216
+ "id": { "type": "string", "minLength": 1 },
217
+ "name": { "type": "string", "minLength": 1 },
218
+ "layoutFamily": { "type": "string", "minLength": 1 },
219
+ "skills": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/skill" } },
220
+ "interactions": { "type": "array", "items": { "type": "string" } },
221
+ "mobile": { "type": "string", "minLength": 1 },
222
+ "fallback": { "type": "string", "minLength": 1 },
223
+ "verification": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } },
224
+ "assets": { "type": "array", "items": { "$ref": "#/$defs/asset" } },
225
+ "status": { "$ref": "#/$defs/status" },
226
+ "reason": { "type": "string", "minLength": 1 }
227
+ }
228
+ },
229
+ "page": {
230
+ "type": "object",
231
+ "additionalProperties": false,
232
+ "required": ["id", "name", "skills", "sections"],
233
+ "properties": {
234
+ "id": { "type": "string", "minLength": 1 },
235
+ "name": { "type": "string", "minLength": 1 },
236
+ "skills": { "$ref": "#/$defs/skillList" },
237
+ "sections": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/section" } }
238
+ }
239
+ }
240
+ }
241
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://dreative.local/schemas/verify.schema.json",
4
+ "title": "Dreative Verification Report",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "generatedAt", "evidence"],
8
+ "properties": {
9
+ "version": { "const": 1 },
10
+ "generatedAt": { "type": "string", "format": "date-time" },
11
+ "evidence": {
12
+ "type": "array",
13
+ "items": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "required": ["id", "criterion", "status", "evidence", "proof"],
17
+ "properties": {
18
+ "id": { "type": "string", "minLength": 1 },
19
+ "criterion": { "type": "string", "minLength": 1 },
20
+ "status": { "enum": ["pass", "fail", "not-applicable"] },
21
+ "evidence": { "type": "string", "minLength": 1 },
22
+ "proof": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "required": ["timestamp"],
26
+ "properties": {
27
+ "timestamp": { "type": "string", "format": "date-time" },
28
+ "artifactPath": { "type": "string", "minLength": 1 },
29
+ "viewport": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["width", "height"],
33
+ "properties": {
34
+ "width": { "type": "number", "exclusiveMinimum": 0 },
35
+ "height": { "type": "number", "exclusiveMinimum": 0 },
36
+ "dpr": { "type": "number", "exclusiveMinimum": 0 }
37
+ }
38
+ },
39
+ "command": { "type": "string", "minLength": 1 },
40
+ "exitCode": { "type": "integer" },
41
+ "consoleErrorCount": { "type": "integer", "minimum": 0 },
42
+ "testedUrl": { "type": "string", "minLength": 1 },
43
+ "averageFps": { "type": "number", "exclusiveMinimum": 0 },
44
+ "maxFrameTimeMs": { "type": "number", "minimum": 0 },
45
+ "playwrightTestId": { "type": "string", "minLength": 1 }
46
+ },
47
+ "anyOf": [
48
+ { "required": ["artifactPath"] },
49
+ { "required": ["command", "exitCode"] },
50
+ { "required": ["consoleErrorCount"] },
51
+ { "required": ["testedUrl"] },
52
+ { "required": ["averageFps"] },
53
+ { "required": ["maxFrameTimeMs"] },
54
+ { "required": ["playwrightTestId"] }
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
@@ -1,157 +1,94 @@
1
- # Dreative Specialist Skill — 3D, WebGL & Shaders
2
-
3
- Load this file when `plan.skills` includes `3d`, or the brief/prompt mentions 3D,
4
- WebGL, three.js, shaders, particles, globes, or point clouds. DESIGN.md still
5
- governs everything around the canvas (layout, color, type, motion budgets).
6
- Integrating 3D usually changes component structure (canvas placement, lazy
7
- boundaries, scroll wrappers) when it does, follow DESIGN.md §11's
8
- transformation-depth ladder: offer the restructure, then do it for real.
9
-
10
- ## 0. Does 3D earn its place?
11
-
12
- 3D is the most expensive pixel on the web in bytes, battery, and attention.
13
- It earns its place when the SUBJECT is spatial (a physical product, a device, a
14
- map/globe, an environment, data with real dimensionality) or when the brand brief
15
- explicitly buys a signature 3D moment. It does not earn its place as ambient
16
- decoration: a random floating torus/blob behind hero text is the 3D equivalent of
17
- the gradient blob — banned as a default reach. One 3D moment per page; make it the
18
- signature element (DESIGN.md §2) or don't ship it.
19
-
20
- Cheaper substitutes to consider first: CSS 3D transforms (`perspective` +
21
- `rotateX/Y` on real DOM — free, accessible, great for cards/mockups/tilt), a
22
- pre-rendered video/image sequence scrubbed on scroll, or a Lottie/Rive vector
23
- animation. If the object never needs live lighting or user-driven rotation,
24
- pre-render it and if a video-generation tool exists in the environment
25
- (PLAN.md §1's probe), a generated loop or frame sequence (media.md §1) is
26
- usually the strongest pre-render source.
27
-
28
- ## 1. Stack
29
-
30
- - **React app React Three Fiber (`@react-three/fiber`) + `@react-three/drei`.**
31
- Never hand-roll a three.js imperative setup inside React. Drei gives you 80%:
32
- `Environment`, `ContactShadows`, `Float`, `ScrollControls`, `Html`, `Text`,
33
- `useGLTF`, `MeshTransmissionMaterial`, `Center`, `Bounds`.
34
- - **Non-React → three.js** with a small render-loop module; or **OGL** when the
35
- scene is one shader plane and three.js is overkill.
36
- - Post-processing via `@react-three/postprocessing` (Bloom, DoF, Noise) — 1-2
37
- effects max; the stacked-postFX look reads as demo-scene, not product.
38
- - Physics only if interaction demands it (`@react-three/rapier`).
39
-
40
- Lazy-load the entire 3D bundle (`next/dynamic` / `React.lazy`) with an SSR-off
41
- canvas and a styled poster fallback. Three.js must never be in the critical path.
42
-
43
- ## 2. Scene fundamentals (where amateur scenes fail)
44
-
45
- - **Lighting is the craft.** Default: `<Environment preset="studio"|"city">` for
46
- image-based lighting + ONE key directional light for shadows. Ambient light
47
- alone = flat plastic. Match light temperature to the page palette.
48
- - **Color management:** renderer defaults in modern three are correct
49
- (`outputColorSpace: SRGBColorSpace`, `ACESFilmicToneMapping`) don't disable
50
- them; DO set `toneMappingExposure` deliberately. Convert hex from the page
51
- palette with `new THREE.Color(hex)` scene colors and page colors must read as
52
- one system.
53
- - **Ground the object:** `<ContactShadows opacity={0.4} blur={2.5}>` or a real
54
- shadow plane. Floating unanchored objects read as clipart.
55
- - Camera: 35-50° FOV for product shots (85°+ distorts); frame with
56
- `<Bounds fit clip>` or `<Center>`; subtle idle via `<Float>` or damped
57
- mouse-parallax (`useFrame` + `THREE.MathUtils.damp`), amplitude ≤ 3°.
58
- - Materials: `meshStandardMaterial`/`meshPhysicalMaterial` with `roughness`/
59
- `metalness` chosen from the real object; `MeshTransmissionMaterial` for glass
60
- (expensive one object max). Untextured default-gray = unfinished.
61
-
62
- ## 3. Models
63
-
64
- - glTF/GLB only, Draco or Meshopt compressed (`gltf-transform optimize in.glb
65
- out.glb --compress draco`). Budget: hero model ≤ 2-3 MB, ≤ 100k triangles.
66
- - `useGLTF.preload(url)`; wrap in `<Suspense>` with a poster (not a spinner).
67
- - No model available? Build from primitives + good materials/lighting (a laptop
68
- from rounded boxes with an `Html` screen reads better than a bad download), or
69
- tell the user what asset is needed — never ship an unrelated placeholder model.
70
-
71
- ## 4. Shaders (the highest-leverage 100 lines)
72
-
73
- A fullscreen/plane fragment shader is the cheapest way to a signature visual:
74
- animated gradient meshes, flowfields, displacement on hover, image transitions.
75
-
76
- - Structure: `shaderMaterial` (drei) with `uTime`, `uMouse`, `uResolution`,
77
- palette colors as `uColorA/B/C` uniforms fed FROM the page palette.
78
- - Vocabulary: fbm/simplex noise for organic movement (inline a noise fn; don't
79
- import a library for it), `smoothstep` for banding-free ramps, domain warping
80
- (`noise(p + noise(p))`) for the expensive look, `mix()` between palette colors
81
- only never rainbow hue-rotation.
82
- - Displace vertices in the vertex shader for cloth/terrain/blob effects; compute
83
- normals or fake lighting with the noise derivative.
84
- - Animate `uTime` at 0.05-0.2 speed; slow reads as premium, fast as screensaver.
85
- - Image effects: sample two textures + a noise mask for transitions; barrel/flow
86
- distortion on scroll velocity for editorial galleries.
87
-
88
- ## 4.5 Media in the scene (images & video as textures)
89
-
90
- The other half of shader craft: real page media rendered THROUGH WebGL so
91
- effects can touch it (the unseen.co gallery mechanic — full pattern in
92
- `skills/media.md` §3):
93
-
94
- - **DOM-synced media planes**: the page's `<img>`/`<video>` elements stay in
95
- the DOM (a11y/layout/fallback, `opacity: 0` never `display:none`) while
96
- textured planes copy their `getBoundingClientRect()` per rAF (lerped).
97
- One scene owns ALL planes — never a canvas per image.
98
- - **Video textures**: `new THREE.VideoTexture(videoEl)` with the element
99
- `muted playsinline` and playing; `texture.colorSpace = SRGBColorSpace`;
100
- generated seamless loops (media.md §1) make the best texture sources —
101
- a pre-rendered loop as a texture often beats a live sim for cost.
102
- - Effects on media planes: hover ripple/lens (damped `uMouse` + radial UV
103
- displacement), velocity stretch + RGB split (clamped, damped decay),
104
- noise-mask dissolves between textures (§4), subtle vertex curvature for
105
- the floating-paper look.
106
- - Failure path is wired, not theoretical: WebGL missing/lost or
107
- reduced-motion → un-hide the DOM media (`opacity: 1`). Verify it fires.
108
-
109
- ## 5. Particles and points
110
-
111
- Points/instancing, never meshes-per-particle: `<Points>` + `BufferAttribute`
112
- positions animated in a shader (`uTime` in the vertex shader), or
113
- `<Instances>`/`InstancedMesh` for repeated geometry (≤ ~10k instances). Counts:
114
- 2-5k points desktop, halve on mobile. Particle color from the page palette at 1-2
115
- hues; size attenuation on; additive blending only on dark surfaces.
116
-
117
- ## 6. Scroll- and layout-integration
118
-
119
- - Canvas placement: either a bounded block IN the layout (preferred — it composes
120
- with the grid) or a full-bleed fixed background with content scrolling over.
121
- Full-page persistent canvases with DOM scrolled on top: use drei
122
- `ScrollControls` + `<Scroll html>` so 3D and DOM share one scroll.
123
- - Scroll-linked 3D: map scroll progress (Motion `useScroll` / ScrollTrigger /
124
- drei `useScroll`) to camera position along a path or object rotation — damped
125
- (`damp3`, `dampE`), never raw-set per frame.
126
- - DOM/3D registration (labels pinned to model parts): drei `<Html transform
127
- occlude>`; keep text as real DOM for accessibility, never texture-baked type.
128
- - The block's `data-dreative-id` goes on the wrapper div around the Canvas.
129
-
130
- ## 7. Performance & fallbacks (ship-blockers)
131
-
132
- - `<Canvas dpr={[1, 2]}>` (cap device pixel ratio), `frameloop="demand"` +
133
- `invalidate()` for static-until-interacted scenes; pause the loop when the
134
- canvas leaves the viewport (IntersectionObserver) and on `document.hidden`.
135
- - One `useFrame` per concern; no allocations inside it (reuse vectors created
136
- outside). Dispose on unmount (R3F handles it; imperative three must
137
- `dispose()` geometries/materials/textures).
138
- - Mobile: halve particle counts, drop post-processing, consider a poster image
139
- below 768px — a janky 3D hero is worse than none.
140
- - `prefers-reduced-motion`: stop idle rotation/particle drift; render one static
141
- well-lit frame (`frameloop="demand"` makes this free).
142
- - WebGL unavailable/context-lost → the poster fallback, never a blank block.
143
- - Keyboard/screen-reader: canvas gets `role="img"` + `aria-label`; any 3D-driven
144
- interaction has a DOM equivalent.
145
-
146
- ## 8. Recipes
147
-
148
- - **Product hero**: GLB + `Environment` + key light + `ContactShadows`, `Float`
149
- idle, damped mouse parallax, scroll scrubs a 90° orbit. Poster until loaded.
150
- - **Gradient-mesh hero background**: one plane, fbm + domain-warp fragment shader
151
- mixing 3 palette colors, `uTime` 0.08, `uMouse` warps locally. ~120 lines, no
152
- model, no lighting — the best effort/impact ratio in this file.
153
- - **Point-cloud globe**: sphere-distributed points, shader-animated shimmer,
154
- arcs as `TubeGeometry`/fat lines between coords, slow idle rotation, drag to
155
- spin (damped).
156
- - **Scroll story**: `ScrollControls pages={4}` + camera on a `CatmullRomCurve3`
157
- path, DOM copy in `<Scroll html>`, one damped lookAt target per section.
1
+ # Dreative Specialist Skill — 3D, WebGL & Shaders
2
+
3
+ ## Contract
4
+
5
+ Follow `../references/SKILL_CONTRACT.md`. Dependencies: `ux`, `mobile`; add
6
+ `motion` when scroll/time drives the scene. Deliver a named spatial purpose,
7
+ asset/material source, staged berth, budgets, semantic/poster fallback, and
8
+ runtime evidence.
9
+
10
+ Load for real spatial subjects, WebGL, three.js/R3F, shaders, particles, globes,
11
+ or a plan-defined dimensional signature. 3D is expensive in bytes, battery, and
12
+ attention; it must serve the subject or concept.
13
+
14
+ ## 0. Explore before recipes
15
+
16
+ Record three original brand-native spatial concepts before opening
17
+ `../recipes/3d-recipes.md`. Begin with subject, spatial purpose, recurrence,
18
+ interaction, and berth—not a primitive or shader technique.
19
+
20
+ ## 1. Hard gates
21
+
22
+ - **No coded organic subjects (`3d.noCodedOrganic`).** Food, plants, fabric,
23
+ skin, liquid, wood, or other richly textured real objects never ship as crude
24
+ primitives. Use a real GLB, photoreal cutout, sourced photo, or cut the object.
25
+ - WebGL/context loss/loading/low power/mobile/reduced motion always has a real
26
+ poster or DOM fallback (`effects.runtimeFallback`, `motion.reducedMotion`).
27
+ - Canvas and traveling objects never cover content or controls; pointer events
28
+ and keyboard paths remain intact (`spatial.noOcclusion`, `ux.functional`).
29
+ - Text remains semantic DOM, not texture-baked. Content is visible without 3D.
30
+ - Models/textures/materials named as shipped assets exist and are tracked.
31
+ - Verification proves a live context/draw, interaction, performance, and
32
+ fallback behavior with structured evidence.
33
+
34
+ ## 2. Award spatial signature
35
+
36
+ `award.spatialSignature` requires one unmistakable dimensional or spatial
37
+ signature with depth, recurrence, input response, and visual dominance on
38
+ desktop and mobile.
39
+
40
+ The proven default is:
41
+
42
+ 1. a recognizable real GLB; or
43
+ 2. a photoreal transparent cutout billboard staged with parallax, restrained
44
+ rotation, contact shadow, rim light, and—when useful—multiple angles.
45
+
46
+ This default exists because dogfood coded/shader hero objects repeatedly read as
47
+ generic demos. Valid registered alternatives include spatial typography,
48
+ layered photographic depth, a persistent interactive scene instrument, or a
49
+ data-driven spatial structure that meets declared observable criteria.
50
+
51
+ A generic orb, blob, sphere, torus, or untextured coded form remains invalid as
52
+ a signature. `3d.signatureRecognizable` permits a brand-native abstract
53
+ instrument only when it has a nameable function, material identity, recurrence,
54
+ and input response; ambient decoration does not qualify.
55
+
56
+ ## 3. Staging and material
57
+
58
+ Every object gets a planned berth: section/lane, space reserved by type/layout,
59
+ crop, light direction, shadow/ground, travel states, and hidden states when no
60
+ safe berth exists. It never floats over other imagery unless genuinely
61
+ composited with matched light and cast/contact shadow.
62
+
63
+ Realism comes from material and light, not geometry count:
64
+
65
+ - environment/IBL plus one coherent key direction;
66
+ - deliberate exposure/color management;
67
+ - contact/cast shadow or defensible weightlessness;
68
+ - texture/normal/roughness or a custom procedural shader for visible coded
69
+ geometry;
70
+ - camera FOV/framing appropriate to the subject;
71
+ - damped input and subtle idle behavior.
72
+
73
+ ## 4. Architecture
74
+
75
+ React uses R3F + drei unless the existing stack strongly dictates otherwise;
76
+ one simple shader plane may use OGL/three.js. Lazy-load the whole spatial bundle
77
+ outside the critical path. One scene owns related planes/objects. Reuse vectors
78
+ and buffers; avoid allocations in render loops.
79
+
80
+ Models use optimized GLB/glTF with measured bytes/triangles and a poster during
81
+ load. Particles use points/instancing, not mesh-per-particle. DOM-synced media
82
+ planes keep semantic source media for layout and fallback.
83
+
84
+ ## 5. Performance and verification
85
+
86
+ - Cap DPR and complexity; pause off-screen/hidden work.
87
+ - Mobile reduces particles/post effects or uses a purpose-designed poster.
88
+ - Reduced motion renders a stable, intentional frame.
89
+ - Dispose imperative resources and test route transitions/context restoration.
90
+ - Record transferred weight, frame-time/FPS sample, context/draw evidence,
91
+ object/material identity, desktop/mobile screenshots, input response, and
92
+ poster/context-loss fallback.
93
+
94
+ Recipe reference: `../recipes/3d-recipes.md`, after concept exploration only.