bsmnt 0.0.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.
Files changed (98) hide show
  1. package/.changeset/2026-02-11-test-patch-bump.md +5 -0
  2. package/.changeset/README.md +10 -0
  3. package/.changeset/config.json +16 -0
  4. package/.cursor/rules/README.md +184 -0
  5. package/.cursor/rules/architecture.mdc +437 -0
  6. package/.cursor/rules/components.mdc +436 -0
  7. package/.cursor/rules/integrations.mdc +447 -0
  8. package/.cursor/rules/main.mdc +278 -0
  9. package/.cursor/rules/styling.mdc +433 -0
  10. package/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  11. package/.github/workflows/.gitkeep +0 -0
  12. package/.github/workflows/ci.yml +37 -0
  13. package/.github/workflows/release.yml +54 -0
  14. package/.tldr/cache/call_graph.json +7 -0
  15. package/.tldr/languages.json +6 -0
  16. package/.tldr/status +1 -0
  17. package/.tldrignore +84 -0
  18. package/.vscode/extensions.json +20 -0
  19. package/.vscode/settings.json +98 -0
  20. package/CHANGELOG.md +13 -0
  21. package/CLAUDE.md +138 -0
  22. package/README.md +176 -0
  23. package/bin/index.js +262 -0
  24. package/biome.json +44 -0
  25. package/bun.lock +496 -0
  26. package/changelog/04-02-26.md +86 -0
  27. package/changelog/05-02-26.md +101 -0
  28. package/changelog/09-02-26.md +83 -0
  29. package/docs/fix-studio-hydration.md +46 -0
  30. package/docs/plans/2026-01-29-sanity-smart-merge-design.md +196 -0
  31. package/docs/plans/2026-01-29-sanity-smart-merge-implementation.md +695 -0
  32. package/docs/sanity-setup-steps.md +199 -0
  33. package/integrations/basehub/README.md +3 -0
  34. package/integrations/sanity/app/api/draft-mode/disable/route.ts +7 -0
  35. package/integrations/sanity/app/api/draft-mode/enable/route.ts +21 -0
  36. package/integrations/sanity/app/api/revalidate/route.ts +37 -0
  37. package/integrations/sanity/app/layout.tsx +111 -0
  38. package/integrations/sanity/app/sitemap.ts +80 -0
  39. package/integrations/sanity/app/studio/[[...tool]]/page.tsx +8 -0
  40. package/integrations/sanity/app/studio/layout.tsx +7 -0
  41. package/integrations/sanity/components/ui/sanity-image/index.tsx +37 -0
  42. package/integrations/sanity/lib/integrations/README.md +58 -0
  43. package/integrations/sanity/lib/integrations/check-integration.ts +62 -0
  44. package/integrations/sanity/lib/integrations/sanity/README.md +144 -0
  45. package/integrations/sanity/lib/integrations/sanity/client.ts +30 -0
  46. package/integrations/sanity/lib/integrations/sanity/components/disable-draft-mode.tsx +29 -0
  47. package/integrations/sanity/lib/integrations/sanity/components/rich-text.tsx +73 -0
  48. package/integrations/sanity/lib/integrations/sanity/env.ts +38 -0
  49. package/integrations/sanity/lib/integrations/sanity/live/index.tsx +34 -0
  50. package/integrations/sanity/lib/integrations/sanity/queries.ts +99 -0
  51. package/integrations/sanity/lib/integrations/sanity/sanity.cli.ts +20 -0
  52. package/integrations/sanity/lib/integrations/sanity/sanity.config.ts +94 -0
  53. package/integrations/sanity/lib/integrations/sanity/sanity.types.ts +337 -0
  54. package/integrations/sanity/lib/integrations/sanity/schema.json +1850 -0
  55. package/integrations/sanity/lib/integrations/sanity/schemas/article.ts +132 -0
  56. package/integrations/sanity/lib/integrations/sanity/schemas/example.ts +203 -0
  57. package/integrations/sanity/lib/integrations/sanity/schemas/index.ts +37 -0
  58. package/integrations/sanity/lib/integrations/sanity/schemas/link.ts +127 -0
  59. package/integrations/sanity/lib/integrations/sanity/schemas/metadata.ts +68 -0
  60. package/integrations/sanity/lib/integrations/sanity/schemas/navigation.ts +39 -0
  61. package/integrations/sanity/lib/integrations/sanity/schemas/page.ts +77 -0
  62. package/integrations/sanity/lib/integrations/sanity/schemas/richText.ts +59 -0
  63. package/integrations/sanity/lib/integrations/sanity/structure.ts +5 -0
  64. package/integrations/sanity/lib/integrations/sanity/utils/image.ts +11 -0
  65. package/integrations/sanity/lib/integrations/sanity/utils/link.ts +61 -0
  66. package/integrations/sanity/lib/scripts/copy-sanity-mcp.ts +23 -0
  67. package/integrations/sanity/lib/scripts/generate-page.ts +310 -0
  68. package/integrations/sanity/lib/utils/metadata.ts +190 -0
  69. package/layers/experiment/components/layout/header/index.tsx +58 -0
  70. package/layers/experiment/components/layout/navigation-menu.tsx +127 -0
  71. package/layers/experiment/lib/constants.ts +12 -0
  72. package/layers/webgl/app/page.tsx +10 -0
  73. package/layers/webgl/components/webgl/canvas/dynamic.tsx +34 -0
  74. package/layers/webgl/components/webgl/canvas/index.tsx +43 -0
  75. package/layers/webgl/components/webgl/components/scene/index.tsx +21 -0
  76. package/layers/webgpu/.gitkeep +0 -0
  77. package/package.json +44 -0
  78. package/plugins/README.md +21 -0
  79. package/plugins/no-anchor-element.grit +11 -0
  80. package/plugins/no-relative-parent-imports.grit +6 -0
  81. package/plugins/no-unnecessary-forwardref.grit +5 -0
  82. package/src/commands/add-integration.js +325 -0
  83. package/src/commands/create.js +415 -0
  84. package/src/commands/setup-sanity.js +426 -0
  85. package/src/commands/worktree.js +805 -0
  86. package/src/mergers/check-integration-merger.js +105 -0
  87. package/src/mergers/config.js +137 -0
  88. package/src/mergers/index.js +355 -0
  89. package/src/mergers/layout-merger.js +223 -0
  90. package/src/mergers/next-config-merger.js +63 -0
  91. package/src/mergers/sitemap-merger.js +121 -0
  92. package/tasks/prd-next-starter-dynamic-layers.md +184 -0
  93. package/tasks/prd.json +153 -0
  94. package/tasks/progress.txt +115 -0
  95. package/template-hooks/use-battery.ts +126 -0
  96. package/template-hooks/use-device-perf.ts +184 -0
  97. package/template-hooks/use-intersection-observer.ts +32 -0
  98. package/template-hooks/use-media.ts +33 -0
