bsmnt 0.9.0 → 0.11.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 (344) hide show
  1. package/dist/application/add-integration/index.d.ts.map +1 -1
  2. package/dist/application/add-integration/index.js +19 -2
  3. package/dist/application/add-integration/index.js.map +1 -1
  4. package/dist/application/shared/node-version.js.map +1 -1
  5. package/dist/core/create/internal-ids.d.ts +3 -0
  6. package/dist/core/create/internal-ids.d.ts.map +1 -1
  7. package/dist/core/create/internal-ids.js +4 -0
  8. package/dist/core/create/internal-ids.js.map +1 -1
  9. package/dist/domain/agents.d.ts.map +1 -1
  10. package/dist/domain/animations.d.ts.map +1 -1
  11. package/dist/domain/cms.d.ts.map +1 -1
  12. package/dist/domain/forms.d.ts.map +1 -1
  13. package/dist/domain/hooks.d.ts.map +1 -1
  14. package/dist/domain/skills.d.ts.map +1 -1
  15. package/dist/domain/templates.d.ts +10 -0
  16. package/dist/domain/templates.d.ts.map +1 -1
  17. package/dist/domain/templates.js +5 -0
  18. package/dist/domain/templates.js.map +1 -1
  19. package/dist/index.js +18 -5
  20. package/dist/index.js.map +1 -1
  21. package/dist/infrastructure/agents/register-sanity-mcp.js +3 -8
  22. package/dist/infrastructure/agents/register-sanity-mcp.js.map +1 -1
  23. package/dist/infrastructure/agents/register-storybook-mcp.d.ts +18 -0
  24. package/dist/infrastructure/agents/register-storybook-mcp.d.ts.map +1 -0
  25. package/dist/infrastructure/agents/register-storybook-mcp.js +157 -0
  26. package/dist/infrastructure/agents/register-storybook-mcp.js.map +1 -0
  27. package/dist/infrastructure/create/lifecycle-registry.d.ts.map +1 -1
  28. package/dist/infrastructure/create/lifecycle-registry.js +39 -1
  29. package/dist/infrastructure/create/lifecycle-registry.js.map +1 -1
  30. package/dist/infrastructure/create/merge-registry.d.ts.map +1 -1
  31. package/dist/infrastructure/create/merge-registry.js +4 -0
  32. package/dist/infrastructure/create/merge-registry.js.map +1 -1
  33. package/dist/infrastructure/create/sanity-auth.js.map +1 -1
  34. package/dist/infrastructure/create/setup-agent.d.ts +6 -1
  35. package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
  36. package/dist/infrastructure/create/setup-agent.js +23 -21
  37. package/dist/infrastructure/create/setup-agent.js.map +1 -1
  38. package/dist/infrastructure/create/setup-dotenvx.js.map +1 -1
  39. package/dist/infrastructure/create/setup-remote.js.map +1 -1
  40. package/dist/infrastructure/create/setup-sanity.d.ts.map +1 -1
  41. package/dist/infrastructure/create/setup-sanity.js +12 -1
  42. package/dist/infrastructure/create/setup-sanity.js.map +1 -1
  43. package/dist/infrastructure/integrations/ensure-studio-headers.d.ts +6 -0
  44. package/dist/infrastructure/integrations/ensure-studio-headers.d.ts.map +1 -0
  45. package/dist/infrastructure/integrations/ensure-studio-headers.js +153 -0
  46. package/dist/infrastructure/integrations/ensure-studio-headers.js.map +1 -0
  47. package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
  48. package/dist/infrastructure/integrations/inject-integration.js +2 -0
  49. package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
  50. package/dist/infrastructure/update/notifier.js.map +1 -1
  51. package/dist/modules/features/cms/index.d.ts.map +1 -1
  52. package/dist/modules/features/cms/index.js +2 -0
  53. package/dist/modules/features/cms/index.js.map +1 -1
  54. package/dist/modules/features/cms/sanity/config.d.ts.map +1 -1
  55. package/dist/modules/features/cms/sanity/config.js +3 -1
  56. package/dist/modules/features/cms/sanity/config.js.map +1 -1
  57. package/dist/modules/features/cms/sanity/index.d.ts.map +1 -1
  58. package/dist/modules/features/cms/sanity/index.js +10 -1
  59. package/dist/modules/features/cms/sanity/index.js.map +1 -1
  60. package/dist/modules/features/cms/sanity/mergers/check-integration.d.ts.map +1 -1
  61. package/dist/modules/features/cms/sanity/mergers/check-integration.js +15 -6
  62. package/dist/modules/features/cms/sanity/mergers/check-integration.js.map +1 -1
  63. package/dist/modules/features/cms/sanity/mergers/knip.d.ts.map +1 -1
  64. package/dist/modules/features/cms/sanity/mergers/knip.js +1 -0
  65. package/dist/modules/features/cms/sanity/mergers/knip.js.map +1 -1
  66. package/dist/modules/features/cms/sanity/mergers/layout.js.map +1 -1
  67. package/dist/modules/features/cms/sanity/mergers/package-json.d.ts +12 -0
  68. package/dist/modules/features/cms/sanity/mergers/package-json.d.ts.map +1 -0
  69. package/dist/modules/features/cms/sanity/mergers/package-json.js +19 -0
  70. package/dist/modules/features/cms/sanity/mergers/package-json.js.map +1 -0
  71. package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
  72. package/dist/modules/features/cms/sanity-pagebuilder/config.js +2 -1
  73. package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
  74. package/dist/modules/features/cms/sanity-pagebuilder/index.d.ts.map +1 -1
  75. package/dist/modules/features/cms/sanity-pagebuilder/index.js +7 -1
  76. package/dist/modules/features/cms/sanity-pagebuilder/index.js.map +1 -1
  77. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts +14 -0
  78. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts.map +1 -0
  79. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js +50 -0
  80. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js.map +1 -0
  81. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts +3 -0
  82. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts.map +1 -0
  83. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js +55 -0
  84. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js.map +1 -0
  85. package/dist/modules/presets/index.d.ts.map +1 -1
  86. package/dist/modules/presets/index.js +2 -0
  87. package/dist/modules/presets/index.js.map +1 -1
  88. package/dist/modules/presets/next-pagebuilder-cache.d.ts +3 -0
  89. package/dist/modules/presets/next-pagebuilder-cache.d.ts.map +1 -0
  90. package/dist/modules/presets/next-pagebuilder-cache.js +10 -0
  91. package/dist/modules/presets/next-pagebuilder-cache.js.map +1 -0
  92. package/dist/paths.d.ts +6 -0
  93. package/dist/paths.d.ts.map +1 -1
  94. package/dist/paths.js +6 -0
  95. package/dist/paths.js.map +1 -1
  96. package/package.json +6 -3
  97. package/src/modules/features/cms/sanity/files/app/api/blog/[slug]/route.ts +4 -1
  98. package/src/modules/features/cms/sanity/files/app/sitemap.md/route.ts +2 -1
  99. package/src/modules/features/cms/sanity/files/components/ui/sanity-image/index.tsx +19 -5
  100. package/src/modules/features/cms/sanity/files/lib/integrations/check-integration.ts +7 -6
  101. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/README.md +32 -1
  102. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/components/rich-text.tsx +1 -0
  103. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/env.ts +2 -2
  104. package/src/modules/features/cms/sanity/files/proxy.ts +9 -0
  105. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/[[...slug]]/route.ts +12 -3
  106. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +172 -24
  107. package/src/modules/features/cms/sanity-pagebuilder/files/app/feed.xml/route.ts +14 -7
  108. package/src/modules/features/cms/sanity-pagebuilder/files/app/sitemap.md/route.ts +8 -2
  109. package/src/modules/features/cms/sanity-pagebuilder/files/app/studio/[[...tool]]/page.tsx +16 -1
  110. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +1 -0
  111. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/visual-editing.tsx +2 -2
  112. package/src/modules/features/cms/sanity-pagebuilder/files/components/ui/sanity-image/index.tsx +15 -5
  113. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/check-integration.ts +6 -5
  114. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/client.ts +8 -0
  115. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-field.tsx +13 -7
  116. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-notices.tsx +125 -0
  117. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/env.ts +2 -2
  118. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +22 -52
  119. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -2
  120. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/live/index.tsx +4 -2
  121. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/markdown-proxy.config.ts +1 -1
  122. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +7 -0
  123. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +70 -57
  124. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +119 -29
  125. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
  126. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +1 -0
  127. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
  128. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +2 -0
  129. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/redirect.ts +35 -4
  130. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +12 -0
  131. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/tags.ts +56 -0
  132. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +12 -0
  133. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/sitemap.ts +11 -8
  134. package/src/modules/features/cms/sanity-pagebuilder/files/proxy.ts +9 -0
  135. package/src/modules/features/cms/sanity-pagebuilder-cache/files/.knip.json +8 -0
  136. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/[[...slug]]/route.ts +112 -0
  137. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/disable/route.ts +7 -0
  138. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/enable/route.ts +20 -0
  139. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/revalidate/route.ts +292 -0
  140. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/feed.xml/route.ts +66 -0
  141. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/sitemap.md/route.ts +132 -0
  142. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/layout.tsx +26 -0
  143. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/page.tsx +23 -0
  144. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/draft-mode-toggle.tsx +27 -0
  145. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/rich-text.tsx +88 -0
  146. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/visual-editing.tsx +11 -0
  147. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/ui/sanity-image/index.tsx +51 -0
  148. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/check-integration.ts +6 -0
  149. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/client.ts +37 -0
  150. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/block-actions-item.tsx +81 -0
  151. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  152. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-input.tsx +39 -0
  153. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  154. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/same-as-input.tsx +66 -0
  155. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-field.tsx +24 -0
  156. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-input.tsx +14 -0
  157. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-notices.tsx +125 -0
  158. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  159. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/env.ts +34 -0
  160. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/layout.ts +39 -0
  161. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/redirects.ts +22 -0
  162. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +81 -0
  163. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/live/index.tsx +140 -0
  164. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  165. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +144 -0
  166. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-category.ts +28 -0
  167. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-tree-pane.tsx +431 -0
  168. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/pinned-pages.ts +54 -0
  169. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +119 -0
  170. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +548 -0
  171. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
  172. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.cli.ts +29 -0
  173. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.config.ts +116 -0
  174. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/index.ts +6 -0
  175. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  176. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  177. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +178 -0
  178. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  179. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
  180. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  181. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/author.ts +70 -0
  182. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  183. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +134 -0
  184. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/company-data.ts +70 -0
  185. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  186. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/navbar.ts +75 -0
  187. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/redirect.ts +152 -0
  188. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/structured-data.ts +124 -0
  189. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  190. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  191. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/metadata.ts +132 -0
  192. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  193. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-builder.ts +43 -0
  194. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  195. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page.ts +265 -0
  196. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  197. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/structured-data-blocks.ts +436 -0
  198. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +51 -0
  199. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +334 -0
  200. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/tags.ts +89 -0
  201. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/image.ts +8 -0
  202. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/link.ts +140 -0
  203. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-builder-markdown.ts +113 -0
  204. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-json-ld.ts +208 -0
  205. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/scripts/sanity-typegen.ts +36 -0
  206. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/check-redirect.ts +30 -0
  207. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/json-ld.tsx +522 -0
  208. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/metadata.ts +189 -0
  209. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/rss.ts +96 -0
  210. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/sitemap.ts +58 -0
  211. package/src/modules/features/cms/sanity-pagebuilder-cache/files/proxy.ts +90 -0
  212. package/src/modules/features/env/dotenvx/files/vercelignore +5 -0
  213. package/src/templates/next-default/.env.example +4 -2
  214. package/src/templates/next-default/.github/workflows/ci.yml +1 -1
  215. package/src/templates/next-default/.vscode/settings.json +0 -2
  216. package/src/templates/next-default/app/robots.ts +2 -3
  217. package/src/templates/next-default/components/ui/image/index.tsx +2 -4
  218. package/src/templates/next-default/knip.json +1 -1
  219. package/src/templates/next-default/lefthook.yml +1 -1
  220. package/src/templates/next-default/lib/utils/README.md +18 -5
  221. package/src/templates/next-default/lib/utils/image-sizes.ts +72 -0
  222. package/src/templates/next-default/lib/utils/merge-refs.ts +56 -0
  223. package/src/templates/next-default/lib/utils/strings.ts +1 -51
  224. package/src/templates/next-default/next.config.ts +38 -5
  225. package/src/templates/next-default/package.json +9 -12
  226. package/src/templates/next-experiments/.env.example +4 -2
  227. package/src/templates/next-experiments/.github/workflows/ci.yml +1 -1
  228. package/src/templates/next-experiments/.vscode/settings.json +0 -2
  229. package/src/templates/next-experiments/app/page.tsx +1 -1
  230. package/src/templates/next-experiments/app/robots.ts +2 -3
  231. package/src/templates/next-experiments/components/ui/image/index.tsx +2 -4
  232. package/src/templates/next-experiments/knip.json +1 -1
  233. package/src/templates/next-experiments/lefthook.yml +1 -1
  234. package/src/templates/next-experiments/lib/utils/README.md +18 -5
  235. package/src/templates/next-experiments/lib/utils/image-sizes.ts +72 -0
  236. package/src/templates/next-experiments/lib/utils/merge-refs.ts +56 -0
  237. package/src/templates/next-experiments/lib/utils/strings.ts +1 -51
  238. package/src/templates/next-experiments/next.config.ts +38 -5
  239. package/src/templates/next-experiments/package.json +9 -12
  240. package/src/templates/next-pagebuilder/.env.example +3 -0
  241. package/src/templates/next-pagebuilder/.github/workflows/ci.yml +1 -1
  242. package/src/templates/next-pagebuilder/.vscode/settings.json +0 -2
  243. package/src/templates/next-pagebuilder/README.md +95 -0
  244. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +24 -9
  245. package/src/templates/next-pagebuilder/app/robots.ts +2 -3
  246. package/src/templates/next-pagebuilder/app/sitemap.xml/route.ts +9 -4
  247. package/src/templates/next-pagebuilder/biome.json +2 -1
  248. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +3 -6
  249. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +3 -2
  250. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +3 -8
  251. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/content-filters.tsx +23 -40
  252. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +88 -58
  253. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/skeleton.tsx +41 -0
  254. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/types.ts +14 -1
  255. package/src/templates/next-pagebuilder/components/page-builder/components/rich-text-block.tsx +16 -0
  256. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +23 -3
  257. package/src/templates/next-pagebuilder/components/page-document/index.tsx +1 -0
  258. package/src/templates/next-pagebuilder/components/ui/image/index.tsx +2 -1
  259. package/src/templates/next-pagebuilder/knip.json +3 -2
  260. package/src/templates/next-pagebuilder/lefthook.yml +1 -1
  261. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +1221 -977
  262. package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +72 -0
  263. package/src/templates/next-pagebuilder/lib/utils/merge-refs.ts +56 -0
  264. package/src/templates/next-pagebuilder/next.config.ts +35 -5
  265. package/src/templates/next-pagebuilder/package.json +8 -10
  266. package/src/templates/next-pagebuilder-cache/.biome/plugins/README.md +21 -0
  267. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-anchor-element.grit +12 -0
  268. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-relative-parent-imports.grit +10 -0
  269. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  270. package/src/templates/next-pagebuilder-cache/.env.example +40 -0
  271. package/src/templates/next-pagebuilder-cache/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  272. package/src/templates/next-pagebuilder-cache/.github/workflows/ci.yml +105 -0
  273. package/src/templates/next-pagebuilder-cache/.vscode/extensions.json +19 -0
  274. package/src/templates/next-pagebuilder-cache/.vscode/settings.json +103 -0
  275. package/src/templates/next-pagebuilder-cache/.zed/settings.json +47 -0
  276. package/src/templates/next-pagebuilder-cache/README.md +212 -0
  277. package/src/templates/next-pagebuilder-cache/_gitignore +65 -0
  278. package/src/templates/next-pagebuilder-cache/app/(content)/[[...slug]]/page.tsx +124 -0
  279. package/src/templates/next-pagebuilder-cache/app/(content)/layout.tsx +28 -0
  280. package/src/templates/next-pagebuilder-cache/app/actions/unlock-gated-content.ts +53 -0
  281. package/src/templates/next-pagebuilder-cache/app/favicon.ico +0 -0
  282. package/src/templates/next-pagebuilder-cache/app/layout.tsx +83 -0
  283. package/src/templates/next-pagebuilder-cache/app/robots.ts +13 -0
  284. package/src/templates/next-pagebuilder-cache/app/sitemap.xml/route.ts +84 -0
  285. package/src/templates/next-pagebuilder-cache/biome.json +257 -0
  286. package/src/templates/next-pagebuilder-cache/components/layout/footer/index.tsx +127 -0
  287. package/src/templates/next-pagebuilder-cache/components/layout/header/components/cta-button.tsx +28 -0
  288. package/src/templates/next-pagebuilder-cache/components/layout/header/components/mega-menu-panel.tsx +90 -0
  289. package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-item-renderer.tsx +98 -0
  290. package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-leaf-item.tsx +33 -0
  291. package/src/templates/next-pagebuilder-cache/components/layout/header/components/types.ts +7 -0
  292. package/src/templates/next-pagebuilder-cache/components/layout/header/header-client.tsx +110 -0
  293. package/src/templates/next-pagebuilder-cache/components/layout/header/index.tsx +32 -0
  294. package/src/templates/next-pagebuilder-cache/components/layout/json-ld/index.tsx +79 -0
  295. package/src/templates/next-pagebuilder-cache/components/layout/wrapper/index.tsx +33 -0
  296. package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/index.tsx +78 -0
  297. package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/related-post-item.tsx +27 -0
  298. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-card.tsx +66 -0
  299. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-filters.tsx +76 -0
  300. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-grid.tsx +40 -0
  301. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-pagination-nav.tsx +71 -0
  302. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/index.tsx +306 -0
  303. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/skeleton.tsx +41 -0
  304. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/types.ts +32 -0
  305. package/src/templates/next-pagebuilder-cache/components/page-builder/components/description.tsx +17 -0
  306. package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +169 -0
  307. package/src/templates/next-pagebuilder-cache/components/page-builder/components/hero.tsx +17 -0
  308. package/src/templates/next-pagebuilder-cache/components/page-builder/components/rich-text-block.tsx +16 -0
  309. package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +71 -0
  310. package/src/templates/next-pagebuilder-cache/components/page-builder/types.ts +25 -0
  311. package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +147 -0
  312. package/src/templates/next-pagebuilder-cache/components/ui/image/index.tsx +216 -0
  313. package/src/templates/next-pagebuilder-cache/components/ui/link/index.tsx +152 -0
  314. package/src/templates/next-pagebuilder-cache/components.json +24 -0
  315. package/src/templates/next-pagebuilder-cache/knip.json +35 -0
  316. package/src/templates/next-pagebuilder-cache/lefthook.yml +25 -0
  317. package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +1588 -0
  318. package/src/templates/next-pagebuilder-cache/lib/scripts/setup-ci-secrets.ts +117 -0
  319. package/src/templates/next-pagebuilder-cache/lib/styles/cn.ts +5 -0
  320. package/src/templates/next-pagebuilder-cache/lib/styles/global.css +69 -0
  321. package/src/templates/next-pagebuilder-cache/lib/utils/base-url.ts +17 -0
  322. package/src/templates/next-pagebuilder-cache/lib/utils/format-date.ts +8 -0
  323. package/src/templates/next-pagebuilder-cache/lib/utils/slug-tag.ts +6 -0
  324. package/src/templates/next-pagebuilder-cache/next.config.ts +176 -0
  325. package/src/templates/next-pagebuilder-cache/package.json +62 -0
  326. package/src/templates/next-pagebuilder-cache/postcss.config.mjs +65 -0
  327. package/src/templates/next-pagebuilder-cache/svg.d.ts +6 -0
  328. package/src/templates/next-pagebuilder-cache/tsconfig.json +38 -0
  329. package/src/templates/next-webgl/.env.example +4 -2
  330. package/src/templates/next-webgl/.github/workflows/ci.yml +1 -1
  331. package/src/templates/next-webgl/.vscode/settings.json +0 -2
  332. package/src/templates/next-webgl/app/robots.ts +2 -3
  333. package/src/templates/next-webgl/components/ui/image/index.tsx +2 -4
  334. package/src/templates/next-webgl/knip.json +1 -1
  335. package/src/templates/next-webgl/lefthook.yml +1 -1
  336. package/src/templates/next-webgl/lib/utils/README.md +18 -5
  337. package/src/templates/next-webgl/lib/utils/image-sizes.ts +72 -0
  338. package/src/templates/next-webgl/lib/utils/merge-refs.ts +56 -0
  339. package/src/templates/next-webgl/lib/utils/strings.ts +1 -51
  340. package/src/templates/next-webgl/next.config.ts +38 -5
  341. package/src/templates/next-webgl/package.json +11 -14
  342. package/src/templates/next-experiments/tsconfig.tsbuildinfo +0 -1
  343. package/src/templates/next-pagebuilder/app/actions/refresh.ts +0 -5
  344. package/src/templates/next-webgl/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Push CI environment to GitHub Actions for this repository.
