bsmnt 0.10.0 → 0.12.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 (343) hide show
  1. package/dist/application/add-integration/index.js.map +1 -1
  2. package/dist/application/shared/node-version.js.map +1 -1
  3. package/dist/core/create/internal-ids.d.ts +3 -0
  4. package/dist/core/create/internal-ids.d.ts.map +1 -1
  5. package/dist/core/create/internal-ids.js +4 -0
  6. package/dist/core/create/internal-ids.js.map +1 -1
  7. package/dist/domain/agents.d.ts.map +1 -1
  8. package/dist/domain/animations.d.ts.map +1 -1
  9. package/dist/domain/cms.d.ts.map +1 -1
  10. package/dist/domain/forms.d.ts.map +1 -1
  11. package/dist/domain/hooks.d.ts.map +1 -1
  12. package/dist/domain/skills.d.ts.map +1 -1
  13. package/dist/domain/templates.d.ts +10 -0
  14. package/dist/domain/templates.d.ts.map +1 -1
  15. package/dist/domain/templates.js +5 -0
  16. package/dist/domain/templates.js.map +1 -1
  17. package/dist/index.js +18 -5
  18. package/dist/index.js.map +1 -1
  19. package/dist/infrastructure/agents/register-sanity-mcp.js +3 -8
  20. package/dist/infrastructure/agents/register-sanity-mcp.js.map +1 -1
  21. package/dist/infrastructure/agents/register-storybook-mcp.d.ts +18 -0
  22. package/dist/infrastructure/agents/register-storybook-mcp.d.ts.map +1 -0
  23. package/dist/infrastructure/agents/register-storybook-mcp.js +157 -0
  24. package/dist/infrastructure/agents/register-storybook-mcp.js.map +1 -0
  25. package/dist/infrastructure/create/lifecycle-registry.d.ts.map +1 -1
  26. package/dist/infrastructure/create/lifecycle-registry.js +39 -1
  27. package/dist/infrastructure/create/lifecycle-registry.js.map +1 -1
  28. package/dist/infrastructure/create/merge-registry.d.ts.map +1 -1
  29. package/dist/infrastructure/create/merge-registry.js +4 -0
  30. package/dist/infrastructure/create/merge-registry.js.map +1 -1
  31. package/dist/infrastructure/create/sanity-auth.js.map +1 -1
  32. package/dist/infrastructure/create/setup-agent.d.ts +6 -1
  33. package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
  34. package/dist/infrastructure/create/setup-agent.js +23 -21
  35. package/dist/infrastructure/create/setup-agent.js.map +1 -1
  36. package/dist/infrastructure/create/setup-dotenvx.js.map +1 -1
  37. package/dist/infrastructure/create/setup-remote.js.map +1 -1
  38. package/dist/infrastructure/create/setup-sanity.d.ts.map +1 -1
  39. package/dist/infrastructure/create/setup-sanity.js +12 -1
  40. package/dist/infrastructure/create/setup-sanity.js.map +1 -1
  41. package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
  42. package/dist/infrastructure/integrations/inject-integration.js +2 -0
  43. package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
  44. package/dist/infrastructure/update/notifier.js.map +1 -1
  45. package/dist/modules/features/cms/index.d.ts.map +1 -1
  46. package/dist/modules/features/cms/index.js +2 -0
  47. package/dist/modules/features/cms/index.js.map +1 -1
  48. package/dist/modules/features/cms/sanity/config.d.ts.map +1 -1
  49. package/dist/modules/features/cms/sanity/config.js +1 -0
  50. package/dist/modules/features/cms/sanity/config.js.map +1 -1
  51. package/dist/modules/features/cms/sanity/index.d.ts.map +1 -1
  52. package/dist/modules/features/cms/sanity/index.js +10 -1
  53. package/dist/modules/features/cms/sanity/index.js.map +1 -1
  54. package/dist/modules/features/cms/sanity/mergers/check-integration.d.ts.map +1 -1
  55. package/dist/modules/features/cms/sanity/mergers/check-integration.js +15 -6
  56. package/dist/modules/features/cms/sanity/mergers/check-integration.js.map +1 -1
  57. package/dist/modules/features/cms/sanity/mergers/knip.d.ts.map +1 -1
  58. package/dist/modules/features/cms/sanity/mergers/knip.js +1 -0
  59. package/dist/modules/features/cms/sanity/mergers/knip.js.map +1 -1
  60. package/dist/modules/features/cms/sanity/mergers/layout.js.map +1 -1
  61. package/dist/modules/features/cms/sanity/mergers/package-json.d.ts +12 -0
  62. package/dist/modules/features/cms/sanity/mergers/package-json.d.ts.map +1 -0
  63. package/dist/modules/features/cms/sanity/mergers/package-json.js +19 -0
  64. package/dist/modules/features/cms/sanity/mergers/package-json.js.map +1 -0
  65. package/dist/modules/features/cms/sanity-pagebuilder/index.d.ts.map +1 -1
  66. package/dist/modules/features/cms/sanity-pagebuilder/index.js +7 -1
  67. package/dist/modules/features/cms/sanity-pagebuilder/index.js.map +1 -1
  68. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts +14 -0
  69. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts.map +1 -0
  70. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js +50 -0
  71. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js.map +1 -0
  72. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts +3 -0
  73. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts.map +1 -0
  74. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js +55 -0
  75. package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js.map +1 -0
  76. package/dist/modules/presets/index.d.ts.map +1 -1
  77. package/dist/modules/presets/index.js +2 -0
  78. package/dist/modules/presets/index.js.map +1 -1
  79. package/dist/modules/presets/next-pagebuilder-cache.d.ts +3 -0
  80. package/dist/modules/presets/next-pagebuilder-cache.d.ts.map +1 -0
  81. package/dist/modules/presets/next-pagebuilder-cache.js +10 -0
  82. package/dist/modules/presets/next-pagebuilder-cache.js.map +1 -0
  83. package/dist/paths.d.ts +6 -0
  84. package/dist/paths.d.ts.map +1 -1
  85. package/dist/paths.js +6 -0
  86. package/dist/paths.js.map +1 -1
  87. package/package.json +5 -2
  88. package/src/modules/features/cms/sanity/files/components/ui/sanity-image/index.tsx +36 -4
  89. package/src/modules/features/cms/sanity/files/lib/integrations/check-integration.ts +7 -6
  90. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/README.md +1 -1
  91. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/components/rich-text.tsx +8 -1
  92. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/env.ts +2 -2
  93. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/[[...slug]]/route.ts +4 -0
  94. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +172 -24
  95. package/src/modules/features/cms/sanity-pagebuilder/files/app/feed.xml/route.ts +14 -7
  96. package/src/modules/features/cms/sanity-pagebuilder/files/app/sitemap.md/route.ts +2 -2
  97. package/src/modules/features/cms/sanity-pagebuilder/files/app/studio/[[...tool]]/page.tsx +16 -1
  98. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +8 -1
  99. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/visual-editing.tsx +2 -2
  100. package/src/modules/features/cms/sanity-pagebuilder/files/components/ui/sanity-image/index.tsx +36 -4
  101. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/check-integration.ts +6 -5
  102. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/client.ts +8 -0
  103. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-input.tsx +26 -7
  104. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +242 -0
  105. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-notices.tsx +6 -16
  106. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +62 -0
  107. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/env.ts +2 -2
  108. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +22 -52
  109. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -2
  110. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/live/index.tsx +3 -1
  111. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +78 -33
  112. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +70 -57
  113. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +119 -29
  114. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
  115. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +2 -0
  116. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
  117. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/studio-preview.ts +37 -0
  118. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +5 -0
  119. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +12 -0
  120. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +2 -0
  121. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +5 -0
  122. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/tags.ts +56 -0
  123. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +12 -0
  124. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/sitemap.ts +11 -8
  125. package/src/modules/features/cms/sanity-pagebuilder-cache/files/.knip.json +8 -0
  126. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/[[...slug]]/route.ts +112 -0
  127. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/disable/route.ts +7 -0
  128. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/enable/route.ts +20 -0
  129. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/revalidate/route.ts +292 -0
  130. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/feed.xml/route.ts +66 -0
  131. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/sitemap.md/route.ts +132 -0
  132. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/layout.tsx +26 -0
  133. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/page.tsx +23 -0
  134. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/draft-mode-toggle.tsx +27 -0
  135. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/rich-text.tsx +94 -0
  136. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/visual-editing.tsx +11 -0
  137. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/ui/sanity-image/index.tsx +83 -0
  138. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/check-integration.ts +6 -0
  139. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/client.ts +37 -0
  140. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/block-actions-item.tsx +81 -0
  141. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  142. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-input.tsx +58 -0
  143. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +242 -0
  144. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  145. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/same-as-input.tsx +66 -0
  146. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-field.tsx +24 -0
  147. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-input.tsx +14 -0
  148. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-notices.tsx +125 -0
  149. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +62 -0
  150. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  151. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/env.ts +34 -0
  152. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/layout.ts +39 -0
  153. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/redirects.ts +22 -0
  154. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +81 -0
  155. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/live/index.tsx +140 -0
  156. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  157. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +182 -0
  158. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-category.ts +28 -0
  159. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-tree-pane.tsx +431 -0
  160. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/pinned-pages.ts +54 -0
  161. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +119 -0
  162. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +548 -0
  163. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
  164. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.cli.ts +29 -0
  165. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.config.ts +116 -0
  166. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/index.ts +7 -0
  167. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  168. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  169. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +178 -0
  170. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  171. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
  172. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  173. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/studio-preview.ts +37 -0
  174. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/author.ts +70 -0
  175. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  176. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +137 -0
  177. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/company-data.ts +70 -0
  178. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  179. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/navbar.ts +75 -0
  180. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/redirect.ts +152 -0
  181. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/structured-data.ts +124 -0
  182. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  183. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  184. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/metadata.ts +132 -0
  185. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  186. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-builder.ts +43 -0
  187. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  188. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page.ts +265 -0
  189. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  190. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/structured-data-blocks.ts +436 -0
  191. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +53 -0
  192. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +339 -0
  193. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/tags.ts +89 -0
  194. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/image.ts +8 -0
  195. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/link.ts +140 -0
  196. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-builder-markdown.ts +113 -0
  197. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-json-ld.ts +208 -0
  198. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/scripts/sanity-typegen.ts +36 -0
  199. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/check-redirect.ts +30 -0
  200. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/json-ld.tsx +522 -0
  201. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/metadata.ts +189 -0
  202. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/rss.ts +96 -0
  203. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/sitemap.ts +58 -0
  204. package/src/modules/features/cms/sanity-pagebuilder-cache/files/proxy.ts +90 -0
  205. package/src/modules/features/env/dotenvx/files/vercelignore +5 -0
  206. package/src/templates/next-default/.biome/plugins/no-fill-without-sizes.grit +11 -0
  207. package/src/templates/next-default/.env.example +2 -2
  208. package/src/templates/next-default/.github/workflows/ci.yml +1 -1
  209. package/src/templates/next-default/.vscode/settings.json +0 -2
  210. package/src/templates/next-default/biome.json +2 -1
  211. package/src/templates/next-default/components/ui/image/index.tsx +21 -15
  212. package/src/templates/next-default/knip.json +1 -1
  213. package/src/templates/next-default/lefthook.yml +1 -1
  214. package/src/templates/next-default/lib/utils/README.md +18 -5
  215. package/src/templates/next-default/lib/utils/image-sizes.ts +72 -0
  216. package/src/templates/next-default/lib/utils/merge-refs.ts +56 -0
  217. package/src/templates/next-default/lib/utils/strings.ts +1 -51
  218. package/src/templates/next-default/next.config.ts +12 -7
  219. package/src/templates/next-default/package.json +2 -5
  220. package/src/templates/next-experiments/.biome/plugins/no-fill-without-sizes.grit +11 -0
  221. package/src/templates/next-experiments/.env.example +2 -2
  222. package/src/templates/next-experiments/.github/workflows/ci.yml +1 -1
  223. package/src/templates/next-experiments/.vscode/settings.json +0 -2
  224. package/src/templates/next-experiments/app/page.tsx +1 -1
  225. package/src/templates/next-experiments/biome.json +2 -1
  226. package/src/templates/next-experiments/components/ui/image/index.tsx +21 -15
  227. package/src/templates/next-experiments/knip.json +1 -1
  228. package/src/templates/next-experiments/lefthook.yml +1 -1
  229. package/src/templates/next-experiments/lib/utils/README.md +18 -5
  230. package/src/templates/next-experiments/lib/utils/image-sizes.ts +72 -0
  231. package/src/templates/next-experiments/lib/utils/merge-refs.ts +56 -0
  232. package/src/templates/next-experiments/lib/utils/strings.ts +1 -51
  233. package/src/templates/next-experiments/next.config.ts +12 -7
  234. package/src/templates/next-experiments/package.json +2 -5
  235. package/src/templates/next-pagebuilder/.biome/plugins/no-fill-without-sizes.grit +11 -0
  236. package/src/templates/next-pagebuilder/.env.example +1 -0
  237. package/src/templates/next-pagebuilder/.github/workflows/ci.yml +1 -1
  238. package/src/templates/next-pagebuilder/.vscode/settings.json +0 -2
  239. package/src/templates/next-pagebuilder/README.md +64 -0
  240. package/src/templates/next-pagebuilder/app/sitemap.xml/route.ts +3 -1
  241. package/src/templates/next-pagebuilder/biome.json +4 -2
  242. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +3 -6
  243. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +3 -2
  244. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +3 -8
  245. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/index.tsx +5 -0
  246. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/related-post-item.tsx +1 -0
  247. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/content-filters.tsx +23 -40
  248. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +88 -58
  249. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/skeleton.tsx +4 -16
  250. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/types.ts +14 -1
  251. package/src/templates/next-pagebuilder/components/page-builder/components/rich-text-block.tsx +16 -0
  252. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +21 -7
  253. package/src/templates/next-pagebuilder/components/page-document/index.tsx +1 -0
  254. package/src/templates/next-pagebuilder/components/ui/image/index.tsx +21 -12
  255. package/src/templates/next-pagebuilder/knip.json +3 -2
  256. package/src/templates/next-pagebuilder/lefthook.yml +1 -1
  257. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +1221 -977
  258. package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +72 -0
  259. package/src/templates/next-pagebuilder/lib/utils/merge-refs.ts +56 -0
  260. package/src/templates/next-pagebuilder/next.config.ts +6 -6
  261. package/src/templates/next-pagebuilder/package.json +4 -6
  262. package/src/templates/next-pagebuilder-cache/.biome/plugins/README.md +21 -0
  263. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-anchor-element.grit +12 -0
  264. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-fill-without-sizes.grit +11 -0
  265. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-relative-parent-imports.grit +10 -0
  266. package/src/templates/next-pagebuilder-cache/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  267. package/src/templates/next-pagebuilder-cache/.env.example +40 -0
  268. package/src/templates/next-pagebuilder-cache/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  269. package/src/templates/next-pagebuilder-cache/.github/workflows/ci.yml +105 -0
  270. package/src/templates/next-pagebuilder-cache/.vscode/extensions.json +19 -0
  271. package/src/templates/next-pagebuilder-cache/.vscode/settings.json +103 -0
  272. package/src/templates/next-pagebuilder-cache/.zed/settings.json +47 -0
  273. package/src/templates/next-pagebuilder-cache/README.md +212 -0
  274. package/src/templates/next-pagebuilder-cache/_gitignore +65 -0
  275. package/src/templates/next-pagebuilder-cache/app/(content)/[[...slug]]/page.tsx +124 -0
  276. package/src/templates/next-pagebuilder-cache/app/(content)/layout.tsx +28 -0
  277. package/src/templates/next-pagebuilder-cache/app/actions/unlock-gated-content.ts +53 -0
  278. package/src/templates/next-pagebuilder-cache/app/favicon.ico +0 -0
  279. package/src/templates/next-pagebuilder-cache/app/layout.tsx +83 -0
  280. package/src/templates/next-pagebuilder-cache/app/robots.ts +13 -0
  281. package/src/templates/next-pagebuilder-cache/app/sitemap.xml/route.ts +84 -0
  282. package/src/templates/next-pagebuilder-cache/biome.json +258 -0
  283. package/src/templates/next-pagebuilder-cache/components/layout/footer/index.tsx +127 -0
  284. package/src/templates/next-pagebuilder-cache/components/layout/header/components/cta-button.tsx +28 -0
  285. package/src/templates/next-pagebuilder-cache/components/layout/header/components/mega-menu-panel.tsx +90 -0
  286. package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-item-renderer.tsx +98 -0
  287. package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-leaf-item.tsx +33 -0
  288. package/src/templates/next-pagebuilder-cache/components/layout/header/components/types.ts +7 -0
  289. package/src/templates/next-pagebuilder-cache/components/layout/header/header-client.tsx +110 -0
  290. package/src/templates/next-pagebuilder-cache/components/layout/header/index.tsx +32 -0
  291. package/src/templates/next-pagebuilder-cache/components/layout/json-ld/index.tsx +79 -0
  292. package/src/templates/next-pagebuilder-cache/components/layout/wrapper/index.tsx +33 -0
  293. package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/index.tsx +83 -0
  294. package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/related-post-item.tsx +28 -0
  295. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-card.tsx +66 -0
  296. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-filters.tsx +76 -0
  297. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-grid.tsx +40 -0
  298. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-pagination-nav.tsx +71 -0
  299. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/index.tsx +306 -0
  300. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/skeleton.tsx +41 -0
  301. package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/types.ts +32 -0
  302. package/src/templates/next-pagebuilder-cache/components/page-builder/components/description.tsx +17 -0
  303. package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +169 -0
  304. package/src/templates/next-pagebuilder-cache/components/page-builder/components/hero.tsx +17 -0
  305. package/src/templates/next-pagebuilder-cache/components/page-builder/components/rich-text-block.tsx +16 -0
  306. package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +71 -0
  307. package/src/templates/next-pagebuilder-cache/components/page-builder/types.ts +25 -0
  308. package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +147 -0
  309. package/src/templates/next-pagebuilder-cache/components/ui/image/index.tsx +225 -0
  310. package/src/templates/next-pagebuilder-cache/components/ui/link/index.tsx +152 -0
  311. package/src/templates/next-pagebuilder-cache/components.json +24 -0
  312. package/src/templates/next-pagebuilder-cache/knip.json +35 -0
  313. package/src/templates/next-pagebuilder-cache/lefthook.yml +25 -0
  314. package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +1588 -0
  315. package/src/templates/next-pagebuilder-cache/lib/scripts/setup-ci-secrets.ts +117 -0
  316. package/src/templates/next-pagebuilder-cache/lib/styles/cn.ts +5 -0
  317. package/src/templates/next-pagebuilder-cache/lib/styles/global.css +69 -0
  318. package/src/templates/next-pagebuilder-cache/lib/utils/base-url.ts +17 -0
  319. package/src/templates/next-pagebuilder-cache/lib/utils/format-date.ts +8 -0
  320. package/src/templates/next-pagebuilder-cache/lib/utils/image-sizes.ts +72 -0
  321. package/src/templates/next-pagebuilder-cache/lib/utils/slug-tag.ts +6 -0
  322. package/src/templates/next-pagebuilder-cache/next.config.ts +177 -0
  323. package/src/templates/next-pagebuilder-cache/package.json +62 -0
  324. package/src/templates/next-pagebuilder-cache/postcss.config.mjs +65 -0
  325. package/src/templates/next-pagebuilder-cache/svg.d.ts +6 -0
  326. package/src/templates/next-pagebuilder-cache/tsconfig.json +38 -0
  327. package/src/templates/next-webgl/.biome/plugins/no-fill-without-sizes.grit +11 -0
  328. package/src/templates/next-webgl/.env.example +2 -2
  329. package/src/templates/next-webgl/.github/workflows/ci.yml +1 -1
  330. package/src/templates/next-webgl/.vscode/settings.json +0 -2
  331. package/src/templates/next-webgl/biome.json +2 -1
  332. package/src/templates/next-webgl/components/ui/image/index.tsx +21 -15
  333. package/src/templates/next-webgl/knip.json +1 -1
  334. package/src/templates/next-webgl/lefthook.yml +1 -1
  335. package/src/templates/next-webgl/lib/utils/README.md +18 -5
  336. package/src/templates/next-webgl/lib/utils/image-sizes.ts +72 -0
  337. package/src/templates/next-webgl/lib/utils/merge-refs.ts +56 -0
  338. package/src/templates/next-webgl/lib/utils/strings.ts +1 -51
  339. package/src/templates/next-webgl/next.config.ts +12 -7
  340. package/src/templates/next-webgl/package.json +4 -7
  341. package/src/templates/next-experiments/tsconfig.tsbuildinfo +0 -1
  342. package/src/templates/next-pagebuilder/app/actions/refresh.ts +0 -5
  343. 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,72 @@
