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,22 @@
1
+ import {
2
+ PUBLISHED_FETCH_OPTIONS,
3
+ sanityFetch,
4
+ toSanityFetchOptions,
5
+ } from "@/lib/integrations/sanity/live"
6
+ import { REDIRECTS_QUERY } from "@/lib/integrations/sanity/queries"
7
+ import type { REDIRECTS_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types"
8
+ import { SANITY_REDIRECTS_TAG } from "@/lib/integrations/sanity/tags"
9
+
10
+ export type RedirectEntry = REDIRECTS_QUERY_RESULT[number]
11
+
12
+ // Routing infra, not preview content — always read published and cache it.
13
+ export async function getRedirects(): Promise<REDIRECTS_QUERY_RESULT> {
14
+ "use cache"
15
+ const { data } = await sanityFetch({
16
+ query: REDIRECTS_QUERY,
17
+ ...toSanityFetchOptions(PUBLISHED_FETCH_OPTIONS),
18
+ tags: [SANITY_REDIRECTS_TAG],
19
+ })
20
+
21
+ return (data as REDIRECTS_QUERY_RESULT | null) ?? []
22
+ }
@@ -0,0 +1,81 @@
1
+ import type { Icon, IconProps } from "@phosphor-icons/react";
2
+ import {
3
+ AppWindowIcon,
4
+ ArrowBendUpRightIcon,
5
+ ArticleNyTimesIcon,
6
+ BracketsCurlyIcon,
7
+ BriefcaseIcon,
8
+ BrowsersIcon,
9
+ BuildingsIcon,
10
+ CalendarBlankIcon,
11
+ CardsIcon,
12
+ FileTextIcon,
13
+ FolderOpenIcon,
14
+ FootprintsIcon,
15
+ LayoutIcon,
16
+ ListBulletsIcon,
17
+ ListIcon,
18
+ LockKeyIcon,
19
+ PackageIcon,
20
+ QuestionIcon,
21
+ RocketIcon,
22
+ ShapesIcon,
23
+ ShareNetworkIcon,
24
+ TagIcon,
25
+ TextAlignLeftIcon,
26
+ TextTIcon,
27
+ TreeStructureIcon,
28
+ UserCircleIcon,
29
+ VideoCameraIcon,
30
+ } from "@phosphor-icons/react/dist/ssr";
31
+ import { createElement, forwardRef } from "react";
32
+
33
+ export type SanityStudioIcon = Icon;
34
+
35
+ const asDuotoneIcon = (IconComponent: Icon): SanityStudioIcon => {
36
+ const DuotoneIcon = forwardRef<SVGSVGElement, IconProps>((props, ref) =>
37
+ createElement(IconComponent, { ...props, ref, weight: "duotone" }),
38
+ );
39
+
40
+ DuotoneIcon.displayName = `${IconComponent.displayName ?? "Phosphor"}Duotone`;
41
+
42
+ return DuotoneIcon;
43
+ };
44
+
45
+ export const pageBuilderCardIcon = asDuotoneIcon(PackageIcon);
46
+ export const pageBuilderCardListIcon = asDuotoneIcon(ListIcon);
47
+
48
+ export const authorIcon = asDuotoneIcon(UserCircleIcon);
49
+
50
+ export const pageListIcon = asDuotoneIcon(ListBulletsIcon);
51
+
52
+ export const blogCategoryIcon = asDuotoneIcon(TagIcon);
53
+
54
+ export const componentsFolderIcon = asDuotoneIcon(ShapesIcon);
55
+
56
+ export const companyDataIcon = asDuotoneIcon(BuildingsIcon);
57
+ export const socialLinksIcon = asDuotoneIcon(ShareNetworkIcon);
58
+ export const navbarIcon = asDuotoneIcon(ListIcon);
59
+ export const footerIcon = asDuotoneIcon(FootprintsIcon);
60
+ export const redirectIcon = asDuotoneIcon(ArrowBendUpRightIcon);
61
+ export const layoutFolderIcon = asDuotoneIcon(LayoutIcon);
62
+ export const structuredDataIcon = asDuotoneIcon(TreeStructureIcon);
63
+
64
+ export const faqJsonLdIcon = asDuotoneIcon(QuestionIcon);
65
+ export const eventJsonLdIcon = asDuotoneIcon(CalendarBlankIcon);
66
+ export const videoJsonLdIcon = asDuotoneIcon(VideoCameraIcon);
67
+ export const jobPostingJsonLdIcon = asDuotoneIcon(BriefcaseIcon);
68
+ export const softwareApplicationJsonLdIcon = asDuotoneIcon(AppWindowIcon);
69
+ export const itemListJsonLdIcon = asDuotoneIcon(CardsIcon);
70
+ export const customJsonLdIcon = asDuotoneIcon(BracketsCurlyIcon);
71
+
72
+ export const heroIcon = asDuotoneIcon(RocketIcon);
73
+ export const descriptionIcon = asDuotoneIcon(TextAlignLeftIcon);
74
+ export const richTextIcon = asDuotoneIcon(TextTIcon);
75
+ export const contentIcon = asDuotoneIcon(ArticleNyTimesIcon);
76
+ export const gatedContentIcon = asDuotoneIcon(LockKeyIcon);
77
+
78
+ export const pageIcon = asDuotoneIcon(FileTextIcon);
79
+ export const pagesFolderIcon = asDuotoneIcon(BrowsersIcon);
80
+ export const pageFolderIcon = asDuotoneIcon(FolderOpenIcon);
81
+ export const contentFolderIcon = asDuotoneIcon(FolderOpenIcon);
@@ -0,0 +1,140 @@
1
+ import { cacheLife, cacheTag } from "next/cache";
2
+ import type { QueryParams } from "next-sanity";
3
+ import {
4
+ defineLive,
5
+ type LivePerspective,
6
+ resolvePerspectiveFromCookies,
7
+ resolveVariantFromCookies,
8
+ type StrictDefinedFetchType,
9
+ type StrictDefinedLiveProps,
10
+ } from "next-sanity/live";
11
+ import { cookies, draftMode } from "next/headers";
12
+ import type { ComponentType } from "react";
13
+ import { isSanityConfigured } from "@/lib/integrations/check-integration";
14
+ import { client } from "../client";
15
+ import { sanityToken } from "../env";
16
+
17
+ const isConfigured = isSanityConfigured() && client;
18
+
19
+ // `strict: true` requires perspective/stega at every call site, resolved outside
20
+ // the `'use cache'` boundary so published reads can land in the static shell.
21
+ const liveExports =
22
+ isConfigured && client
23
+ ? defineLive({
24
+ client,
25
+ browserToken: sanityToken ?? false,
26
+ serverToken: sanityToken ?? false,
27
+ strict: true,
28
+ })
29
+ : null;
30
+
31
+ export interface DynamicFetchOptions {
32
+ perspective: LivePerspective;
33
+ stega: boolean;
34
+ // Required, not optional: absence is valid, but an optional key lets a call
35
+ // site drop it and serve base content to someone previewing a release.
36
+ variant: string | undefined;
37
+ }
38
+
39
+ // What every static branch reads. Shared so a new field can't be missed at one
40
+ // call site.
41
+ export const PUBLISHED_FETCH_OPTIONS: DynamicFetchOptions = {
42
+ perspective: "published",
43
+ stega: false,
44
+ variant: undefined,
45
+ };
46
+
47
+ // Under `exactOptionalPropertyTypes` an explicit `undefined` variant is a type
48
+ // error, so raw `DynamicFetchOptions` can't be spread into a fetch. That's the
49
+ // point: it forces call sites through here instead of dropping `variant`.
50
+ export const toSanityFetchOptions = ({
51
+ perspective,
52
+ stega,
53
+ variant,
54
+ }: DynamicFetchOptions) => ({
55
+ perspective,
56
+ stega,
57
+ ...(variant === undefined ? {} : { variant }),
58
+ });
59
+
60
+ // Null-returning stubs keep the template buildable without Sanity env.
61
+ const fallbackFetch = (async () => ({
62
+ data: null,
63
+ sourceMap: null,
64
+ tags: [],
65
+ })) as unknown as StrictDefinedFetchType;
66
+
67
+ export const sanityFetch: StrictDefinedFetchType =
68
+ liveExports?.sanityFetch ?? fallbackFetch;
69
+
70
+ export const SanityLive: ComponentType<StrictDefinedLiveProps> =
71
+ liveExports?.SanityLive ?? (() => null);
72
+
73
+ // Prerender-safe: `draftMode()` resolves false without bailing out, and
74
+ // `cookies()` is only read once draft mode is on. `strict: true` disables
75
+ // next-sanity's own cookie resolution, so the variant must be read here.
76
+ export async function getDynamicFetchOptions(): Promise<DynamicFetchOptions> {
77
+ const { isEnabled: isDraftMode } = await draftMode();
78
+ if (!isDraftMode)
79
+ return { perspective: "published", stega: false, variant: undefined };
80
+
81
+ const jar = await cookies();
82
+ const [perspective, variant] = await Promise.all([
83
+ resolvePerspectiveFromCookies({ cookies: jar }),
84
+ resolveVariantFromCookies({ cookies: jar }),
85
+ ]);
86
+ return { perspective: perspective ?? "drafts", stega: true, variant };
87
+ }
88
+
89
+ // For `generateStaticParams`: cookies aren't available at build time and stega
90
+ // is never wanted in route params, so both are hardcoded.
91
+ export async function sanityFetchStaticParams<T = unknown>({
92
+ query,
93
+ params = {},
94
+ }: {
95
+ query: string;
96
+ params?: QueryParams;
97
+ }): Promise<{ data: T | null }> {
98
+ "use cache";
99
+ const { data } = await sanityFetch({
100
+ query,
101
+ params,
102
+ ...toSanityFetchOptions(PUBLISHED_FETCH_OPTIONS),
103
+ });
104
+ return { data: (data as T | null) ?? null };
105
+ }
106
+
107
+ // Cached read for contexts that render no DOM next to <VisualEditing>. `tags` is
108
+ // required, not optional: the markdown route answers at /api/<slug>.md, which no
109
+ // `revalidatePath` reaches, so an untagged entry is stranded for the ~1y lifetime.
110
+ // Takes the whole options object and overrides `stega` itself, so call sites
111
+ // can't hand-pick fields and drop `variant`.
112
+ export async function sanityFetchCached<T = unknown>({
113
+ query,
114
+ params = {},
115
+ tags,
116
+ ...fetchOptions
117
+ }: {
118
+ query: string;
119
+ params?: QueryParams;
120
+ tags: string[];
121
+ } & DynamicFetchOptions): Promise<{ data: T | null }> {
122
+ "use cache";
123
+ const { data } = await sanityFetch({
124
+ query,
125
+ params,
126
+ ...toSanityFetchOptions(fetchOptions),
127
+ stega: false,
128
+ });
129
+ const result = (data as T | null) ?? null;
130
+
131
+ if (result === null) {
132
+ // No document, so no publish clears this — and any URL can mint one.
133
+ cacheLife("hours");
134
+ } else {
135
+ // Tagged on a hit only, for that same reason — mirrors `getCachedPage`.
136
+ cacheTag(...tags);
137
+ }
138
+
139
+ return { data: result };
140
+ }
@@ -0,0 +1,50 @@
1
+ export interface MarkdownRoute {
2
+ /** Regex to match the public-facing URL */
3
+ regex: RegExp;
4
+ /** API route path template (under /api/) */
5
+ apiPath: string;
6
+ /** Public markdown URL template (for Link headers) */
7
+ publicPath: string;
8
+ }
9
+
10
+ /**
11
+ * Routes that serve markdown versions for AI agents.
12
+ * All pages are backed by the shared `page` document type and resolved
13
+ * through the catch-all route handlers.
14
+ *
15
+ * How it works:
16
+ * - `regex`: match the public-facing URL (e.g. /about.md or /about)
17
+ * - `apiPath`: the internal API route that serves the markdown (e.g. /api/about.md)
18
+ * - Proxy rewrites .md URLs and Accept: text/markdown requests to the API route
19
+ * - Route handlers live under /api/ so page.tsx can coexist at the public path
20
+ */
21
+
22
+ /** .md extension routes -- rewrite to API endpoints */
23
+ export const mdExtensionRoutes: MarkdownRoute[] = [
24
+ {
25
+ regex: /^\/((?:[^/]+\/)*[^/]+)\.md$/,
26
+ apiPath: "/api/[slug].md",
27
+ publicPath: "/[slug].md",
28
+ },
29
+ ];
30
+
31
+ /** Accept: text/markdown routes -- content negotiation for HTML pages */
32
+ export const acceptHeaderRoutes: MarkdownRoute[] = [
33
+ {
34
+ regex: /^\/(.+)$/,
35
+ apiPath: "/api/[slug].md",
36
+ publicPath: "/[slug].md",
37
+ },
38
+ ];
39
+
40
+ /**
41
+ * Paths the proxy should never process.
42
+ * Studio, static files, Next.js internals.
43
+ */
44
+ export const ignoredPaths = [
45
+ "/studio",
46
+ "/api/",
47
+ "/_next/",
48
+ "/favicon.ico",
49
+ "/sitemap.md",
50
+ ];
@@ -0,0 +1,182 @@
1
+ import { contentIcon, pageIcon, type SanityStudioIcon } from "./icons";
2
+ import { singletonComponents } from "./singletons";
3
+
4
+ export type PageBuilderDocumentType =
5
+ | "hero"
6
+ | "description"
7
+ | "richTextBlock"
8
+ | "gatedContent"
9
+ | "blogContent"
10
+ | (typeof singletonComponents)[number]["schemaType"];
11
+
12
+ /**
13
+ * A block declares two orthogonal axes. `pageTypes` is which page documents may
14
+ * host it and drives validation; `category` is what the block structurally is
15
+ * and drives the insert menu. Never collapse them back into one field — that is
16
+ * what made the menu a single flat list.
17
+ */
18
+ export type PageBuilderGroupName = "generic" | "blogEntry";
19
+
20
+ export const componentCategories = [
21
+ { name: "hero", title: "Hero" },
22
+ { name: "text", title: "Text" },
23
+ { name: "list", title: "List" },
24
+ { name: "content", title: "Content" },
25
+ { name: "misc", title: "Miscellaneous" },
26
+ ] as const satisfies ReadonlyArray<{ name: string; title: string }>;
27
+
28
+ export type ComponentCategory = (typeof componentCategories)[number]["name"];
29
+
30
+ type PageBuilderReferenceMember = {
31
+ documentType: PageBuilderDocumentType;
32
+ name: string;
33
+ title: string;
34
+ documentId?: string;
35
+ pageTypes: readonly PageBuilderGroupName[];
36
+ category: ComponentCategory;
37
+ };
38
+
39
+ export const blockPreviewKey = (schemaTypeName: string) =>
40
+ `block.${schemaTypeName}`;
41
+
42
+ export const pageBuilderPageTypes: Array<{
43
+ title: string;
44
+ value: PageBuilderGroupName;
45
+ }> = [
46
+ { title: "Generic", value: "generic" },
47
+ { title: "Blog Entry", value: "blogEntry" },
48
+ ];
49
+
50
+ const pageCategoryIcons: Record<PageBuilderGroupName, SanityStudioIcon> = {
51
+ generic: pageIcon,
52
+ blogEntry: contentIcon,
53
+ };
54
+
55
+ export const getPageCategoryIcon = (
56
+ pageType: PageBuilderGroupName | undefined | null,
57
+ ) => pageCategoryIcons[pageType ?? "generic"];
58
+
59
+ const reusablePageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
60
+ {
61
+ documentType: "hero",
62
+ name: "heroReference",
63
+ title: "Heading",
64
+ pageTypes: ["generic"],
65
+ category: "hero",
66
+ },
67
+ {
68
+ documentType: "description",
69
+ name: "descriptionReference",
70
+ title: "Description",
71
+ pageTypes: ["generic"],
72
+ category: "text",
73
+ },
74
+ {
75
+ documentType: "richTextBlock",
76
+ name: "richTextBlockReference",
77
+ title: "Rich Text",
78
+ pageTypes: ["generic"],
79
+ category: "text",
80
+ },
81
+ {
82
+ documentType: "gatedContent",
83
+ name: "gatedContentReference",
84
+ title: "Gated Content",
85
+ pageTypes: ["generic"],
86
+ category: "misc",
87
+ },
88
+ {
89
+ documentType: "blogContent",
90
+ name: "blogContentReference",
91
+ title: "Blog Content",
92
+ pageTypes: ["blogEntry"],
93
+ category: "content",
94
+ },
95
+ ];
96
+
97
+ const singletonPageBuilderReferenceMembers: PageBuilderReferenceMember[] =
98
+ singletonComponents.map((component) => ({
99
+ documentType: component.schemaType,
100
+ name: `${component.schemaType}Reference`,
101
+ title: component.title,
102
+ documentId: component.documentId,
103
+ pageTypes: ["generic"],
104
+ category: component.category,
105
+ }));
106
+
107
+ export const pageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
108
+ ...reusablePageBuilderReferenceMembers,
109
+ ...singletonPageBuilderReferenceMembers,
110
+ ];
111
+
112
+ export const getPageBuilderReferenceMember = (name: string) =>
113
+ pageBuilderReferenceMembers.find((member) => member.name === name);
114
+
115
+ export const getPageBuilderReferenceMemberByDocumentType = (
116
+ documentType: PageBuilderDocumentType,
117
+ ) =>
118
+ pageBuilderReferenceMembers.find(
119
+ (member) => member.documentType === documentType,
120
+ );
121
+
122
+ const isMemberVisibleForPageType = (
123
+ member: PageBuilderReferenceMember,
124
+ pageType: PageBuilderGroupName | undefined,
125
+ ) => member.pageTypes.includes(pageType ?? "generic");
126
+
127
+ export const getVisiblePageBuilderReferenceMembers = (
128
+ pageType: PageBuilderGroupName | undefined,
129
+ ) =>
130
+ pageBuilderReferenceMembers.filter((member) =>
131
+ isMemberVisibleForPageType(member, pageType),
132
+ );
133
+
134
+ export const getVisiblePageBuilderMemberNames = (
135
+ pageType: PageBuilderGroupName | undefined,
136
+ ) =>
137
+ new Set(
138
+ getVisiblePageBuilderReferenceMembers(pageType).map((member) => member.name),
139
+ );
140
+
141
+ export const getVisiblePageBuilderInsertMenuGroups = (
142
+ pageType: PageBuilderGroupName | undefined,
143
+ ) => {
144
+ const visible = getVisiblePageBuilderMemberNames(pageType);
145
+ return pageBuilderInsertMenuGroups
146
+ .map((group) => ({
147
+ ...group,
148
+ of: group.of.filter((name) => visible.has(name)),
149
+ }))
150
+ .filter((group) => group.of.length > 0);
151
+ };
152
+
153
+ export const getInvalidPageBuilderDocumentTypes = (
154
+ pageType: PageBuilderGroupName | undefined,
155
+ documentTypes: PageBuilderDocumentType[],
156
+ ) =>
157
+ documentTypes.filter((documentType) => {
158
+ const member = getPageBuilderReferenceMemberByDocumentType(documentType);
159
+
160
+ if (!member) return false;
161
+
162
+ return !isMemberVisibleForPageType(member, pageType);
163
+ });
164
+
165
+ export const pageBuilderInsertMenuGroups: Array<{
166
+ name: ComponentCategory;
167
+ title: string;
168
+ of: string[];
169
+ }> = componentCategories.map(({ name, title }) => ({
170
+ name,
171
+ title,
172
+ of: pageBuilderReferenceMembers
173
+ .filter((member) => member.category === name)
174
+ .map((member) => member.name),
175
+ }));
176
+
177
+ export const pageBuilderBlockPreviewOptions = pageBuilderReferenceMembers.map(
178
+ (member) => ({
179
+ title: `Block — ${member.title} · ${member.name}`,
180
+ value: blockPreviewKey(member.name),
181
+ }),
182
+ );
@@ -0,0 +1,28 @@
1
+ import type { PageBuilderGroupName } from "@/lib/integrations/sanity/page-builder-config";
2
+
3
+ type PageCategoryParams = {
4
+ slug?: string | null;
5
+ folder?: string | null;
6
+ };
7
+
8
+ export const isEmptyPageSlug = (slug?: string | null) =>
9
+ slug == null || slug === "" || slug === "/";
10
+
11
+ export const getGeneratedPageCategory = ({
12
+ slug,
13
+ folder,
14
+ }: PageCategoryParams): PageBuilderGroupName => {
15
+ if (!isEmptyPageSlug(slug) && folder === "blog") return "blogEntry";
16
+
17
+ return "generic";
18
+ };
19
+
20
+ export const pageCategoryExpression = `
21
+ select(
22
+ defined(slug.current) &&
23
+ slug.current != "" &&
24
+ slug.current != "/" &&
25
+ pageFolder->slug.current == "blog" => "blogEntry",
26
+ "generic"
27
+ )
28
+ `;