3
+ *
4
+ * Reads values from `.env.local` and sets them on the current repo via the
5
+ * GitHub CLI (`gh`), matching the `build` step in `.github/workflows/ci.yml`:
6
+ * the public Sanity project ID and dataset become repository *variables*, and
7
+ * the read token becomes a *secret*.
8
+ *
9
+ * Run once the repo exists on GitHub: `bun run ci:secrets`
10
+ * Requires the GitHub CLI, authenticated (`gh auth login`).
11
+ */
12
+ import { execFileSync } from "node:child_process"
13
+ import { existsSync, readFileSync } from "node:fs"
14
+ import path from "node:path"
15
+
16
+ const ENV_FILE = ".env.local"
17
+
18
+ /** Public config — stored as GitHub Actions repository variables. */
19
+ const VARIABLES = [
20
+ "NEXT_PUBLIC_SANITY_PROJECT_ID",
21
+ "NEXT_PUBLIC_SANITY_DATASET",
22
+ ] as const
23
+
24
+ /** Sensitive config — stored as GitHub Actions secrets. */
25
+ const SECRETS = ["SANITY_API_READ_TOKEN"] as const
26
+
27
+ function parseEnvFile(file: string): Record<string, string> {
28
+ const env: Record<string, string> = {}
29
+ if (!existsSync(file)) return env
30
+
31
+ for (const rawLine of readFileSync(file, "utf8").split("\n")) {
32
+ const line = rawLine.trim()
33
+ if (!line || line.startsWith("#")) continue
34
+
35
+ const eq = line.indexOf("=")
36
+ if (eq === -1) continue
37
+
38
+ const key = line.slice(0, eq).trim()
39
+ let value = line.slice(eq + 1).trim()
40
+ if (
41
+ (value.startsWith('"') && value.endsWith('"')) ||
42
+ (value.startsWith("'") && value.endsWith("'"))
43
+ ) {
44
+ value = value.slice(1, -1)
45
+ }
46
+ env[key] = value
47
+ }
48
+
49
+ return env
50
+ }
51
+
52
+ function ensureGitHubRepo(): void {
53
+ try {
54
+ execFileSync("gh", ["--version"], { stdio: "pipe" })
55
+ } catch {
56
+ console.error(
57
+ "✖ GitHub CLI (gh) not found. Install it: https://cli.github.com",
58
+ )
59
+ process.exit(1)
60
+ }
61
+
62
+ try {
63
+ execFileSync("gh", ["repo", "view", "--json", "nameWithOwner"], {
64
+ stdio: "pipe",
65
+ })
66
+ } catch {
67
+ console.error("✖ No GitHub repository detected for this directory.")
68
+ console.error(
69
+ " Create and push the repo first (e.g. `gh repo create`), then re-run.",
70
+ )
71
+ process.exit(1)
72
+ }
73
+ }
74
+
75
+ ensureGitHubRepo()
76
+
77
+ const env = parseEnvFile(path.resolve(ENV_FILE))
78
+ let pushed = 0
79
+ let skipped = 0
80
+
81
+ for (const name of VARIABLES) {
82
+ const value = env[name] ?? process.env[name]
83
+ if (!value) {
84
+ console.info(`- ${name}: not found in ${ENV_FILE}, skipping`)
85
+ skipped++
86
+ continue
87
+ }
88
+ // Public value — safe to pass on the command line.
89
+ execFileSync("gh", ["variable", "set", name, "--body", value], {
90
+ stdio: "pipe",
91
+ })
92
+ console.info(`✓ variable ${name}`)
93
+ pushed++
94
+ }
95
+
96
+ for (const name of SECRETS) {
97
+ const value = env[name] ?? process.env[name]
98
+ if (!value) {
99
+ console.info(`- ${name}: not found in ${ENV_FILE}, skipping`)
100
+ skipped++
101
+ continue
102
+ }
103
+ // Sensitive — pipe via stdin so the token never appears in the process args.
104
+ execFileSync("gh", ["secret", "set", name], { input: value, stdio: "pipe" })
105
+ console.info(`✓ secret ${name}`)
106
+ pushed++
107
+ }
108
+
109
+ if (pushed === 0) {
110
+ console.info(
111
+ `\nNothing to sync. Add your Sanity values to ${ENV_FILE} (or run Sanity setup) first.`,
112
+ )
113
+ } else {
114
+ console.info(
115
+ `\nDone — ${String(pushed)} value(s) pushed to GitHub Actions${skipped ? `, ${String(skipped)} skipped` : ""}.`,
116
+ )
117
+ }
@@ -0,0 +1,5 @@
1
+ import { cx } from "class-variance-authority"
2
+ import type { ClassValue } from "class-variance-authority/types"
3
+ import { twMerge } from "tailwind-merge"
4
+
5
+ export const cn = (...inputs: ClassValue[]) => twMerge(cx(inputs))
@@ -0,0 +1,69 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --breakpoint-*: initial;
5
+ --breakpoint-desktop-large: 1920px;
6
+ --breakpoint-desktop: 1440px;
7
+ --breakpoint-tablet-lg: 1024px;
8
+ --breakpoint-tablet: 768px;
9
+ --breakpoint-mobile: 640px;
10
+
11
+ --color-*: initial;
12
+ --color-primary: #ffffff;
13
+ --color-secondary: #000000;
14
+ --color-contrast: #ff4d00;
15
+ --color-black: #000000;
16
+ --color-white: #ffffff;
17
+ --color-orange: #ff4d00;
18
+ --color-blue: #487cff;
19
+ --color-green: #00ff9b;
20
+ --color-violet: #f101a5;
21
+ --color-pink: #ff73a6;
22
+ --color-gray: #666666;
23
+
24
+ /* gray */
25
+ --color-gray-50: #f5f5f5;
26
+ --color-gray-100: #e0e0e0;
27
+ --color-gray-200: #c2c2c2;
28
+ --color-gray-300: #a3a3a3;
29
+ --color-gray-400: #858585;
30
+ --color-gray-500: #666666;
31
+ --color-gray-600: #4d4d4d;
32
+ --color-gray-700: #333333;
33
+ --color-gray-800: #1a1a1a;
34
+ }
35
+
36
+ @theme inline {
37
+ --font-geist: var(--font-geist-variable);
38
+ }
39
+
40
+ html {
41
+ --scrollbar-gutter: 0px;
42
+ scrollbar-gutter: stable;
43
+ }
44
+
45
+ body {
46
+ -webkit-font-smoothing: antialiased;
47
+ -moz-osx-font-smoothing: grayscale;
48
+
49
+ @apply flex flex-col bg-primary text-secondary overscroll-none min-h-svh;
50
+ }
51
+
52
+ *:focus-visible {
53
+ outline: 2px solid var(--color-contrast);
54
+ @apply outline-2 outline-contrast;
55
+ }
56
+
57
+ img {
58
+ -webkit-touch-callout: none;
59
+ -webkit-user-select: none;
60
+ -moz-user-select: none;
61
+ -ms-user-select: none;
62
+ -o-user-select: none;
63
+ user-select: none;
64
+ }
65
+
66
+ button {
67
+ cursor: pointer;
68
+ user-select: none;
69
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Centralized base URL resolution.
3
+ *
4
+ * Priority:
5
+ * 1. NEXT_PUBLIC_BASE_URL (explicit production URL)
6
+ * 2. VERCEL_PROJECT_PRODUCTION_URL (Vercel production domain)
7
+ * 3. VERCEL_URL (Vercel preview/deployment URL)
8
+ * 4. http://localhost:3000 (local development)
9
+ */
10
+ export const getBaseUrl = () =>
11
+ process.env.NEXT_PUBLIC_BASE_URL ||
12
+ (process.env.VERCEL_PROJECT_PRODUCTION_URL
13
+ ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
14
+ : undefined) ||
15
+ (process.env.VERCEL_URL
16
+ ? `https://${process.env.VERCEL_URL}`
17
+ : "http://localhost:3000")
@@ -0,0 +1,8 @@
1
+ const options: Intl.DateTimeFormatOptions = {
2
+ year: "numeric",
3
+ month: "long",
4
+ day: "numeric",
5
+ }
6
+
7
+ export const formatDate = (date: Date | string | number) =>
8
+ new Date(date).toLocaleDateString("en-US", options)
@@ -0,0 +1,6 @@
1
+ export const getSlugTag = (slug: string | null | undefined) => {
2
+ const normalizedSlug = slug?.replace(/^\/+|\/+$/g, "") ?? ""
3
+ const lastSlugSegment = normalizedSlug.split("/").filter(Boolean).at(-1)
4
+
5
+ return lastSlugSegment ?? "homepage"
6
+ }
@@ -0,0 +1,176 @@
1
+ import withBundleAnalyzer from "@next/bundle-analyzer"
2
+ import type { NextConfig } from "next"
3
+ import { sanity } from "next-sanity/live/cache-life"
4
+
5
+ const nextConfig: NextConfig = {
6
+ cacheComponents: true,
7
+ // Publishes invalidate by tag, so the window is long. `expire` is pinned
8
+ // because the `sanity` profile omits it and Next's fallback is unbounded.
9
+ cacheLife: { default: { ...sanity, expire: sanity.revalidate } },
10
+ reactStrictMode: true,
11
+ reactCompiler: true,
12
+ typedRoutes: true,
13
+ // Bundle the committed encrypted env files so instrumentation.ts can decrypt
14
+ // them at runtime. `.env.keys` is never listed; missing files are skipped.
15
+ outputFileTracingIncludes: {
16
+ "/**": ["./.env", "./.env.production", "./.env.preview"],
17
+ },
18
+ turbopack: {
19
+ rules: {
20
+ "*.svg": {
21
+ loaders: [
22
+ {
23
+ loader: "@svgr/webpack",
24
+ options: {
25
+ memo: true,
26
+ dimensions: false,
27
+ svgoConfig: {
28
+ multipass: true,
29
+ plugins: [
30
+ "removeDimensions",
31
+ "removeOffCanvasPaths",
32
+ "reusePaths",
33
+ "removeElementsByAttr",
34
+ "removeStyleElement",
35
+ "removeScriptElement",
36
+ "prefixIds",
37
+ "cleanupIds",
38
+ {
39
+ name: "cleanupNumericValues",
40
+ params: {
41
+ floatPrecision: 1,
42
+ },
43
+ },
44
+ {
45
+ name: "convertPathData",
46
+ params: {
47
+ floatPrecision: 1,
48
+ },
49
+ },
50
+ {
51
+ name: "convertTransform",
52
+ params: {
53
+ floatPrecision: 1,
54
+ },
55
+ },
56
+ {
57
+ name: "cleanupListOfValues",
58
+ params: {
59
+ floatPrecision: 1,
60
+ },
61
+ },
62
+ ],
63
+ },
64
+ },
65
+ },
66
+ ],
67
+ as: "*.js",
68
+ },
69
+ },
70
+ },
71
+ logging: {
72
+ browserToTerminal: true,
73
+ },
74
+ experimental: {
75
+ optimizePackageImports: [
76
+ "@react-three/drei",
77
+ "@react-three/fiber",
78
+ "gsap",
79
+ "three",
80
+ "postprocessing",
81
+ "lenis",
82
+ ],
83
+ },
84
+ images: {
85
+ dangerouslyAllowSVG: true,
86
+ remotePatterns: [
87
+ {
88
+ protocol: "https",
89
+ hostname: "cdn.sanity.io",
90
+ },
91
+ ],
92
+ minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
93
+ qualities: [90],
94
+ formats: ["image/avif", "image/webp"],
95
+ deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
96
+ imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
97
+ },
98
+ headers: async () => [
99
+ {
100
+ // Excludes /studio* — must stay mutually exclusive with the rule below.
101
+ source: "/((?!studio(?:/|$)).*)",
102
+ headers: [
103
+ {
104
+ key: "X-Content-Type-Options",
105
+ value: "nosniff",
106
+ },
107
+ {
108
+ key: "Content-Security-Policy",
109
+ value: "frame-ancestors 'self';",
110
+ },
111
+ {
112
+ key: "X-Frame-Options",
113
+ value: "SAMEORIGIN",
114
+ },
115
+ {
116
+ key: "X-XSS-Protection",
117
+ value: "1; mode=block",
118
+ },
119
+ {
120
+ key: "X-DNS-Prefetch-Control",
121
+ value: "on",
122
+ },
123
+ {
124
+ key: "Strict-Transport-Security",
125
+ value: "max-age=63072000; includeSubDomains; preload",
126
+ },
127
+ {
128
+ key: "Permissions-Policy",
129
+ value: "camera=(), microphone=(), geolocation=()",
130
+ },
131
+ ],
132
+ },
133
+ {
134
+ // X-Frame-Options can't allow a third-party origin, and Next can't unset
135
+ // it from another rule — the iframe needs it absent, not overridden.
136
+ source: "/studio/:path*",
137
+ headers: [
138
+ {
139
+ key: "X-Content-Type-Options",
140
+ value: "nosniff",
141
+ },
142
+ {
143
+ key: "Content-Security-Policy",
144
+ value: "frame-ancestors 'self' https://*.sanity.io;",
145
+ },
146
+ {
147
+ key: "X-XSS-Protection",
148
+ value: "1; mode=block",
149
+ },
150
+ {
151
+ key: "X-DNS-Prefetch-Control",
152
+ value: "on",
153
+ },
154
+ {
155
+ key: "Strict-Transport-Security",
156
+ value: "max-age=63072000; includeSubDomains; preload",
157
+ },
158
+ {
159
+ key: "Permissions-Policy",
160
+ value: "camera=(), microphone=(), geolocation=()",
161
+ },
162
+ ],
163
+ },
164
+ ],
165
+ }
166
+
167
+ const bundleAnalyzerPlugin = withBundleAnalyzer({
168
+ enabled: process.env.ANALYZE === "true",
169
+ })
170
+
171
+ const NextApp = () => {
172
+ const plugins = [bundleAnalyzerPlugin]
173
+ return plugins.reduce((config, plugin) => plugin(config), nextConfig)
174
+ }
175
+
176
+ export default NextApp
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "bsmnt-pagebuilder-cache-starter",
3
+ "description": "Basement Next.js starter template (Cache Components)",
4
+ "version": "0.1.0",
5
+ "private": true,
6
+ "packageManager": "bun@1.3.14",
7
+ "engines": {
8
+ "node": ">=24"
9
+ },
10
+ "scripts": {
11
+ "analyze": "cross-env ANALYZE=true bun run build",
12
+ "analyze:experimental": "next experimental-analyze",
13
+ "build": "next build",
14
+ "ci:secrets": "bun ./lib/scripts/setup-ci-secrets.ts",
15
+ "dev": "next dev",
16
+ "format": "biome format --write .",
17
+ "knip": "knip",
18
+ "knip:fix": "knip --fix",
19
+ "lighthouse": "bunx @unlighthouse/cli --site http://localhost:3000",
20
+ "lint": "biome lint --max-diagnostics=200",
21
+ "lint:fix": "biome check --write --unsafe --max-diagnostics=200",
22
+ "prepare": "lefthook install",
23
+ "start": "next start",
24
+ "typecheck": "tsc --noEmit",
25
+ "update:packages": "cross-env NPM_CHECK_INSTALLER=bun bunx npm-check -u"
26
+ },
27
+ "dependencies": {
28
+ "class-variance-authority": "^0.7.1",
29
+ "next": "^16.3.0",
30
+ "react": "^19.2.8",
31
+ "react-dom": "^19.2.8",
32
+ "react-use": "^17.6.0",
33
+ "tailwind-merge": "^3.5.0",
34
+ "zod": "^4.3.6"
35
+ },
36
+ "devDependencies": {
37
+ "@biomejs/biome": "^2.4.14",
38
+ "@csstools/postcss-global-data": "^4.0.0",
39
+ "@next/bundle-analyzer": "^16.3.0",
40
+ "@svgr/webpack": "^8.1.0",
41
+ "@tailwindcss/postcss": "^4.2.2",
42
+ "@types/bun": "^1.3.11",
43
+ "@types/node": "^24.13.1",
44
+ "@types/react": "^19.2.14",
45
+ "@types/react-dom": "^19.2.3",
46
+ "babel-plugin-react-compiler": "^1.0.0",
47
+ "cross-env": "^10.1.0",
48
+ "knip": "^6.16.1",
49
+ "lefthook": "^1.13.0",
50
+ "postcss-functions": "^4.0.2",
51
+ "postcss-preset-env": "^11.2.0",
52
+ "tailwindcss": "^4.2.2",
53
+ "typescript": "^7.0.2"
54
+ },
55
+ "trustedDependencies": [
56
+ "@biomejs/biome",
57
+ "@tailwindcss/oxide",
58
+ "esbuild",
59
+ "sharp"
60
+ ],
61
+ "browserslist": "extends @sanity/browserslist-config"
62
+ }
@@ -0,0 +1,65 @@
1
+ import { existsSync } from "node:fs"
2
+ import { fileURLToPath } from "node:url"
3
+ import path from "node:path"
4
+
5
+ // Turbopack evaluates this from .next/, sanity CLI from lib/integrations/sanity/.
6
+ // Walk up from both candidates until we find the project root.
7
+ const TARGET = "lib/styles/global.css"
8
+
9
+ function findRoot(...candidates) {
10
+ for (const start of candidates) {
11
+ let dir = start
12
+ while (true) {
13
+ if (existsSync(path.join(dir, TARGET))) return dir
14
+ const parent = path.dirname(dir)
15
+ if (parent === dir) break
16
+ dir = parent
17
+ }
18
+ }
19
+ return process.cwd()
20
+ }
21
+
22
+ const projectRoot = findRoot(
23
+ path.dirname(fileURLToPath(import.meta.url)),
24
+ process.cwd(),
25
+ )
26
+
27
+ /**
28
+ * PostCSS preset-env config
29
+ * @see Docs {@link https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/README.md#options}
30
+ * @see Features Flags {@link https://github.com/csstools/postcss-plugins/blob/main/plugin-packs/postcss-preset-env/FEATURES.md}
31
+ * @type {import('postcss-preset-env').pluginOptions}
32
+ */
33
+ const presetEnvConfig = {
34
+ autoprefixer: {
35
+ flexbox: "no-2009",
36
+ },
37
+ stage: 3,
38
+ features: {
39
+ "custom-properties": false,
40
+ "custom-media-queries": true,
41
+ "nesting-rules": true,
42
+ },
43
+ }
44
+
45
+ /**
46
+ * PostCSS global data config
47
+ * Makes sure the css module files have access to these context files
48
+ * @see {@link https://github.com/csstools/postcss-global-data?tab=readme-ov-file#options}
49
+ * @type {import('@csstools/postcss-global-data').pluginOptions}
50
+ */
51
+ const globalDataConfig = {
52
+ files: [path.join(projectRoot, "lib/styles/global.css")],
53
+ }
54
+
55
+ const postcssConfig = {
56
+ // NOTE: Order is important
57
+ plugins: {
58
+ "@tailwindcss/postcss": {},
59
+ "@csstools/postcss-global-data": globalDataConfig,
60
+ // NOTE: This has to be last config
61
+ "postcss-preset-env": presetEnvConfig,
62
+ },
63
+ }
64
+
65
+ export default postcssConfig
@@ -0,0 +1,6 @@
1
+ declare module "*.svg" {
2
+ import type { FC, SVGProps } from "react"
3
+
4
+ const content: FC<SVGProps<SVGSVGElement>>
5
+ export default content
6
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "noImplicitOverride": true,
17
+ "exactOptionalPropertyTypes": true,
18
+ "useUnknownInCatchVariables": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noImplicitReturns": true,
21
+ "noUncheckedSideEffectImports": true,
22
+ "noUnusedLocals": true,
23
+ "noUnusedParameters": true,
24
+ "noUncheckedIndexedAccess": true,
25
+ "plugins": [{ "name": "next" }],
26
+ "types": ["bun", "node"],
27
+ "paths": { "@/*": ["./*"] }
28
+ },
29
+ "include": [
30
+ "next-env.d.ts",
31
+ "**/*.ts",
32
+ "**/*.tsx",
33
+ ".next/types/**/*.ts",
34
+ ".next/dev/types/**/*.ts",
35
+ "**/*.mts"
36
+ ],
37
+ "exclude": ["node_modules"]
38
+ }
@@ -32,6 +32,8 @@
32
32
  # Base URL for your site (used for SEO, canonical URLs, etc.)
