bsmnt 0.0.2 → 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.
Files changed (430) hide show
  1. package/.github/workflows/release.yml +2 -0
  2. package/CHANGELOG.md +21 -0
  3. package/CLAUDE.md +42 -23
  4. package/README.md +33 -11
  5. package/biome.json +1 -0
  6. package/bun.lock +1 -1
  7. package/docs/architecture.drawio +266 -0
  8. package/docs/architecture.mermaid +91 -0
  9. package/package.json +1 -1
  10. package/{bin → packages/cli/bin}/index.js +28 -27
  11. package/packages/cli/package.json +16 -0
  12. package/{src → packages/cli/src}/commands/add-integration.js +23 -25
  13. package/{src → packages/cli/src}/commands/create.js +104 -133
  14. package/packages/create-basement-app/integrations/basehub/config.js +21 -0
  15. package/packages/create-basement-app/integrations/sanity/config.js +46 -0
  16. package/{src → packages/create-basement-app/integrations/sanity}/mergers/check-integration-merger.js +1 -1
  17. package/{src → packages/create-basement-app/integrations/sanity}/mergers/layout-merger.js +1 -1
  18. package/{src → packages/create-basement-app/integrations/sanity}/mergers/sitemap-merger.js +1 -1
  19. package/packages/create-basement-app/package.json +10 -0
  20. package/packages/create-basement-app/src/configs/animations.js +28 -0
  21. package/packages/create-basement-app/src/index.js +15 -0
  22. package/packages/create-basement-app/src/mergers/check-integration-merger.js +105 -0
  23. package/{src → packages/create-basement-app/src}/mergers/config.js +1 -7
  24. package/{src → packages/create-basement-app/src}/mergers/index.js +87 -93
  25. package/packages/create-basement-app/src/mergers/layout-merger.js +223 -0
  26. package/packages/create-basement-app/src/mergers/sitemap-merger.js +121 -0
  27. package/packages/create-basement-app/template-hooks/config.js +38 -0
  28. package/packages/create-basement-app/templates/default/.biome/plugins/README.md +21 -0
  29. package/packages/create-basement-app/templates/default/.biome/plugins/no-anchor-element.grit +12 -0
  30. package/packages/create-basement-app/templates/default/.biome/plugins/no-relative-parent-imports.grit +10 -0
  31. package/packages/create-basement-app/templates/default/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  32. package/packages/create-basement-app/templates/default/.cursor/rules/README.md +184 -0
  33. package/packages/create-basement-app/templates/default/.cursor/rules/architecture.mdc +437 -0
  34. package/packages/create-basement-app/templates/default/.cursor/rules/components.mdc +436 -0
  35. package/packages/create-basement-app/templates/default/.cursor/rules/integrations.mdc +447 -0
  36. package/packages/create-basement-app/templates/default/.cursor/rules/main.mdc +278 -0
  37. package/packages/create-basement-app/templates/default/.cursor/rules/styling.mdc +433 -0
  38. package/packages/create-basement-app/templates/default/.editorconfig +40 -0
  39. package/packages/create-basement-app/templates/default/.env.example +81 -0
  40. package/packages/create-basement-app/templates/default/.gitattributes +19 -0
  41. package/packages/create-basement-app/templates/default/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  42. package/packages/create-basement-app/templates/default/.github/workflows/lighthouse-to-slack.yml +136 -0
  43. package/packages/create-basement-app/templates/default/.vscode/extensions.json +20 -0
  44. package/packages/create-basement-app/templates/default/.vscode/settings.json +105 -0
  45. package/packages/create-basement-app/templates/default/README.md +221 -0
  46. package/packages/create-basement-app/templates/default/_gitignore +67 -0
  47. package/packages/create-basement-app/templates/default/app/favicon.ico +0 -0
  48. package/packages/create-basement-app/templates/default/app/layout.tsx +104 -0
  49. package/packages/create-basement-app/templates/default/app/page.tsx +275 -0
  50. package/packages/create-basement-app/templates/default/app/robots.ts +15 -0
  51. package/packages/create-basement-app/templates/default/app/sitemap.ts +16 -0
  52. package/packages/create-basement-app/templates/default/biome.json +250 -0
  53. package/packages/create-basement-app/templates/default/components/basement.svg +1 -0
  54. package/packages/create-basement-app/templates/default/components/layout/footer/index.tsx +27 -0
  55. package/packages/create-basement-app/templates/default/components/layout/header/index.tsx +11 -0
  56. package/packages/create-basement-app/templates/default/components/layout/theme/index.tsx +66 -0
  57. package/packages/create-basement-app/templates/default/components/layout/wrapper/index.tsx +65 -0
  58. package/packages/create-basement-app/templates/default/components/ui/README.md +77 -0
  59. package/packages/create-basement-app/templates/default/components/ui/image/README.md +37 -0
  60. package/packages/create-basement-app/templates/default/components/ui/image/index.tsx +224 -0
  61. package/packages/create-basement-app/templates/default/components/ui/link/index.tsx +146 -0
  62. package/packages/create-basement-app/templates/default/lib/README.md +33 -0
  63. package/packages/create-basement-app/templates/default/lib/hooks/index.ts +12 -0
  64. package/packages/create-basement-app/templates/default/lib/hooks/use-device-detection.ts +81 -0
  65. package/packages/create-basement-app/templates/default/lib/hooks/use-media-breakpoint.ts +15 -0
  66. package/packages/create-basement-app/templates/default/lib/hooks/use-prefetch.ts +74 -0
  67. package/packages/create-basement-app/templates/default/lib/scripts/dev.ts +52 -0
  68. package/packages/create-basement-app/templates/default/lib/scripts/generate-component.ts +322 -0
  69. package/packages/create-basement-app/templates/default/lib/scripts/generate-page.ts +193 -0
  70. package/packages/create-basement-app/templates/default/lib/scripts/generate.ts +79 -0
  71. package/packages/create-basement-app/templates/default/lib/scripts/utils.ts +246 -0
  72. package/packages/create-basement-app/templates/default/lib/store/app.ts +11 -0
  73. package/packages/create-basement-app/templates/default/lib/store/index.ts +11 -0
  74. package/packages/create-basement-app/templates/default/lib/styles/README.md +64 -0
  75. package/packages/create-basement-app/templates/default/lib/styles/cn.ts +7 -0
  76. package/packages/create-basement-app/templates/default/lib/styles/colors.ts +63 -0
  77. package/packages/create-basement-app/templates/default/lib/styles/config.ts +34 -0
  78. package/packages/create-basement-app/templates/default/lib/styles/css/global.css +85 -0
  79. package/packages/create-basement-app/templates/default/lib/styles/css/index.css +6 -0
  80. package/packages/create-basement-app/templates/default/lib/styles/css/reset.css +166 -0
  81. package/packages/create-basement-app/templates/default/lib/styles/css/root.css +68 -0
  82. package/packages/create-basement-app/templates/default/lib/styles/css/tailwind.css +132 -0
  83. package/packages/create-basement-app/templates/default/lib/styles/easings.ts +21 -0
  84. package/packages/create-basement-app/templates/default/lib/styles/fonts.ts +28 -0
  85. package/packages/create-basement-app/templates/default/lib/styles/index.ts +12 -0
  86. package/packages/create-basement-app/templates/default/lib/styles/layout.mjs +27 -0
  87. package/packages/create-basement-app/templates/default/lib/styles/scripts/README.md +29 -0
  88. package/packages/create-basement-app/templates/default/lib/styles/scripts/generate-root.ts +57 -0
  89. package/packages/create-basement-app/templates/default/lib/styles/scripts/generate-tailwind.ts +162 -0
  90. package/packages/create-basement-app/templates/default/lib/styles/scripts/postcss-functions.mjs +168 -0
  91. package/packages/create-basement-app/templates/default/lib/styles/scripts/setup-styles.ts +24 -0
  92. package/packages/create-basement-app/templates/default/lib/styles/scripts/utils.ts +20 -0
  93. package/packages/create-basement-app/templates/default/lib/styles/typography.ts +36 -0
  94. package/packages/create-basement-app/templates/default/lib/utils/README.md +40 -0
  95. package/packages/create-basement-app/templates/default/lib/utils/css.d.ts +21 -0
  96. package/packages/create-basement-app/templates/default/lib/utils/easings.ts +240 -0
  97. package/packages/create-basement-app/templates/default/lib/utils/fetch.ts +84 -0
  98. package/packages/create-basement-app/templates/default/lib/utils/math.test.ts +221 -0
  99. package/packages/create-basement-app/templates/default/lib/utils/math.ts +236 -0
  100. package/packages/create-basement-app/templates/default/lib/utils/metadata.ts +126 -0
  101. package/packages/create-basement-app/templates/default/lib/utils/strings.test.ts +166 -0
  102. package/packages/create-basement-app/templates/default/lib/utils/strings.ts +246 -0
  103. package/packages/create-basement-app/templates/default/lib/utils/types.d.ts +15 -0
  104. package/packages/create-basement-app/templates/default/lib/utils/viewport.test.ts +256 -0
  105. package/packages/create-basement-app/templates/default/lib/utils/viewport.ts +193 -0
  106. package/packages/create-basement-app/templates/default/next.config.ts +142 -0
  107. package/packages/create-basement-app/templates/default/package.json +62 -0
  108. package/packages/create-basement-app/templates/default/postcss.config.mjs +42 -0
  109. package/packages/create-basement-app/templates/default/public/fonts/geist/Geist-Mono.woff2 +0 -0
  110. package/packages/create-basement-app/templates/default/tsconfig.json +43 -0
  111. package/packages/create-basement-app/templates/experiment/.biome/plugins/README.md +21 -0
  112. package/packages/create-basement-app/templates/experiment/.biome/plugins/no-anchor-element.grit +12 -0
  113. package/packages/create-basement-app/templates/experiment/.biome/plugins/no-relative-parent-imports.grit +10 -0
  114. package/packages/create-basement-app/templates/experiment/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  115. package/packages/create-basement-app/templates/experiment/.cursor/rules/README.md +184 -0
  116. package/packages/create-basement-app/templates/experiment/.cursor/rules/architecture.mdc +437 -0
  117. package/packages/create-basement-app/templates/experiment/.cursor/rules/components.mdc +436 -0
  118. package/packages/create-basement-app/templates/experiment/.cursor/rules/integrations.mdc +447 -0
  119. package/packages/create-basement-app/templates/experiment/.cursor/rules/main.mdc +278 -0
  120. package/packages/create-basement-app/templates/experiment/.cursor/rules/styling.mdc +433 -0
  121. package/packages/create-basement-app/templates/experiment/.editorconfig +40 -0
  122. package/packages/create-basement-app/templates/experiment/.env.example +81 -0
  123. package/packages/create-basement-app/templates/experiment/.gitattributes +19 -0
  124. package/packages/create-basement-app/templates/experiment/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  125. package/packages/create-basement-app/templates/experiment/.github/workflows/lighthouse-to-slack.yml +136 -0
  126. package/packages/create-basement-app/templates/experiment/.vscode/extensions.json +20 -0
  127. package/packages/create-basement-app/templates/experiment/.vscode/settings.json +105 -0
  128. package/packages/create-basement-app/templates/experiment/README.md +221 -0
  129. package/packages/create-basement-app/templates/experiment/_gitignore +67 -0
  130. package/packages/create-basement-app/templates/experiment/app/favicon.ico +0 -0
  131. package/packages/create-basement-app/templates/experiment/app/layout.tsx +104 -0
  132. package/packages/create-basement-app/templates/experiment/app/page.tsx +275 -0
  133. package/packages/create-basement-app/templates/experiment/app/robots.ts +15 -0
  134. package/packages/create-basement-app/templates/experiment/app/sitemap.ts +16 -0
  135. package/packages/create-basement-app/templates/experiment/biome.json +250 -0
  136. package/packages/create-basement-app/templates/experiment/components/basement.svg +1 -0
  137. package/packages/create-basement-app/templates/experiment/components/layout/footer/index.tsx +27 -0
  138. package/packages/create-basement-app/templates/experiment/components/layout/header/index.tsx +58 -0
  139. package/packages/create-basement-app/templates/experiment/components/layout/navigation-menu.tsx +127 -0
  140. package/packages/create-basement-app/templates/experiment/components/layout/theme/index.tsx +66 -0
  141. package/packages/create-basement-app/templates/experiment/components/layout/wrapper/index.tsx +65 -0
  142. package/packages/create-basement-app/templates/experiment/components/ui/README.md +77 -0
  143. package/packages/create-basement-app/templates/experiment/components/ui/image/README.md +37 -0
  144. package/packages/create-basement-app/templates/experiment/components/ui/image/index.tsx +224 -0
  145. package/packages/create-basement-app/templates/experiment/components/ui/link/index.tsx +146 -0
  146. package/packages/create-basement-app/templates/experiment/lib/README.md +33 -0
  147. package/packages/create-basement-app/templates/experiment/lib/constants.ts +12 -0
  148. package/packages/create-basement-app/templates/experiment/lib/hooks/index.ts +12 -0
  149. package/packages/create-basement-app/templates/experiment/lib/hooks/use-device-detection.ts +81 -0
  150. package/packages/create-basement-app/templates/experiment/lib/hooks/use-media-breakpoint.ts +15 -0
  151. package/packages/create-basement-app/templates/experiment/lib/hooks/use-prefetch.ts +74 -0
  152. package/packages/create-basement-app/templates/experiment/lib/integrations/.gitkeep +0 -0
  153. package/packages/create-basement-app/templates/experiment/lib/scripts/dev.ts +52 -0
  154. package/packages/create-basement-app/templates/experiment/lib/scripts/generate-component.ts +322 -0
  155. package/packages/create-basement-app/templates/experiment/lib/scripts/generate-page.ts +193 -0
  156. package/packages/create-basement-app/templates/experiment/lib/scripts/generate.ts +79 -0
  157. package/packages/create-basement-app/templates/experiment/lib/scripts/utils.ts +246 -0
  158. package/packages/create-basement-app/templates/experiment/lib/store/app.ts +11 -0
  159. package/packages/create-basement-app/templates/experiment/lib/store/index.ts +11 -0
  160. package/packages/create-basement-app/templates/experiment/lib/styles/README.md +64 -0
  161. package/packages/create-basement-app/templates/experiment/lib/styles/cn.ts +7 -0
  162. package/packages/create-basement-app/templates/experiment/lib/styles/colors.ts +63 -0
  163. package/packages/create-basement-app/templates/experiment/lib/styles/config.ts +34 -0
  164. package/packages/create-basement-app/templates/experiment/lib/styles/css/global.css +85 -0
  165. package/packages/create-basement-app/templates/experiment/lib/styles/css/index.css +6 -0
  166. package/packages/create-basement-app/templates/experiment/lib/styles/css/reset.css +166 -0
  167. package/packages/create-basement-app/templates/experiment/lib/styles/css/root.css +68 -0
  168. package/packages/create-basement-app/templates/experiment/lib/styles/css/tailwind.css +132 -0
  169. package/packages/create-basement-app/templates/experiment/lib/styles/easings.ts +21 -0
  170. package/packages/create-basement-app/templates/experiment/lib/styles/fonts.ts +28 -0
  171. package/packages/create-basement-app/templates/experiment/lib/styles/index.ts +12 -0
  172. package/packages/create-basement-app/templates/experiment/lib/styles/layout.mjs +27 -0
  173. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/README.md +29 -0
  174. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/generate-root.ts +57 -0
  175. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/generate-tailwind.ts +162 -0
  176. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/postcss-functions.mjs +168 -0
  177. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/setup-styles.ts +24 -0
  178. package/packages/create-basement-app/templates/experiment/lib/styles/scripts/utils.ts +20 -0
  179. package/packages/create-basement-app/templates/experiment/lib/styles/typography.ts +36 -0
  180. package/packages/create-basement-app/templates/experiment/lib/utils/README.md +40 -0
  181. package/packages/create-basement-app/templates/experiment/lib/utils/css.d.ts +21 -0
  182. package/packages/create-basement-app/templates/experiment/lib/utils/easings.ts +240 -0
  183. package/packages/create-basement-app/templates/experiment/lib/utils/fetch.ts +84 -0
  184. package/packages/create-basement-app/templates/experiment/lib/utils/math.test.ts +221 -0
  185. package/packages/create-basement-app/templates/experiment/lib/utils/math.ts +236 -0
  186. package/packages/create-basement-app/templates/experiment/lib/utils/metadata.ts +126 -0
  187. package/packages/create-basement-app/templates/experiment/lib/utils/strings.test.ts +166 -0
  188. package/packages/create-basement-app/templates/experiment/lib/utils/strings.ts +246 -0
  189. package/packages/create-basement-app/templates/experiment/lib/utils/types.d.ts +15 -0
  190. package/packages/create-basement-app/templates/experiment/lib/utils/viewport.test.ts +256 -0
  191. package/packages/create-basement-app/templates/experiment/lib/utils/viewport.ts +193 -0
  192. package/packages/create-basement-app/templates/experiment/next.config.ts +142 -0
  193. package/packages/create-basement-app/templates/experiment/package.json +69 -0
  194. package/packages/create-basement-app/templates/experiment/postcss.config.mjs +42 -0
  195. package/packages/create-basement-app/templates/experiment/public/fonts/geist/Geist-Mono.woff2 +0 -0
  196. package/packages/create-basement-app/templates/experiment/tsconfig.json +43 -0
  197. package/packages/create-basement-app/templates/webgl/.biome/plugins/README.md +21 -0
  198. package/packages/create-basement-app/templates/webgl/.biome/plugins/no-anchor-element.grit +12 -0
  199. package/packages/create-basement-app/templates/webgl/.biome/plugins/no-relative-parent-imports.grit +10 -0
  200. package/packages/create-basement-app/templates/webgl/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  201. package/packages/create-basement-app/templates/webgl/.cursor/rules/README.md +184 -0
  202. package/packages/create-basement-app/templates/webgl/.cursor/rules/architecture.mdc +437 -0
  203. package/packages/create-basement-app/templates/webgl/.cursor/rules/components.mdc +436 -0
  204. package/packages/create-basement-app/templates/webgl/.cursor/rules/integrations.mdc +447 -0
  205. package/packages/create-basement-app/templates/webgl/.cursor/rules/main.mdc +278 -0
  206. package/packages/create-basement-app/templates/webgl/.cursor/rules/styling.mdc +433 -0
  207. package/packages/create-basement-app/templates/webgl/.editorconfig +40 -0
  208. package/packages/create-basement-app/templates/webgl/.env.example +81 -0
  209. package/packages/create-basement-app/templates/webgl/.gitattributes +19 -0
  210. package/packages/create-basement-app/templates/webgl/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  211. package/packages/create-basement-app/templates/webgl/.github/workflows/lighthouse-to-slack.yml +136 -0
  212. package/packages/create-basement-app/templates/webgl/.vscode/extensions.json +20 -0
  213. package/packages/create-basement-app/templates/webgl/.vscode/settings.json +105 -0
  214. package/packages/create-basement-app/templates/webgl/README.md +221 -0
  215. package/packages/create-basement-app/templates/webgl/_gitignore +67 -0
  216. package/packages/create-basement-app/templates/webgl/app/favicon.ico +0 -0
  217. package/packages/create-basement-app/templates/webgl/app/layout.tsx +104 -0
  218. package/packages/create-basement-app/templates/webgl/app/page.tsx +10 -0
  219. package/packages/create-basement-app/templates/webgl/app/robots.ts +15 -0
  220. package/packages/create-basement-app/templates/webgl/app/sitemap.ts +16 -0
  221. package/packages/create-basement-app/templates/webgl/biome.json +250 -0
  222. package/packages/create-basement-app/templates/webgl/components/basement.svg +1 -0
  223. package/packages/create-basement-app/templates/webgl/components/layout/footer/index.tsx +27 -0
  224. package/packages/create-basement-app/templates/webgl/components/layout/header/index.tsx +11 -0
  225. package/packages/create-basement-app/templates/webgl/components/layout/theme/index.tsx +66 -0
  226. package/packages/create-basement-app/templates/webgl/components/layout/wrapper/index.tsx +65 -0
  227. package/packages/create-basement-app/templates/webgl/components/ui/README.md +77 -0
  228. package/packages/create-basement-app/templates/webgl/components/ui/image/README.md +37 -0
  229. package/packages/create-basement-app/templates/webgl/components/ui/image/index.tsx +224 -0
  230. package/packages/create-basement-app/templates/webgl/components/ui/link/index.tsx +146 -0
  231. package/packages/create-basement-app/templates/webgl/components/webgl/canvas/dynamic.tsx +34 -0
  232. package/packages/create-basement-app/templates/webgl/components/webgl/canvas/index.tsx +43 -0
  233. package/packages/create-basement-app/templates/webgl/components/webgl/components/scene/index.tsx +21 -0
  234. package/packages/create-basement-app/templates/webgl/lib/README.md +33 -0
  235. package/packages/create-basement-app/templates/webgl/lib/hooks/index.ts +12 -0
  236. package/packages/create-basement-app/templates/webgl/lib/hooks/use-device-detection.ts +81 -0
  237. package/packages/create-basement-app/templates/webgl/lib/hooks/use-media-breakpoint.ts +15 -0
  238. package/packages/create-basement-app/templates/webgl/lib/hooks/use-prefetch.ts +74 -0
  239. package/packages/create-basement-app/templates/webgl/lib/integrations/.gitkeep +0 -0
  240. package/packages/create-basement-app/templates/webgl/lib/scripts/dev.ts +52 -0
  241. package/packages/create-basement-app/templates/webgl/lib/scripts/generate-component.ts +322 -0
  242. package/packages/create-basement-app/templates/webgl/lib/scripts/generate-page.ts +193 -0
  243. package/packages/create-basement-app/templates/webgl/lib/scripts/generate.ts +79 -0
  244. package/packages/create-basement-app/templates/webgl/lib/scripts/utils.ts +246 -0
  245. package/packages/create-basement-app/templates/webgl/lib/store/app.ts +11 -0
  246. package/packages/create-basement-app/templates/webgl/lib/store/index.ts +11 -0
  247. package/packages/create-basement-app/templates/webgl/lib/styles/README.md +64 -0
  248. package/packages/create-basement-app/templates/webgl/lib/styles/cn.ts +7 -0
  249. package/packages/create-basement-app/templates/webgl/lib/styles/colors.ts +63 -0
  250. package/packages/create-basement-app/templates/webgl/lib/styles/config.ts +34 -0
  251. package/packages/create-basement-app/templates/webgl/lib/styles/css/global.css +85 -0
  252. package/packages/create-basement-app/templates/webgl/lib/styles/css/index.css +6 -0
  253. package/packages/create-basement-app/templates/webgl/lib/styles/css/reset.css +166 -0
  254. package/packages/create-basement-app/templates/webgl/lib/styles/css/root.css +68 -0
  255. package/packages/create-basement-app/templates/webgl/lib/styles/css/tailwind.css +132 -0
  256. package/packages/create-basement-app/templates/webgl/lib/styles/easings.ts +21 -0
  257. package/packages/create-basement-app/templates/webgl/lib/styles/fonts.ts +28 -0
  258. package/packages/create-basement-app/templates/webgl/lib/styles/index.ts +12 -0
  259. package/packages/create-basement-app/templates/webgl/lib/styles/layout.mjs +27 -0
  260. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/README.md +29 -0
  261. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/generate-root.ts +57 -0
  262. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/generate-tailwind.ts +162 -0
  263. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/postcss-functions.mjs +168 -0
  264. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/setup-styles.ts +24 -0
  265. package/packages/create-basement-app/templates/webgl/lib/styles/scripts/utils.ts +20 -0
  266. package/packages/create-basement-app/templates/webgl/lib/styles/typography.ts +36 -0
  267. package/packages/create-basement-app/templates/webgl/lib/utils/README.md +40 -0
  268. package/packages/create-basement-app/templates/webgl/lib/utils/css.d.ts +21 -0
  269. package/packages/create-basement-app/templates/webgl/lib/utils/easings.ts +240 -0
  270. package/packages/create-basement-app/templates/webgl/lib/utils/fetch.ts +84 -0
  271. package/packages/create-basement-app/templates/webgl/lib/utils/math.test.ts +221 -0
  272. package/packages/create-basement-app/templates/webgl/lib/utils/math.ts +236 -0
  273. package/packages/create-basement-app/templates/webgl/lib/utils/metadata.ts +126 -0
  274. package/packages/create-basement-app/templates/webgl/lib/utils/strings.test.ts +166 -0
  275. package/packages/create-basement-app/templates/webgl/lib/utils/strings.ts +246 -0
  276. package/packages/create-basement-app/templates/webgl/lib/utils/types.d.ts +15 -0
  277. package/packages/create-basement-app/templates/webgl/lib/utils/viewport.test.ts +256 -0
  278. package/packages/create-basement-app/templates/webgl/lib/utils/viewport.ts +193 -0
  279. package/packages/create-basement-app/templates/webgl/next.config.ts +142 -0
  280. package/packages/create-basement-app/templates/webgl/package.json +68 -0
  281. package/packages/create-basement-app/templates/webgl/postcss.config.mjs +42 -0
  282. package/packages/create-basement-app/templates/webgl/public/fonts/geist/Geist-Mono.woff2 +0 -0
  283. package/packages/create-basement-app/templates/webgl/tsconfig.json +43 -0
  284. package/packages/create-basement-app/templates/webgpu/.biome/plugins/README.md +21 -0
  285. package/packages/create-basement-app/templates/webgpu/.biome/plugins/no-anchor-element.grit +12 -0
  286. package/packages/create-basement-app/templates/webgpu/.biome/plugins/no-relative-parent-imports.grit +10 -0
  287. package/packages/create-basement-app/templates/webgpu/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  288. package/packages/create-basement-app/templates/webgpu/.cursor/rules/README.md +184 -0
  289. package/packages/create-basement-app/templates/webgpu/.cursor/rules/architecture.mdc +437 -0
  290. package/packages/create-basement-app/templates/webgpu/.cursor/rules/components.mdc +436 -0
  291. package/packages/create-basement-app/templates/webgpu/.cursor/rules/integrations.mdc +447 -0
  292. package/packages/create-basement-app/templates/webgpu/.cursor/rules/main.mdc +278 -0
  293. package/packages/create-basement-app/templates/webgpu/.cursor/rules/styling.mdc +433 -0
  294. package/packages/create-basement-app/templates/webgpu/.editorconfig +40 -0
  295. package/packages/create-basement-app/templates/webgpu/.env.example +81 -0
  296. package/packages/create-basement-app/templates/webgpu/.gitattributes +19 -0
  297. package/packages/create-basement-app/templates/webgpu/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  298. package/packages/create-basement-app/templates/webgpu/.github/workflows/lighthouse-to-slack.yml +136 -0
  299. package/packages/create-basement-app/templates/webgpu/.vscode/extensions.json +20 -0
  300. package/packages/create-basement-app/templates/webgpu/.vscode/settings.json +105 -0
  301. package/packages/create-basement-app/templates/webgpu/README.md +221 -0
  302. package/packages/create-basement-app/templates/webgpu/_gitignore +67 -0
  303. package/packages/create-basement-app/templates/webgpu/app/favicon.ico +0 -0
  304. package/packages/create-basement-app/templates/webgpu/app/layout.tsx +104 -0
  305. package/packages/create-basement-app/templates/webgpu/app/page.tsx +275 -0
  306. package/packages/create-basement-app/templates/webgpu/app/robots.ts +15 -0
  307. package/packages/create-basement-app/templates/webgpu/app/sitemap.ts +16 -0
  308. package/packages/create-basement-app/templates/webgpu/biome.json +250 -0
  309. package/packages/create-basement-app/templates/webgpu/components/basement.svg +1 -0
  310. package/packages/create-basement-app/templates/webgpu/components/layout/footer/index.tsx +27 -0
  311. package/packages/create-basement-app/templates/webgpu/components/layout/header/index.tsx +11 -0
  312. package/packages/create-basement-app/templates/webgpu/components/layout/theme/index.tsx +66 -0
  313. package/packages/create-basement-app/templates/webgpu/components/layout/wrapper/index.tsx +65 -0
  314. package/packages/create-basement-app/templates/webgpu/components/ui/README.md +77 -0
  315. package/packages/create-basement-app/templates/webgpu/components/ui/image/README.md +37 -0
  316. package/packages/create-basement-app/templates/webgpu/components/ui/image/index.tsx +224 -0
  317. package/packages/create-basement-app/templates/webgpu/components/ui/link/index.tsx +146 -0
  318. package/packages/create-basement-app/templates/webgpu/lib/README.md +33 -0
  319. package/packages/create-basement-app/templates/webgpu/lib/hooks/index.ts +12 -0
  320. package/packages/create-basement-app/templates/webgpu/lib/hooks/use-device-detection.ts +81 -0
  321. package/packages/create-basement-app/templates/webgpu/lib/hooks/use-media-breakpoint.ts +15 -0
  322. package/packages/create-basement-app/templates/webgpu/lib/hooks/use-prefetch.ts +74 -0
  323. package/packages/create-basement-app/templates/webgpu/lib/integrations/.gitkeep +0 -0
  324. package/packages/create-basement-app/templates/webgpu/lib/scripts/dev.ts +52 -0
  325. package/packages/create-basement-app/templates/webgpu/lib/scripts/generate-component.ts +322 -0
  326. package/packages/create-basement-app/templates/webgpu/lib/scripts/generate-page.ts +193 -0
  327. package/packages/create-basement-app/templates/webgpu/lib/scripts/generate.ts +79 -0
  328. package/packages/create-basement-app/templates/webgpu/lib/scripts/utils.ts +246 -0
  329. package/packages/create-basement-app/templates/webgpu/lib/store/app.ts +11 -0
  330. package/packages/create-basement-app/templates/webgpu/lib/store/index.ts +11 -0
  331. package/packages/create-basement-app/templates/webgpu/lib/styles/README.md +64 -0
  332. package/packages/create-basement-app/templates/webgpu/lib/styles/cn.ts +7 -0
  333. package/packages/create-basement-app/templates/webgpu/lib/styles/colors.ts +63 -0
  334. package/packages/create-basement-app/templates/webgpu/lib/styles/config.ts +34 -0
  335. package/packages/create-basement-app/templates/webgpu/lib/styles/css/global.css +85 -0
  336. package/packages/create-basement-app/templates/webgpu/lib/styles/css/index.css +6 -0
  337. package/packages/create-basement-app/templates/webgpu/lib/styles/css/reset.css +166 -0
  338. package/packages/create-basement-app/templates/webgpu/lib/styles/css/root.css +68 -0
  339. package/packages/create-basement-app/templates/webgpu/lib/styles/css/tailwind.css +132 -0
  340. package/packages/create-basement-app/templates/webgpu/lib/styles/easings.ts +21 -0
  341. package/packages/create-basement-app/templates/webgpu/lib/styles/fonts.ts +28 -0
  342. package/packages/create-basement-app/templates/webgpu/lib/styles/index.ts +12 -0
  343. package/packages/create-basement-app/templates/webgpu/lib/styles/layout.mjs +27 -0
  344. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/README.md +29 -0
  345. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/generate-root.ts +57 -0
  346. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/generate-tailwind.ts +162 -0
  347. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/postcss-functions.mjs +168 -0
  348. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/setup-styles.ts +24 -0
  349. package/packages/create-basement-app/templates/webgpu/lib/styles/scripts/utils.ts +20 -0
  350. package/packages/create-basement-app/templates/webgpu/lib/styles/typography.ts +36 -0
  351. package/packages/create-basement-app/templates/webgpu/lib/utils/README.md +40 -0
  352. package/packages/create-basement-app/templates/webgpu/lib/utils/css.d.ts +21 -0
  353. package/packages/create-basement-app/templates/webgpu/lib/utils/easings.ts +240 -0
  354. package/packages/create-basement-app/templates/webgpu/lib/utils/fetch.ts +84 -0
  355. package/packages/create-basement-app/templates/webgpu/lib/utils/math.test.ts +221 -0
  356. package/packages/create-basement-app/templates/webgpu/lib/utils/math.ts +236 -0
  357. package/packages/create-basement-app/templates/webgpu/lib/utils/metadata.ts +126 -0
  358. package/packages/create-basement-app/templates/webgpu/lib/utils/strings.test.ts +166 -0
  359. package/packages/create-basement-app/templates/webgpu/lib/utils/strings.ts +246 -0
  360. package/packages/create-basement-app/templates/webgpu/lib/utils/types.d.ts +15 -0
  361. package/packages/create-basement-app/templates/webgpu/lib/utils/viewport.test.ts +256 -0
  362. package/packages/create-basement-app/templates/webgpu/lib/utils/viewport.ts +193 -0
  363. package/packages/create-basement-app/templates/webgpu/next.config.ts +142 -0
  364. package/packages/create-basement-app/templates/webgpu/package.json +69 -0
  365. package/packages/create-basement-app/templates/webgpu/postcss.config.mjs +42 -0
  366. package/packages/create-basement-app/templates/webgpu/public/fonts/geist/Geist-Mono.woff2 +0 -0
  367. package/packages/create-basement-app/templates/webgpu/tsconfig.json +43 -0
  368. package/tasks/.last-branch +1 -0
  369. package/tasks/CLAUDE.md +104 -0
  370. package/tasks/archive/2026-02-09-next-starter-dynamic-layers/prd.json +153 -0
  371. package/tasks/archive/2026-02-09-next-starter-dynamic-layers/progress.txt +115 -0
  372. package/tasks/prd-project-restructure.md +375 -0
  373. package/tasks/prd.json +227 -91
  374. package/tasks/progress.txt +281 -87
  375. package/tasks/ralph.sh +113 -0
  376. package/layers/experiment/components/layout/header/index.tsx +0 -58
  377. package/layers/experiment/components/layout/navigation-menu.tsx +0 -127
  378. package/layers/experiment/lib/constants.ts +0 -12
  379. package/layers/webgl/app/page.tsx +0 -10
  380. package/layers/webgl/components/webgl/canvas/dynamic.tsx +0 -34
  381. package/layers/webgl/components/webgl/canvas/index.tsx +0 -43
  382. package/layers/webgl/components/webgl/components/scene/index.tsx +0 -21
  383. package/src/mergers/next-config-merger.js +0 -63
  384. /package/{src → packages/cli/src}/commands/setup-sanity.js +0 -0
  385. /package/{src → packages/cli/src}/commands/worktree.js +0 -0
  386. /package/{integrations/basehub → packages/create-basement-app/integrations/basehub/files}/README.md +0 -0
  387. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/api/draft-mode/disable/route.ts +0 -0
  388. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/api/draft-mode/enable/route.ts +0 -0
  389. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/api/revalidate/route.ts +0 -0
  390. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/layout.tsx +0 -0
  391. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/sitemap.ts +0 -0
  392. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/studio/[[...tool]]/page.tsx +0 -0
  393. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/app/studio/layout.tsx +0 -0
  394. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/components/ui/sanity-image/index.tsx +0 -0
  395. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/README.md +0 -0
  396. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/check-integration.ts +0 -0
  397. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/README.md +0 -0
  398. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/client.ts +0 -0
  399. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/components/disable-draft-mode.tsx +0 -0
  400. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/components/rich-text.tsx +0 -0
  401. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/env.ts +0 -0
  402. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/live/index.tsx +0 -0
  403. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/queries.ts +0 -0
  404. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/sanity.cli.ts +0 -0
  405. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/sanity.config.ts +0 -0
  406. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/sanity.types.ts +0 -0
  407. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schema.json +0 -0
  408. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/article.ts +0 -0
  409. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/example.ts +0 -0
  410. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/index.ts +0 -0
  411. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/link.ts +0 -0
  412. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/metadata.ts +0 -0
  413. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/navigation.ts +0 -0
  414. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/page.ts +0 -0
  415. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/schemas/richText.ts +0 -0
  416. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/structure.ts +0 -0
  417. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/utils/image.ts +0 -0
  418. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/integrations/sanity/utils/link.ts +0 -0
  419. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/scripts/copy-sanity-mcp.ts +0 -0
  420. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/scripts/generate-page.ts +0 -0
  421. /package/{integrations/sanity → packages/create-basement-app/integrations/sanity/files}/lib/utils/metadata.ts +0 -0
  422. /package/{plugins → packages/create-basement-app/plugins}/README.md +0 -0
  423. /package/{plugins → packages/create-basement-app/plugins}/no-anchor-element.grit +0 -0
  424. /package/{plugins → packages/create-basement-app/plugins}/no-relative-parent-imports.grit +0 -0
  425. /package/{plugins → packages/create-basement-app/plugins}/no-unnecessary-forwardref.grit +0 -0
  426. /package/{template-hooks → packages/create-basement-app/template-hooks}/use-battery.ts +0 -0
  427. /package/{template-hooks → packages/create-basement-app/template-hooks}/use-device-perf.ts +0 -0
  428. /package/{template-hooks → packages/create-basement-app/template-hooks}/use-intersection-observer.ts +0 -0
  429. /package/{template-hooks → packages/create-basement-app/template-hooks}/use-media.ts +0 -0
  430. /package/{layers/webgpu → packages/create-basement-app/templates/default/lib/integrations}/.gitkeep +0 -0