1
+ /** Mirrors the theme's `--breakpoint-*` scale, which clears Tailwind's defaults. */
2
+ export const BASEMENT_BREAKPOINTS = {
3
+ mobile: 640,
4
+ tablet: 768,
5
+ "tablet-lg": 1024,
6
+ desktop: 1440,
7
+ "desktop-large": 1920,
8
+ } as const
9
+
10
+ export type BreakpointMap = Readonly<Record<string, number>>
11
+
12
+ /** Mirrors the element's variants: `grid-cols-1 tablet:grid-cols-2` → `{ base: 1, tablet: 2 }`. */
13
+ export type ByBreakpoint<
14
+ T,
15
+ B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
16
+ > = { base: T } & Partial<Record<Extract<keyof B, string>, T>>
17
+
18
+ function columnWidth(columns: number): string {
19
+ return `${Math.round(100 / columns)}vw`
20
+ }
21
+
22
+ /**
23
+ * Widest first, since `sizes` takes the first matching condition and the last
24
+ * entry must be bare. `min-width` matches the Tailwind variant's boundary; a
25
+ * `max-width: <next> - 1` one would leave a fractional-pixel gap.
26
+ */
27
+ function toSizes(
28
+ base: string,
29
+ overrides: Readonly<Record<string, string | undefined>>,
30
+ scale: BreakpointMap
31
+ ): string {
32
+ const conditions: string[] = []
33
+
34
+ for (const [name, min] of Object.entries(scale).sort(
35
+ ([, a], [, b]) => b - a
36
+ )) {
37
+ const value = overrides[name]
38
+ if (value !== undefined) {
39
+ conditions.push(`(min-width: ${min}px) ${value}`)
40
+ }
41
+ }
42
+
43
+ return [...conditions, base].join(", ")
44
+ }
45
+
46
+ /** Builds `sizes` from the CSS length the image renders at per breakpoint. */
47
+ export function buildImageSizes<
48
+ B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
49
+ >(widths: ByBreakpoint<string, B>, breakpoints?: B): string {
50
+ const { base, ...overrides } = widths
51
+ return toSizes(base, overrides, breakpoints ?? BASEMENT_BREAKPOINTS)
52
+ }
53
+
54
+ /**
55
+ * Builds `sizes` from a grid's column count per breakpoint. Rounded: `sizes`
56
+ * only steers which srcset candidate the browser picks, and gaps make the real
57
+ * column narrower than `100 / N` anyway.
58
+ */
59
+ export function buildGridImageSizes<
60
+ B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
61
+ >(columns: ByBreakpoint<number, B>, breakpoints?: B): string {
62
+ const { base, ...overrides } = columns
63
+ const widths: Record<string, string> = {}
64
+
65
+ for (const [name, count] of Object.entries(overrides)) {
66
+ if (count !== undefined) {
67
+ widths[name] = columnWidth(count)
68
+ }
69
+ }
70
+
71
+ return toSizes(columnWidth(base), widths, breakpoints ?? BASEMENT_BREAKPOINTS)
72
+ }
@@ -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,177 @@
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
+ remotePatterns: [
86
+ {
87
+ protocol: "https",
88
+ hostname: "cdn.sanity.io",
89
+ },
90
+ ],
91
+ minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
92
+ qualities: [75, 90, 100],
93
+ formats: ["image/avif", "image/webp"],
94
+ deviceSizes: [
95
+ 640, 750, 828, 1080, 1200, 1320, 1620, 1920, 2048, 2560, 3024, 3456, 3840,
96
+ ],
97
+ imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
98
+ },
99
+ headers: async () => [
100
+ {
101
+ // Excludes /studio* — must stay mutually exclusive with the rule below.
102
+ source: "/((?!studio(?:/|$)).*)",
103
+ headers: [
104
+ {
105
+ key: "X-Content-Type-Options",
106
+ value: "nosniff",
107
+ },
108
+ {
109
+ key: "Content-Security-Policy",
110
+ value: "frame-ancestors 'self';",
111
+ },
112
+ {
113
+ key: "X-Frame-Options",
114
+ value: "SAMEORIGIN",
115
+ },
116
+ {
117
+ key: "X-XSS-Protection",
118
+ value: "1; mode=block",
119
+ },
120
+ {
121
+ key: "X-DNS-Prefetch-Control",
122
+ value: "on",
123
+ },
124
+ {
125
+ key: "Strict-Transport-Security",
126
+ value: "max-age=63072000; includeSubDomains; preload",
127
+ },
128
+ {
129
+ key: "Permissions-Policy",
130
+ value: "camera=(), microphone=(), geolocation=()",
131
+ },
132
+ ],
133
+ },
134
+ {
135
+ // X-Frame-Options can't allow a third-party origin, and Next can't unset
136
+ // it from another rule — the iframe needs it absent, not overridden.
137
+ source: "/studio/:path*",
138
+ headers: [
139
+ {
140
+ key: "X-Content-Type-Options",
141
+ value: "nosniff",
142
+ },
143
+ {
144
+ key: "Content-Security-Policy",
145
+ value: "frame-ancestors 'self' https://*.sanity.io;",
146
+ },
147
+ {
148
+ key: "X-XSS-Protection",
149
+ value: "1; mode=block",
150
+ },
151
+ {
152
+ key: "X-DNS-Prefetch-Control",
153
+ value: "on",
154
+ },
155
+ {
156
+ key: "Strict-Transport-Security",
157
+ value: "max-age=63072000; includeSubDomains; preload",
158
+ },
159
+ {
160
+ key: "Permissions-Policy",
161
+ value: "camera=(), microphone=(), geolocation=()",
162
+ },
163
+ ],
164
+ },
165
+ ],
166
+ }
167
+
168
+ const bundleAnalyzerPlugin = withBundleAnalyzer({
169
+ enabled: process.env.ANALYZE === "true",
170
+ })
171
+
172
+ const NextApp = () => {
173
+ const plugins = [bundleAnalyzerPlugin]
174
+ return plugins.reduce((config, plugin) => plugin(config), nextConfig)
175
+ }
176
+
177
+ 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
+ }
@@ -0,0 +1,11 @@
1
+ language js
2
+
3
+ or {
4
+ `<Image $attrs />`,
5
+ `<SanityImage $attrs />`
6
+ } as $image where {
7
+ $attrs <: contains `fill`,
8
+ ! $attrs <: contains `fill={false}`,
9
+ ! $attrs <: contains or { `sizes`, `mobileSize`, `desktopSize` },
10
+ register_diagnostic(span=$image, message="A `fill` image has no intrinsic width, so without `sizes` the browser assumes 100vw and requests the largest candidate. Pass `sizes`, or `mobileSize`/`desktopSize`.", severity="error")
11
+ }
@@ -56,8 +56,8 @@ NEXT_PUBLIC_SANITY_API_READ_TOKEN=""
56
56
  # Optional - for server-side mutations and visual editing
57
57
  # SANITY_PRIVATE_TOKEN=""
58
58
 
59
- # Optional - API version (defaults to 2024-03-15)
60
- # 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"
61
61
 
62
62
 
63
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