33
33
  # Development: http://localhost:3000
34
34
  # Production: https://your-domain.com
35
+ # Inlined at build time — scope this to the Production environment only in
36
+ # Vercel so Preview deployments fall through to VERCEL_PROJECT_PRODUCTION_URL.
35
37
  NEXT_PUBLIC_BASE_URL=""
36
38
 
37
39
  # Draft mode secret for preview functionality
@@ -54,8 +56,8 @@ NEXT_PUBLIC_SANITY_API_READ_TOKEN=""
54
56
  # Optional - for server-side mutations and visual editing
55
57
  # SANITY_PRIVATE_TOKEN=""
56
58
 
57
- # Optional - API version (defaults to 2024-03-15)
58
- # NEXT_PUBLIC_SANITY_API_VERSION="2024-03-15"
59
+ # Optional - API version (defaults to 2025-02-19, the floor for Content Releases)
60
+ # NEXT_PUBLIC_SANITY_API_VERSION="2025-02-19"
59
61
 
60
62
 
61
63
  # ============================================
@@ -41,7 +41,7 @@ jobs:
41
41
  run: bun install --frozen-lockfile
42
42
 
43
43
  - name: Type check
44
- run: bun run typecheck:compare
44
+ run: bun run typecheck
45
45
 
46
46
  - name: Lint