@@ -0,0 +1,77 @@
1
+ # Components
2
+
3
+ UI components organized by purpose.
4
+
5
+ ```
6
+ components/
7
+ ├── ui/ → Primitives (reusable across projects)
8
+ ├── layout/ → Site chrome (customize per project)
9
+ └── magic/ → Animation & visual enhancements
10
+ ```
11
+
12
+ ## Direct Imports (Recommended)
13
+
14
+ ```tsx
15
+ // UI Components - import directly for better clarity
16
+ import { Image } from '@/components/ui/image'
17
+ import { Link } from '@/components/ui/link'
18
+
19
+ // Layout Components
20
+ import { Wrapper } from '@/components/layout/wrapper'
21
+ import { Header } from '@/components/layout/header'
22
+ import { Footer } from '@/components/layout/footer'
23
+
24
+ // Magic Components
25
+ import { Marquee } from '@/components/magic/marquee'
26
+ ```
27
+
28
+ ## UI Components
29
+
30
+ | Component | Purpose |
31
+ |-----------|---------|
32
+ | `image/` | Optimized images (always use this, never `next/image`) |
33
+ | `link/` | Smart navigation (auto-detects external) |
34
+
35
+ ## Layout Components
36
+
37
+ | Component | Purpose |
38
+ |-----------|---------|
39
+ | `wrapper/` | Page wrapper (theme, WebGL, Lenis) |
40
+ | `header/` | Site header/navigation |
41
+ | `footer/` | Site footer |
42
+ | `lenis/` | Smooth scrolling |
43
+
44
+ ```tsx
45
+ <Wrapper theme="dark" webgl lenis>
46
+ <section>Your content</section>
47
+ </Wrapper>
48
+ ```
49
+
50
+ ## Effects Components
51
+
52
+ | Component | Purpose |
53
+ |-----------|---------|
54
+ | `marquee/` | Infinite scrolling text |
55
+
56
+ ## Best Practices
57
+
58
+ ```tsx
59
+ // ✅ Always use custom Image
60
+ import { Image } from '@/components/ui/image'
61
+ <Image src="/photo.jpg" alt="Photo" aspectRatio={16/9} />
62
+
63
+ // ✅ Always use custom Link
64
+ import { Link } from '@/components/ui/link'
65
+ <Link href="/about">Internal</Link>
66
+ <Link href="https://example.com">External</Link>
67
+
68
+ // ✅ CSS Modules + Tailwind
69
+ import s from './component.module.css'
70
+ <div className={cn(s.wrapper, 'flex items-center')} />
71
+ ```
72
+
73
+ ## Related
74
+
75
+ - [Image docs](ui/image/README.md)
76
+ - [Real Viewport docs](ui/real-viewport/README.md)
77
+ - [WebGL Components](../lib/webgl/README.md)
@@ -0,0 +1,37 @@
1
+ # Image Component
2
+
3
+ Optimized images with smart loading, blur placeholders, and responsive sizing.
4
+
5
+ ## Usage
6
+
7
+ ```tsx
8
+ import { Image } from '@/components/ui/image'
9
+
10
+ // Basic
11
+ <Image src="/hero.jpg" alt="Hero" aspectRatio={16/9} />
12
+
13
+ // Priority (LCP images)
14
+ <Image src="/hero.jpg" alt="Hero" aspectRatio={16/9} priority />
15
+
16
+ // Responsive
17
+ <Image
18
+ src="/product.jpg"
19
+ alt="Product"
20
+ mobileSize="100vw"
21
+ desktopSize="33vw"
22
+ />
23
+ ```
24
+
25
+ ## Props
26
+
27
+ | Prop | Description |
28
+ |------|-------------|
29
+ | `aspectRatio` | Prevents layout shift, enables blur placeholder |
30
+ | `priority` | Eager loading for above-the-fold images |
31
+ | `mobileSize` / `desktopSize` | Responsive sizing |
32
+
33
+ ## Best Practices
34
+
35
+ - Always provide `aspectRatio` (prevents CLS)
36
+ - Use `priority` for LCP images
37
+ - Never use `next/image` directly
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Enhanced Image Component
3
+ *
4
+ * Next.js Image wrapper with optimized defaults and error handling.
5
+ * Always use this component instead of next/image directly.
6
+ */
7
+ "use client"
8
+
9
+ import cn from "clsx"
10
+ import NextImage, { type ImageProps as NextImageProps } from "next/image"
11
+ import type { CSSProperties, Ref } from "react"
12
+ import { breakpoints } from "@/lib/styles/config"
13
+ import s from "./image.module.css"
14
+
15
+ /**
16
+ * Enhanced Image component props extending Next.js Image.
17
+ *
18
+ * Adds responsive sizing, aspect ratio support, and automatic blur placeholders.
19
+ * Always use this component instead of next/image directly.
20
+ */
21
+ export type ImageProps = Omit<NextImageProps, "objectFit" | "alt"> & {
22
+ /** CSS object-fit property for image positioning */
23
+ objectFit?: CSSProperties["objectFit"]
24
+ /** Display as block element (adds display: block) */
25
+ block?: boolean
26
+ /** Size on mobile devices (e.g., "100vw", "50vw") */
27
+ mobileSize?: `${number}vw`
28
+ /** Size on desktop devices (e.g., "33vw", "25vw") */
29
+ desktopSize?: `${number}vw`
30
+ /** Ref for accessing the underlying img element */
31
+ ref?: Ref<HTMLImageElement>
32
+ /** Alt text for accessibility (required for meaningful images) */
33
+ alt?: string
34
+ /** Aspect ratio for automatic placeholder and layout stability */
35
+ aspectRatio?: number
36
+ }
37
+
38
+ // Memoize helper functions to avoid recreation
39
+ const toBase64 = (str: string) =>
40
+ typeof window === "undefined"
41
+ ? Buffer.from(str).toString("base64")
42
+ : window.btoa(str)
43
+
44
+ // Helper to generate blur placeholder with transparent background by default
45
+ const generateShimmer = (w: number, h: number) => `
46
+ <svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
47
+ <defs>
48
+ <linearGradient id="g">
49
+ <stop stop-color="rgba(255,255,255,0.1)" offset="20%" />
50
+ <stop stop-color="rgba(255,255,255,0.2)" offset="50%" />
51
+ <stop stop-color="rgba(255,255,255,0.1)" offset="70%" />
52
+ </linearGradient>
53
+ </defs>
54
+ <rect width="${w}" height="${h}" fill="rgba(0,0,0,0)" />
55
+ <rect id="r" width="${w}" height="${h}" fill="url(#g)" />
56
+ <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
57
+ </svg>`
58
+
59
+ // Helper to determine if blur placeholder should be used
60
+ const shouldUseBlurPlaceholder = (
61
+ src: NextImageProps["src"],
62
+ placeholder: string,
63
+ blurDataURL: string | undefined
64
+ ): boolean => {
65
+ if (!src) return false
66
+ const isSvg = typeof src === "string" && src.includes(".svg")
67
+ return !isSvg && placeholder === "blur" && !blurDataURL
68
+ }
69
+
70
+ // Helper to generate blur data URL
71
+ const generateBlurDataURL = (
72
+ shouldUse: boolean,
73
+ aspectRatio: number | undefined,
74
+ existingBlurDataURL: string | undefined
75
+ ): string | undefined => {
76
+ if (!(shouldUse && aspectRatio)) return existingBlurDataURL
77
+
78
+ const shimmerSvg = generateShimmer(700, Math.round(700 / aspectRatio))
79
+ return `data:image/svg+xml;base64,${toBase64(shimmerSvg)}`
80
+ }
81
+
82
+ // Helper to determine final placeholder value
83
+ const getFinalPlaceholder = (
84
+ shouldUse: boolean,
85
+ aspectRatio: number | undefined,
86
+ blurDataURL: string | undefined,
87
+ originalPlaceholder: NextImageProps["placeholder"]
88
+ ): NextImageProps["placeholder"] => {
89
+ if (!shouldUse) {
90
+ return originalPlaceholder === "blur" && !blurDataURL
91
+ ? "empty"
92
+ : originalPlaceholder
93
+ }
94
+
95
+ return aspectRatio || blurDataURL ? "blur" : "empty"
96
+ }
97
+
98
+ /**
99
+ * Enhanced Image component with responsive sizing and automatic optimizations.
100
+ *
101
+ * Always use this component instead of next/image directly. Provides:
102
+ * - Automatic responsive sizes generation
103
+ * - Smart blur placeholders with aspect ratio support
104
+ * - Performance optimizations (lazy loading by default)
105
+ * - Preload for LCP images
106
+ *
107
+ * @param props - Image props extending Next.js Image
108
+ * @param props.aspectRatio - Aspect ratio for layout stability and blur placeholder
109
+ * @param props.mobileSize - Size on mobile (e.g., "100vw")
110
+ * @param props.desktopSize - Size on desktop (e.g., "50vw")
111
+ * @param props.block - Display as block element
112
+ * @param props.preload - Enable preloading for LCP images
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * // Basic usage with aspect ratio
117
+ * <Image
118
+ * src="/hero.jpg"
119
+ * alt="Hero image"
120
+ * aspectRatio={16/9}
121
+ * />
122
+ * ```
123
+ *
124
+ * @example
125
+ * ```tsx
126
+ * // LCP image with preload
127
+ * <Image
128
+ * src="/hero.jpg"
129
+ * alt="Hero image"
130
+ * aspectRatio={16/9}
131
+ * preload // Preloads image for LCP
132
+ * />
133
+ * ```
134
+ *
135
+ * @example
136
+ * ```tsx
137
+ * // Responsive grid image
138
+ * <Image
139
+ * src="/product.jpg"
140
+ * alt="Product"
141
+ * aspectRatio={1}
142
+ * mobileSize="100vw"
143
+ * desktopSize="33vw"
144
+ * />
145
+ * ```
146
+ */
147
+ export function Image({
148
+ style,
149
+ className,
150
+ loading,
151
+ objectFit = "cover",
152
+ quality = 90,
153
+ alt = "",
154
+ fill,
155
+ block = !fill,
156
+ width = block ? 1 : undefined,
157
+ height = block ? 1 : undefined,
158
+ mobileSize = "100vw",
159
+ desktopSize = "100vw",
160
+ sizes,
161
+ src,
162
+ unoptimized,
163
+ ref,
164
+ aspectRatio,
165
+ placeholder = "blur",
166
+ preload = false,
167
+ ...props
168
+ }: ImageProps) {
169
+ // Determine loading strategy
170
+ const finalLoading = loading ?? (preload ? "eager" : "lazy")
171
+
172
+ // Generate responsive sizes if not provided
173
+ const finalSizes =
174
+ sizes ||
175
+ `(max-width: ${breakpoints.desktop}px) ${mobileSize}, ${desktopSize}`
176
+
177
+ // Early return after hooks
178
+ if (!src) return null
179
+
180
+ // Determine SVG status and placeholder logic
181
+ const isSvg = typeof src === "string" && src.includes(".svg")
182
+ const shouldUsePlaceholder = shouldUseBlurPlaceholder(
183
+ src,
184
+ placeholder,
185
+ props.blurDataURL
186
+ )
187
+ const blurDataURL = generateBlurDataURL(
188
+ shouldUsePlaceholder,
189
+ aspectRatio,
190
+ props.blurDataURL
191
+ )
192
+ const finalPlaceholder = getFinalPlaceholder(
193
+ shouldUsePlaceholder,
194
+ aspectRatio,
195
+ props.blurDataURL,
196
+ placeholder
197
+ )
198
+
199
+ return (
200
+ <NextImage
201
+ ref={ref}
202
+ fill={!block}
203
+ {...(width !== undefined && { width })}
204
+ {...(height !== undefined && { height })}
205
+ loading={finalLoading}
206
+ quality={quality}
207
+ alt={alt}
208
+ style={{
209
+ objectFit,
210
+ ...style,
211
+ }}
212
+ className={cn(className, block && s.block)}
213
+ sizes={finalSizes}
214
+ src={src}
215
+ unoptimized={unoptimized || isSvg}
216
+ draggable={false}
217
+ onDragStart={(e) => e.preventDefault()}
218
+ {...(finalPlaceholder && { placeholder: finalPlaceholder })}
219
+ {...(blurDataURL && { blurDataURL })}
220
+ preload={preload}
221
+ {...props}
222
+ />
223
+ )
224
+ }
@@ -0,0 +1,146 @@
1
+ "use client"
2
+
3
+ import NextLink from "next/link"
4
+ import { usePathname } from "next/navigation"
5
+ import {
6
+ type AnchorHTMLAttributes,
7
+ type ComponentProps,
8
+ type MouseEvent,
9
+ useEffect,
10
+ useState,
11
+ } from "react"
12
+
13
+ // Helper to extract props safe for button elements
14
+ function getButtonProps(props: Record<string, unknown>) {
15
+ const {
16
+ href,
17
+ target,
18
+ rel,
19
+ "data-external": _dataExternal,
20
+ ...buttonProps
21
+ } = props
22
+ return buttonProps
23
+ }
24
+
25
+ // Helper to extract props safe for div elements
26
+ function getDivProps(props: Record<string, unknown>) {
27
+ const {
28
+ href,
29
+ target,
30
+ rel,
31
+ onClick,
32
+ "data-external": _dataExternal,
33
+ ...divProps
34
+ } = props
35
+ return divProps
36
+ }
37
+
38
+ type CustomLinkProps = Omit<
39
+ AnchorHTMLAttributes<HTMLAnchorElement>,
40
+ keyof ComponentProps<typeof NextLink> | "href"
41
+ > &
42
+ Omit<ComponentProps<typeof NextLink>, "href"> & {
43
+ href?: string
44
+ onClick?: (e: MouseEvent<HTMLElement>) => void
45
+ scroll?: boolean
46
+ }
47
+
48
+ export function Link({
49
+ href,
50
+ children,
51
+ onClick,
52
+ scroll = false, // Default to false to prevent scroll restoration warnings with fixed/sticky elements
53
+ ...props
54
+ }: CustomLinkProps) {
55
+ const [shouldPrefetch, setShouldPrefetch] = useState(false)
56
+ const [isExternal, setIsExternal] = useState(false)
57
+ const [isActive, setIsActive] = useState(false)
58
+
59
+ // Get pathname - deferred to avoid blocking static generation
60
+ // usePathname is safe to call but we defer the active check to useEffect
61
+ const pathname = usePathname()
62
+
63
+ useEffect(() => {
64
+ // Check if this link is active (current page)
65
+ if (href && pathname) {
66
+ setIsActive(pathname === href)
67
+ }
68
+ }, [href, pathname])
69
+
70
+ useEffect(() => {
71
+ // Skip if no href
72
+ if (!href) return
73
+
74
+ // Check if external link
75
+ try {
76
+ const url = new URL(href, window.location.href)
77
+ setIsExternal(url.host !== window.location.host)
78
+ } catch {
79
+ setIsExternal(false)
80
+ }
81
+
82
+ // Only prefetch on good connections
83
+ const connection = (
84
+ navigator as Navigator & {
85
+ connection?: { effectiveType: string; saveData: boolean }
86
+ }
87
+ ).connection
88
+ if (connection) {
89
+ const { effectiveType, saveData } = connection
90
+ setShouldPrefetch(effectiveType === "4g" && !saveData)
91
+ } else {
92
+ // Default to prefetching if API not available
93
+ setShouldPrefetch(true)
94
+ }
95
+ }, [href])
96
+
97
+ // If no href is provided but there's an onClick, render a button
98
+ if (!href && onClick) {
99
+ return (
100
+ <button
101
+ onClick={(e: MouseEvent<HTMLButtonElement>) => onClick(e)}
102
+ type="button"
103
+ {...getButtonProps(props)}
104
+ >
105
+ {children}
106
+ </button>
107
+ )
108
+ }
109
+
110
+ // If no href and no onClick, render a div
111
+ if (!href) {
112
+ return <div {...getDivProps(props)}>{children}</div>
113
+ }
114
+
115
+ // For SSR, check if it's external based on the href pattern
116
+ const isExternalSSR =
117
+ href.startsWith("http://") || href.startsWith("https://")
118
+
119
+ if (isExternalSSR || isExternal) {
120
+ return (
121
+ <a
122
+ href={href}
123
+ target="_blank"
124
+ rel="noopener noreferrer"
125
+ data-external
126
+ onClick={onClick}
127
+ {...props}
128
+ >
129
+ {children}
130
+ </a>
131
+ )
132
+ }
133
+
134
+ return (
135
+ <NextLink
136
+ href={href as ComponentProps<typeof NextLink>["href"]}
137
+ prefetch={shouldPrefetch}
138
+ scroll={scroll}
139
+ data-active={isActive || undefined}
140
+ {...(onClick && { onClick })}
141
+ {...props}
142
+ >
143
+ {children}
144
+ </NextLink>
145
+ )
146
+ }
@@ -0,0 +1,34 @@
1
+ "use client"
2
+
3
+ import dynamic from "next/dynamic"
4
+ import { Suspense, useRef } from "react"
5
+ import { cn } from "@/lib/styles/cn"
6
+
7
+ const WebGLCanvas = dynamic(() => import("./index"), {
8
+ ssr: false,
9
+ })
10
+
11
+ export default function DynamicCanvas() {
12
+ const eventSourceRef = useRef<HTMLDivElement>(null)
13
+
14
+ return (
15
+ <div
16
+ ref={eventSourceRef}
17
+ className={cn(
18
+ "pointer-events-none fixed top-0 left-0 z-50 h-lvh w-full overflow-hidden"
19
+ )}
20
+ >
21
+ <Suspense
22
+ fallback={
23
+ <div className="flex h-full w-full items-center justify-center bg-black/10">
24
+ <span className="font-mono text-xs uppercase tracking-widest opacity-30">
25
+ Loading WebGL...
26
+ </span>
27
+ </div>
28
+ }
29
+ >
30
+ <WebGLCanvas eventSource={eventSourceRef} />
31
+ </Suspense>
32
+ </div>
33
+ )
34
+ }
@@ -0,0 +1,43 @@
1
+ "use client"
2
+
3
+ import { Preload } from "@react-three/drei"
4
+ import { Canvas } from "@react-three/fiber"
5
+ import dynamic from "next/dynamic"
6
+
7
+ import { cn } from "@/lib/styles/cn"
8
+
9
+ const Scene = dynamic(
10
+ () =>
11
+ import("@/components/webgl/components/scene").then((mod) => mod.default),
12
+ {
13
+ ssr: false,
14
+ }
15
+ )
16
+
17
+ export default function WebGLCanvas({ ...props }) {
18
+ return (
19
+ <Canvas
20
+ className={cn("pointer-events-none h-lvh! w-full")}
21
+ dpr={[1, 2]}
22
+ eventPrefix="client"
23
+ frameloop="always"
24
+ camera={{
25
+ far: 1000,
26
+ near: 0.01,
27
+ fov: 16,
28
+ position: [0, 17, 350],
29
+ }}
30
+ gl={{
31
+ alpha: true,
32
+ antialias: true,
33
+ logarithmicDepthBuffer: true,
34
+ powerPreference: "high-performance",
35
+ premultipliedAlpha: true,
36
+ }}
37
+ {...props}
38
+ >
39
+ <Scene />
40
+ <Preload all />
41
+ </Canvas>
42
+ )
43
+ }
@@ -0,0 +1,21 @@
1
+ import { useFrame } from "@react-three/fiber"
2
+ import { useRef } from "react"
3
+ import type { Mesh } from "three"
4
+
5
+ const Scene = () => {
6
+ const meshRef = useRef<Mesh>(null)
7
+
8
+ useFrame((_state, delta) => {
9
+ meshRef.current.rotation.x += delta
10
+ meshRef.current.rotation.y += delta
11
+ })
12
+
13
+ return (
14
+ <mesh ref={meshRef} scale={10}>
15
+ <boxGeometry />
16
+ <meshBasicMaterial color="orange" />
17
+ </mesh>
18
+ )
19
+ }
20
+
21
+ export default Scene
@@ -0,0 +1,33 @@
1
+ # Lib
2
+
3
+ Non-UI code: hooks, integrations, styles, and utilities.
4
+
5
+ > **Rule**: Renders UI → `components/` · Everything else → `lib/`
6
+
7
+ ## Quick Imports
8
+
9
+ ```tsx
10
+ // Utilities - explicit imports for better tree-shaking
11
+ import { clamp, lerp } from '@/lib/utils/math'
12
+ import { slugify } from '@/lib/utils/strings'
13
+
14
+ // Styles
15
+ import { colors, themes, breakpoints } from '@/lib/styles/config'
16
+ ```
17
+
18
+ ## Directories
19
+
20
+ | Directory | Purpose | Optional? |
21
+ |-----------|---------|-----------|
22
+ | [hooks/](hooks/README.md) | React hooks + Zustand store | ❌ Core |
23
+ | [styles/](styles/README.md) | CSS & Tailwind config | ❌ Core |
24
+ | [utils/](utils/README.md) | Pure utility functions | ❌ Core |
25
+
26
+ ## Scripts
27
+
28
+ ```bash
29
+ bun dev # Start dev server
30
+ bun run generate # Generate pages/components
31
+ bun run setup:project # Configure integrations
32
+ bun setup:styles # Regenerate CSS
33
+ ```
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Custom React Hooks
3
+ *
4
+ * Import individual hooks:
5
+ * import { useDeviceDetection } from '@/hooks/use-device-detection'
6
+ *
7
+ * Or import from barrel:
8
+ * import { useDeviceDetection, usePrefetch } from '@/hooks/use-device-detection'
9
+ */
10
+
11
+ export { useDeviceDetection } from "./use-device-detection"
12
+ export { usePrefetch } from "./use-prefetch"