@@ -0,0 +1,436 @@
1
+ ---
2
+ alwaysApply: true
3
+ ---
4
+ ---
5
+ description: React component patterns and WebGL integration
6
+ globs: *.tsx, *.jsx, *.js, *.ts
7
+ ---
8
+
9
+ # Component Guidelines
10
+
11
+ ## Imports and Dependencies
12
+
13
+ ### Utility Functions
14
+ Always use `cn` from `@/styles/cn` for className conditionals
15
+
16
+ ```tsx
17
+ import { cn } from '@/styles/cn'
18
+
19
+ function MyComponent({ className }) {
20
+ return <div className={cn(s.component, className)} />
21
+ }
22
+ ```
23
+
24
+ ### Animation Libraries
25
+ - Use `motion` for animations
26
+ - Use `react-use` for DOM utilities
27
+
28
+ ## Component Structure
29
+
30
+ ### CSS Modules
31
+ Use CSS modules for component styling. Import styles as `s`
32
+
33
+ ```tsx
34
+ import s from './component-name.module.css'
35
+ ```
36
+
37
+ ### Client Components
38
+ Add 'use client' directive for client components
39
+
40
+ ```tsx
41
+ 'use client'
42
+
43
+ import { useState } from 'react'
44
+ ```
45
+
46
+ ### Props Interface
47
+ Define props interface at the top of the file. Extend HTML attributes when appropriate.
48
+
49
+ ```tsx
50
+ import type { ComponentProps } from 'react'
51
+
52
+ interface ButtonProps extends ComponentProps<'button'> {
53
+ variant?: 'primary' | 'secondary'
54
+ size?: 'sm' | 'md' | 'lg'
55
+ }
56
+ ```
57
+
58
+ ### React 19 Ref Handling
59
+ In React 19, ref is passed as a regular prop (no forwardRef needed)
60
+
61
+ ```tsx
62
+ // Old pattern (React 18)
63
+ // const Button = forwardRef<HTMLButtonElement, ButtonProps>(...)
64
+
65
+ // New pattern (React 19)
66
+ function Button({ ref, variant = 'primary', ...props }: ButtonProps & { ref?: React.Ref<HTMLButtonElement> }) {
67
+ return <button ref={ref} {...props} />
68
+ }
69
+ ```
70
+
71
+ ### Default Exports
72
+ Use named function declarations for components. Export the component as default.
73
+
74
+ ```tsx
75
+ function Button({ variant = 'primary', size = 'md', ...props }: ButtonProps) {
76
+ // component logic
77
+ }
78
+
79
+ export default Button
80
+ ```
81
+
82
+ ## Form Components
83
+
84
+ -- TODO: Add form handling rules
85
+
86
+ ### Server Actions
87
+ Use Server Actions for form submissions when possible. Implement proper error handling.
88
+
89
+ ```tsx
90
+ async function submitForm(formData: FormData) {
91
+ 'use server'
92
+ // server-side logic
93
+ }
94
+ ```
95
+
96
+ ## Responsive Design
97
+
98
+ ### Device Detection
99
+ Use `useDeviceDetection` hook from `@/hooks/use-device-detection` for device specific logic
100
+
101
+ ```tsx
102
+ import { useDeviceDetection } from '@/hooks/use-device-detection'
103
+
104
+ function ResponsiveComponent() {
105
+ const { isMobile } = useDeviceDetection()
106
+ return isMobile ? <MobileVersion /> : <DesktopVersion />
107
+ }
108
+ ```
109
+
110
+ ### Media Breakpoints
111
+ Use `useMediaBreakpoint` hook from `@/hooks/use-media-breakpoint` for media breakpoints detection
112
+
113
+ ```tsx
114
+ import { useMediaBreakpoint } from '@/hooks/use-media-breakpoint'
115
+
116
+ function ResponsiveComponent() {
117
+ const isDesktop = useMediaBreakpoint('desktop')
118
+ return isDesktop ? <DesktopVersion /> : <MobileVersion />
119
+ }
120
+ ```
121
+
122
+ ### Viewport Units
123
+ Use custom viewport units for responsive values (see styling.mdc for details)
124
+
125
+ ```css
126
+ .element {
127
+ width: tovw(150);
128
+ margin-top: torem(100);
129
+ }
130
+ ```
131
+
132
+ ## Performance Best Practices
133
+
134
+ ### Code Splitting
135
+ Use `next/dynamic` for heavy components
136
+
137
+ ```tsx
138
+ import dynamic from 'next/dynamic'
139
+
140
+ const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
141
+ loading: () => <div>Loading...</div>,
142
+ ssr: false // if needed
143
+ })
144
+ ```
145
+
146
+ ### Memoization
147
+ See main.mdc for React Compiler guidance - manual memoization is rarely needed.
148
+
149
+ ## Error Handling
150
+
151
+ ### Error Boundaries
152
+ Implement error boundaries for critical sections. Provide meaningful fallback UI.
153
+
154
+ ### Loading States
155
+ Always handle loading states. Use Suspense boundaries where appropriate.
156
+
157
+ ---
158
+
159
+ # WebGL Components
160
+
161
+ ## React Three Fiber Setup
162
+
163
+ ### Canvas Component
164
+ -- TODO: Add Canvas component rules
165
+
166
+ ## WebGL File Organization
167
+
168
+ Separate WebGL logic into `webgl.tsx` files. Keep React logic in main component files.
169
+
170
+ ```
171
+ components/
172
+ scene/
173
+ index.tsx # React component
174
+ webgl.tsx # Three.js logic
175
+ scene.module.css # Styles
176
+ ```
177
+
178
+ ### WebGL Component Pattern
179
+
180
+ ```tsx
181
+ // scene/webgl.tsx
182
+ import { useFrame } from '@react-three/fiber'
183
+ import { useRef } from 'react'
184
+ import type { Mesh } from 'three'
185
+
186
+ export default function SceneWebGL() {
187
+ const meshRef = useRef<Mesh>(null)
188
+
189
+ useFrame((state, delta) => {
190
+ if (meshRef.current) {
191
+ meshRef.current.rotation.y += delta
192
+ }
193
+ })
194
+
195
+ // Simple logs are auto-stripped in production by Next.js
196
+ console.log('SceneWebGL rendered')
197
+
198
+ return (
199
+ <mesh ref={meshRef}>
200
+ <boxGeometry args={[1, 1, 1]} />
201
+ <meshStandardMaterial color="hotpink" />
202
+ </mesh>
203
+ )
204
+ }
205
+ ```
206
+
207
+ ## Drei Components
208
+
209
+ ### Common Helpers
210
+ Use Drei components for common functionality
211
+
212
+ ```tsx
213
+ import {
214
+ OrbitControls,
215
+ PerspectiveCamera,
216
+ Environment,
217
+ useGLTF,
218
+ useTexture
219
+ } from '@react-three/drei'
220
+ ```
221
+
222
+ ### Loading Assets
223
+ Preload assets using Drei hooks. Implement proper loading states.
224
+
225
+ ```tsx
226
+ // Preload in separate component
227
+ function Preload() {
228
+ const start = performance.now()
229
+ useGLTF.preload('/models/model.glb')
230
+ useTexture.preload('/textures/texture.jpg')
231
+ // Console logs auto-stripped in production by Next.js
232
+ console.log(`Preload took ${performance.now() - start}ms`)
233
+ return null
234
+ }
235
+ ```
236
+
237
+ ## Custom Shaders
238
+
239
+ ### Shader Materials
240
+ Use template literals for GLSL. Implement proper uniforms.
241
+
242
+ ```tsx
243
+ import { shaderMaterial } from '@react-three/drei'
244
+ import { extend } from '@react-three/fiber'
245
+
246
+ const CustomMaterial = shaderMaterial(
247
+ { uTime: 0, uColor: new THREE.Color(0.0, 0.0, 0.0) },
248
+ vertexShader,
249
+ fragmentShader
250
+ )
251
+
252
+ extend({ CustomMaterial })
253
+ ```
254
+
255
+ ### GLSL Best Practices
256
+ - Keep shaders in separate files when complex
257
+ - Use proper precision qualifiers
258
+ - Comment complex calculations
259
+
260
+ ```glsl
261
+ precision mediump float;
262
+
263
+ uniform float uTime;
264
+ varying vec2 vUv;
265
+
266
+ void main() {
267
+ // Shader logic
268
+ }
269
+ ```
270
+
271
+ ## Animation & Interaction
272
+
273
+ ### Animation Loops
274
+ Use `useFrame` for frame-based animations. Consider performance impact.
275
+
276
+ ```tsx
277
+ useFrame((state, delta) => {
278
+ // Animation logic
279
+ }, priority) // Lower priority = runs first
280
+ ```
281
+
282
+ ### Interaction
283
+ Use Drei's interaction helpers. Implement proper hover/click states.
284
+
285
+ ```tsx
286
+ import { useCursor } from '@react-three/drei'
287
+
288
+ function InteractiveObject() {
289
+ const [hovered, setHovered] = useState(false)
290
+ useCursor(hovered)
291
+
292
+ return (
293
+ <mesh
294
+ onPointerOver={() => setHovered(true)}
295
+ onPointerOut={() => setHovered(false)}
296
+ >
297
+ {/* geometry and material */}
298
+ </mesh>
299
+ )
300
+ }
301
+ ```
302
+
303
+ ## Post-Processing
304
+
305
+ ### Effect Composer
306
+ Use postprocessing library for effects. Chain effects efficiently.
307
+
308
+ ```tsx
309
+ import { EffectComposer, Bloom, ChromaticAberration } from '@react-three/postprocessing'
310
+
311
+ function Effects() {
312
+ return (
313
+ <EffectComposer>
314
+ <Bloom intensity={1.5} />
315
+ <ChromaticAberration offset={[0.002, 0.002]} />
316
+ </EffectComposer>
317
+ )
318
+ }
319
+ ```
320
+
321
+ ### Performance Considerations
322
+ - Limit number of passes
323
+ - Use lower resolution for effects when possible
324
+ - Profile performance impact
325
+
326
+ ## WebGL Best Practices
327
+
328
+ ### Memory Management
329
+ Dispose of geometries and materials when components unmount. Clean up in useEffect return for complex resources. React Compiler handles most cleanup automatically.
330
+
331
+ ```tsx
332
+ useEffect(() => {
333
+ // Only for complex resources that need explicit disposal
334
+ return () => {
335
+ geometry.dispose()
336
+ material.dispose()
337
+ texture.dispose()
338
+ }
339
+ }, [geometry, material, texture])
340
+ ```
341
+
342
+ ### Performance Optimization
343
+ See main.mdc for React Compiler guidance. For WebGL-specific object instantiation, always use `useRef`:
344
+
345
+ ```tsx
346
+ // ⚠️ EXCEPTION: Object instantiation MUST use useRef to prevent infinite loops
347
+ // Creating new objects on every render creates new references that trigger effects
348
+
349
+ // ❌ DON'T: This causes infinite re-renders
350
+ const flowmap = new Flowmap()
351
+
352
+ // ✅ DO: Use useRef for object instantiation
353
+ const flowmapRef = useRef<Flowmap | null>(null)
354
+ if (!flowmapRef.current) {
355
+ flowmapRef.current = new Flowmap(gl, { size: 128 })
356
+ }
357
+ const flowmap = flowmapRef.current
358
+ ```
359
+
360
+ ### Responsive Design
361
+ Handle window resizing. Adjust quality based on device capabilities.
362
+
363
+ ```tsx
364
+ const { viewport } = useThree()
365
+ // Use viewport.width, viewport.height for responsive sizing
366
+ ```
367
+
368
+ ## React 19.2 Activity Integration
369
+
370
+ Use `<Activity />` to optimize WebGL performance by deferring off-screen scenes:
371
+
372
+ ```tsx
373
+ import { Activity, useEffect, useRef, useState } from 'react'
374
+ import { useRect } from 'hamo'
375
+ import { WebGLTunnel } from '@/lib/webgl/components/tunnel'
376
+
377
+ export function WebGLScene({ className }) {
378
+ const [setRectRef, rect] = useRect()
379
+ const [isVisible, setIsVisible] = useState(true)
380
+ const elementRef = useRef<HTMLDivElement | null>(null)
381
+
382
+ // Intersection Observer with 200px margin for pre-activation
383
+ useEffect(() => {
384
+ const element = elementRef.current
385
+ if (!element) return
386
+
387
+ const observer = new IntersectionObserver(
388
+ ([entry]) => setIsVisible(entry.isIntersecting),
389
+ { rootMargin: '200px' }
390
+ )
391
+
392
+ observer.observe(element)
393
+ return () => observer.disconnect()
394
+ }, [])
395
+
396
+ return (
397
+ // Wrap DOM container - defers rect tracking when off-screen
398
+ <Activity mode={isVisible ? 'visible' : 'hidden'}>
399
+ <div ref={(el) => { setRectRef(el); elementRef.current = el }} className={className}>
400
+ {/* WebGL content goes in WebGLTunnel (no Activity wrapper needed) */}
401
+ <WebGLTunnel>
402
+ <WebGLComponent rect={rect} />
403
+ </WebGLTunnel>
404
+ </div>
405
+ </Activity>
406
+ )
407
+ }
408
+ ```
409
+
410
+ **Pattern**: `<Activity />` → DOM container → `WebGLTunnel` → WebGL content
411
+
412
+ ### Debugging
413
+ - Use Theatre.js for animation debugging
414
+ - Enable WebGL inspector in development
415
+ - **Always gate debug UI components** - these are NOT auto-removed
416
+ - Simple console logs are auto-stripped in production by Next.js
417
+
418
+ ```tsx
419
+ // Simple logs: Auto-stripped in production
420
+ console.log('WebGL state:', { fps, drawCalls, triangles })
421
+
422
+ // Debug components: MUST be gated (not auto-removed)
423
+ {process.env.NODE_ENV === 'development' && <Stats />}
424
+ {process.env.NODE_ENV === 'development' && <Perf />}
425
+ ```
426
+
427
+ ### Mobile Optimization
428
+ - Reduce polygon count for mobile
429
+ - Use simpler shaders
430
+ - Implement touch controls
431
+
432
+ ```tsx
433
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
434
+ ```
435
+
436
+ Last updated: 2026-01-26