47
47
  run: bun run lint
@@ -58,7 +58,6 @@
58
58
 
59
59
  // General
60
60
  "files.eol": "\n",
61
- // "typescript.experimental.useTsgo": true, // Disabled: tsgo doesn't support Next.js plugin
62
61
  "javascript.suggest.autoImports": true,
63
62
  // Disable Prettier to prevent silent formatter conflicts
64
63
  "prettier.enable": false,
@@ -90,7 +89,6 @@
90
89
 
91
90
  // TypeScript
92
91
  "typescript.suggest.autoImports": true,
93
- "typescript.tsdk": "node_modules/typescript/lib",
94
92
 
95
93
  // Editor labels (fixed for .tsx files)
96
94
  "workbench.editor.customLabels.patterns": {
@@ -1,6 +1,5 @@
1
1
  import type { MetadataRoute } from "next"
2
-
3
- const APP_BASE_URL = process.env.NEXT_PUBLIC_BASE_URL ?? "http://localhost:3000"
2
+ import { getBaseUrl } from "@/lib/utils/url"
4
3
 
5
4
  export default function robots(): MetadataRoute.Robots {
6
5
  return {
@@ -9,6 +8,6 @@ export default function robots(): MetadataRoute.Robots {
9
8
  allow: "/",
10
9
  disallow: [],
11
10
  },
12
- sitemap: `${APP_BASE_URL}/sitemap.xml`,
11
+ sitemap: `${getBaseUrl()}/sitemap.xml`,
13
12
  }
14
13
  }
@@ -9,8 +9,7 @@
9
9
  import cn from "clsx"
10
10
  import NextImage, { type ImageProps as NextImageProps } from "next/image"
11
11
  import type { CSSProperties, Ref } from "react"
12
-
13
- const DESKTOP_BREAKPOINT = 1440
12
+ import { buildImageSizes } from "@/lib/utils/image-sizes"
14
13
 
15
14
  /**
16
15
  * Enhanced Image component props extending Next.js Image.
@@ -167,8 +166,7 @@ export function Image({
167
166
  }: ImageProps) {
168
167
  // Generate responsive sizes if not provided
169
168
  const finalSizes =
170
- sizes ||
171
- `(max-width: ${DESKTOP_BREAKPOINT}px) ${mobileSize}, ${desktopSize}`
169
+ sizes || buildImageSizes({ base: mobileSize, desktop: desktopSize })
172
170
 
173
171
  // Early return after hooks
174
172
  if (!src) return null
@@ -19,5 +19,5 @@
19
19
  "zustand"
20
20
  ],
21
21
  "ignoreBinaries": ["op", "gh", "vercel"],
22
- "ignoreFiles": [".agents/**", ".claude/**", "hooks/**"]
22
+ "ignoreFiles": [".agents/**", ".claude/**", "hooks/**", "lib/integrations/hubspot/**"]
23
23
  }
@@ -11,7 +11,7 @@ pre-commit:
11
11
  stage_fixed: true
12
12
  typecheck:
13
13
  glob: '*.{ts,tsx}'
14
- run: bunx tsgo --noEmit --incremental false
14
+ run: bunx tsc --noEmit --incremental false
15
15
  stage_fixed: false
16
16
 
17
17
  post-merge: