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
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/presets/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC5C,iBAAiB;IACjB,qBAAqB;IACrB,eAAe;IACf,qBAAqB;CACrB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/presets/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC5C,iBAAiB;IACjB,qBAAqB;IACrB,0BAA0B;IAC1B,eAAe;IACf,qBAAqB;CACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PresetModule } from "../../core/create/types.js";
2
+ export declare const nextPagebuilderCachePreset: PresetModule;
3
+ //# sourceMappingURL=next-pagebuilder-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-pagebuilder-cache.d.ts","sourceRoot":"","sources":["../../../src/modules/presets/next-pagebuilder-cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,eAAO,MAAM,0BAA0B,EAAE,YAQxC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { PRESET_MODULE_IDS, SANITY_PAGEBUILDER_CACHE_FEATURE_MODULE_ID, } from "../../core/create/internal-ids.js";
2
+ export const nextPagebuilderCachePreset = {
3
+ id: PRESET_MODULE_IDS["next-pagebuilder-cache"],
4
+ kind: "preset",
5
+ label: "Page Builder (Cache Components)",
6
+ description: "Page builder preset adopted for Next.js Cache Components (next-sanity v13 strict mode)",
7
+ template: "next-pagebuilder-cache",
8
+ defaultFeatures: [SANITY_PAGEBUILDER_CACHE_FEATURE_MODULE_ID],
9
+ };
10
+ //# sourceMappingURL=next-pagebuilder-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-pagebuilder-cache.js","sourceRoot":"","sources":["../../../src/modules/presets/next-pagebuilder-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EACjB,0CAA0C,GAC1C,MAAM,mCAAmC,CAAC;AAG3C,MAAM,CAAC,MAAM,0BAA0B,GAAiB;IACvD,EAAE,EAAE,iBAAiB,CAAC,wBAAwB,CAAC;IAC/C,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,iCAAiC;IACxC,WAAW,EACV,wFAAwF;IACzF,QAAQ,EAAE,wBAAwB;IAClC,eAAe,EAAE,CAAC,0CAA0C,CAAC;CAC7D,CAAC"}
package/dist/paths.d.ts CHANGED
@@ -19,6 +19,12 @@ export declare const SANITY_FILES_DIR: string;
19
19
  * relative to the project root.
20
20
  */
21
21
  export declare const SANITY_PAGEBUILDER_FILES_DIR: string;
22
+ /**
23
+ * Directory containing the Cache Components variant of the Sanity Page Builder
24
+ * integration source files. Resolves to
25
+ * `src/modules/features/cms/sanity-pagebuilder-cache/files/`.
26
+ */
27
+ export declare const SANITY_PAGEBUILDER_CACHE_FILES_DIR: string;
22
28
  /**
23
29
  * Directory containing the HubSpot integration source files.
24
30
  * Always resolves to `src/modules/features/forms/hubspot/files/` relative to the
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAaA,6DAA6D;AAC7D,eAAO,MAAM,aAAa,EAAE,MAI3B,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,EAAE,MAIhC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,EAAE,MAI9B,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,EAAE,MAKrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAQ9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAQ1C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAQ/B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAQ/B,CAAC"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAaA,6DAA6D;AAC7D,eAAO,MAAM,aAAa,EAAE,MAI3B,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,EAAE,MAIhC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,EAAE,MAI9B,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,EAAE,MAKrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAQ9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAQ1C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,EAAE,MAQhD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAQ/B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAQ/B,CAAC"}
package/dist/paths.js CHANGED
@@ -29,6 +29,12 @@ export const SANITY_FILES_DIR = path.join(PROJECT_ROOT, "src", "modules", "featu
29
29
  * relative to the project root.
30
30
  */
31
31
  export const SANITY_PAGEBUILDER_FILES_DIR = path.join(PROJECT_ROOT, "src", "modules", "features", "cms", "sanity-pagebuilder", "files");
32
+ /**
33
+ * Directory containing the Cache Components variant of the Sanity Page Builder
34
+ * integration source files. Resolves to
35
+ * `src/modules/features/cms/sanity-pagebuilder-cache/files/`.
36
+ */
37
+ export const SANITY_PAGEBUILDER_CACHE_FILES_DIR = path.join(PROJECT_ROOT, "src", "modules", "features", "cms", "sanity-pagebuilder-cache", "files");
32
38
  /**
33
39
  * Directory containing the HubSpot integration source files.
34
40
  * Always resolves to `src/modules/features/forms/hubspot/files/` relative to the
package/dist/paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAW,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAW,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAEnD;;;;GAIG;AACH,MAAM,YAAY,GAAW,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAE3D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAW,IAAI,CAAC,IAAI,CAC7C,YAAY,EACZ,KAAK,EACL,WAAW,CACX,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAW,IAAI,CAAC,IAAI,CAClD,YAAY,EACZ,KAAK,EACL,gBAAgB,CAChB,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAW,IAAI,CAAC,IAAI,CAChD,YAAY,EACZ,KAAK,EACL,cAAc,CACd,CAAC;AAEF,mGAAmG;AACnG,MAAM,CAAC,MAAM,uBAAuB,GAAW,IAAI,CAAC,IAAI,CACvD,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,wBAAwB,CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAW,IAAI,CAAC,IAAI,CAChD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,EACR,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAW,IAAI,CAAC,IAAI,CAC5D,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,oBAAoB,EACpB,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAW,IAAI,CAAC,IAAI,CACjD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,SAAS,EACT,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAW,IAAI,CAAC,IAAI,CACjD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,SAAS,EACT,OAAO,CACP,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAW,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAW,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAEnD;;;;GAIG;AACH,MAAM,YAAY,GAAW,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAE3D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAW,IAAI,CAAC,IAAI,CAC7C,YAAY,EACZ,KAAK,EACL,WAAW,CACX,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAW,IAAI,CAAC,IAAI,CAClD,YAAY,EACZ,KAAK,EACL,gBAAgB,CAChB,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAW,IAAI,CAAC,IAAI,CAChD,YAAY,EACZ,KAAK,EACL,cAAc,CACd,CAAC;AAEF,mGAAmG;AACnG,MAAM,CAAC,MAAM,uBAAuB,GAAW,IAAI,CAAC,IAAI,CACvD,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,wBAAwB,CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAW,IAAI,CAAC,IAAI,CAChD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,EACR,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAW,IAAI,CAAC,IAAI,CAC5D,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,oBAAoB,EACpB,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAW,IAAI,CAAC,IAAI,CAClE,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,0BAA0B,EAC1B,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAW,IAAI,CAAC,IAAI,CACjD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,SAAS,EACT,OAAO,CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAW,IAAI,CAAC,IAAI,CACjD,YAAY,EACZ,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,SAAS,EACT,OAAO,CACP,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bsmnt",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "packageManager": "bun@1.3.14",
5
5
  "description": "CLI to scaffold basement projects and add integrations",
6
6
  "type": "module",
@@ -22,10 +22,12 @@
22
22
  "!src/templates/*/node_modules",
23
23
  "!src/templates/*/.next",
24
24
  "!src/templates/*/bun.lock",
25
+ "!src/templates/*/*.tsbuildinfo",
25
26
  "src/template-hooks",
26
27
  "src/agent-skills",
27
28
  "src/modules/features/cms/sanity/files",
28
29
  "src/modules/features/cms/sanity-pagebuilder/files",
30
+ "src/modules/features/cms/sanity-pagebuilder-cache/files",
29
31
  "src/modules/features/forms/hubspot/files",
30
32
  "src/modules/features/env/dotenvx/files",
31
33
  "src/assets"
@@ -62,6 +64,7 @@
62
64
  "version-canary": "changeset version --snapshot canary",
63
65
  "release-canary": "changeset publish --tag canary --no-git-tag",
64
66
  "test:templates": "bash scripts/test-templates.sh",
67
+ "check:pagebuilder": "bash scripts/typecheck-pagebuilder.sh",
65
68
  "link:local": "bash scripts/build-and-link.sh",
66
69
  "unlink:local": "bash scripts/build-and-link.sh --unlink"
67
70
  },
@@ -98,6 +101,6 @@
98
101
  "lefthook": "^1.13.0",
99
102
  "tsx": "^4.19.0",
100
103
  "turbo": "^2.5.0",
101
- "typescript": "^5.8.0"
104
+ "typescript": "^7.0.2"
102
105
  }
103
106
  }
@@ -2,7 +2,8 @@ import { getImageDimensions } from "@sanity/asset-utils";
2
2
  import { Image, type ImageProps } from "@/components/ui/image";
3
3
  import { urlForImage } from "@/lib/integrations/sanity/utils/image";
4
4
 
5
- interface SanityImageProps extends Omit<ImageProps, "src" | "aspectRatio"> {
5
+ interface SanityImageBaseProps
6
+ extends Omit<ImageProps, "src" | "aspectRatio" | "sizes" | "width" | "height"> {
6
7
  image: {
7
8
  asset?: {
8
9
  _ref: string;
@@ -15,6 +16,38 @@ interface SanityImageProps extends Omit<ImageProps, "src" | "aspectRatio"> {
15
16
  maxWidth?: number;
16
17
  }
17
18
 
19
+ type SanityImageProps = SanityImageBaseProps &
20
+ (
21
+ | { sizes: string; width?: never; height?: never }
22
+ | { width: number; height: number; sizes?: string }
23
+ );
24
+
25
+ const MAX_SOURCE_WIDTH = 3840;
26
+
27
+ const isGifRef = (ref: string) => ref.endsWith("-gif");
28
+
29
+ const getImageSrc = (
30
+ image: SanityImageProps["image"],
31
+ maxWidth: number,
32
+ croppedWidth: number,
33
+ ) => {
34
+ const builder = urlForImage(image);
35
+ const ref = image.asset?._ref ?? "";
36
+
37
+ if (ref.endsWith("-svg")) return builder.url();
38
+
39
+ const requestWidth = Math.min(maxWidth, MAX_SOURCE_WIDTH, croppedWidth);
40
+ const { left, right, top, bottom } = image.crop ?? {};
41
+ const hasCrop = Boolean(left || right || top || bottom);
42
+ const isGif = isGifRef(ref);
43
+
44
+ if (!(isGif || hasCrop) && requestWidth >= croppedWidth) {
45
+ return builder.url();
46
+ }
47
+
48
+ return builder.width(requestWidth).url();
49
+ };
50
+
18
51
  export function SanityImage({
19
52
  image,
20
53
  maxWidth = 1920,
@@ -39,11 +72,10 @@ export function SanityImage({
39
72
 
40
73
  return (
41
74
  <Image
42
- src={urlForImage(image)
43
- .width(Math.min(maxWidth, sourceWidth))
44
- .url()}
75
+ src={getImageSrc(image, maxWidth, sourceWidth)}
45
76
  alt={alt || image.alt || ""}
46
77
  aspectRatio={sourceWidth / sourceHeight}
78
+ unoptimized={isGifRef(image.asset._ref)}
47
79
  {...imageProps}
48
80
  {...props}
49
81
  />
@@ -1,3 +1,5 @@
1
+ import { dataset, projectId } from "@/lib/integrations/sanity/env";
2
+
1
3
  /**
2
4
  * Integration Configuration Checker
3
5
  *
@@ -16,14 +18,13 @@
16
18
  */
17
19
 
18
20
  /**
19
- * Check if Sanity CMS is configured
20
- * Requires: NEXT_PUBLIC_SANITY_PROJECT_ID and NEXT_PUBLIC_SANITY_DATASET
21
+ * Check if Sanity CMS is configured. Derived from env.ts, not a second read of
22
+ * `process.env`: read directly these disagreed — env.ts also accepts
23
+ * `SANITY_STUDIO_PROJECT_ID` and defaults the dataset — so a resolvable project
24
+ * reported itself unconfigured.
21
25
  */
22
26
  export function isSanityConfigured(): boolean {
23
- return Boolean(
24
- process.env.NEXT_PUBLIC_SANITY_PROJECT_ID &&
25
- process.env.NEXT_PUBLIC_SANITY_DATASET,
26
- );
27
+ return Boolean(projectId && dataset);
27
28
  }
28
29
 
29
30
  /**
@@ -14,7 +14,7 @@ SANITY_API_READ_TOKEN="your-viewer-token"
14
14
 
15
15
  # Optional
16
16
  NEXT_PUBLIC_SANITY_STUDIO_URL="http://localhost:3000/studio"
17
- NEXT_PUBLIC_SANITY_API_VERSION="2024-03-15"
17
+ NEXT_PUBLIC_SANITY_API_VERSION="2025-02-19"
18
18
  ```
19
19
 
20
20
  > **Note**: Create a **Viewer** token in [Sanity Dashboard](https://sanity.io/manage) → Your Project → API → Tokens and set it as `SANITY_API_READ_TOKEN`.
@@ -37,7 +37,13 @@ export function RichText({ content }: RichTextProps) {
37
37
  value={content}
38
38
  components={{
39
39
  types: {
40
- image: ({ value }) => <SanityImage image={value} maxWidth={1920} />,
40
+ image: ({ value }) => (
41
+ <SanityImage
42
+ image={value}
43
+ maxWidth={1920}
44
+ sizes="(min-width: 768px) 768px, 100vw"
45
+ />
46
+ ),
41
47
  },
42
48
  marks: {
43
49
  link: ({ children, value }) => {
@@ -51,6 +57,7 @@ export function RichText({ content }: RichTextProps) {
51
57
  rel={
52
58
  isExternal && value?.blank ? "noopener noreferrer" : undefined
53
59
  }
60
+ className="text-blue underline underline-offset-2 transition-opacity hover:opacity-70"
54
61
  data-sanity-edit-target
55
62
  >
56
63
  {children}
@@ -6,9 +6,9 @@
6
6
  * if Sanity is properly set up before making API calls.
7
7
  */
8
8
 
9
- /** Sanity API version - defaults to latest stable */
9
+ /** Floor, not a preference: Content Releases need 2025-02-19 or later. */
10
10
  export const apiVersion =
11
- process.env.NEXT_PUBLIC_SANITY_API_VERSION || "2024-03-15";
11
+ process.env.NEXT_PUBLIC_SANITY_API_VERSION || "2025-02-19";
12
12
 
13
13
  /** Sanity dataset name - defaults to 'production' */
14
14
  export const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET || "production";
@@ -5,6 +5,7 @@ import { PAGE_QUERY } from "@/lib/integrations/sanity/queries";
5
5
  import type { PAGE_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types";
6
6
  import { renderPageBuilderMarkdown } from "@/lib/integrations/sanity/utils/page-builder-markdown";
7
7
  import { getBaseUrl } from "@/lib/utils/base-url";
8
+ import { getSlugTag } from "@/lib/utils/slug-tag";
8
9
 
9
10
  type PageResult = NonNullable<PAGE_QUERY_RESULT>;
10
11
 
@@ -57,6 +58,9 @@ export async function GET(
57
58
  const { data } = await sanityFetch({
58
59
  query: PAGE_QUERY,
59
60
  params: { slug },
61
+ // This route answers at /api/<slug>.md, which no `revalidatePath` on the
62
+ // page path reaches. The tag is the only thing that clears it.
63
+ tags: [getSlugTag(slug)],
60
64
  });
61
65
 
62
66
  const page = data as PageResult | null;
@@ -1,16 +1,37 @@
1
1
  import { revalidatePath, revalidateTag } from "next/cache";
2
2
  import { type NextRequest, NextResponse } from "next/server";
3
3
  import { parseBody } from "next-sanity/webhook";
4
- import { client } from "@/lib/integrations/sanity/client";
4
+ // `directClient`, never `client`: the shared client runs `useCdn: true`, and every
5
+ // lookup here reads state the mutation that triggered this request just produced.
6
+ // A CDN hit returns the pre-mutation slug or folder chain, which purges the old
7
+ // path twice and never touches the new one.
8
+ import { directClient } from "@/lib/integrations/sanity/client";
5
9
  import { SANITY_LAYOUT_TAGS } from "@/lib/integrations/sanity/fetchers/layout";
6
10
  import { SANITY_REDIRECTS_TAG } from "@/lib/integrations/sanity/fetchers/redirects";
7
11
  import { pageBuilderReferenceMembers as pbrm } from "@/lib/integrations/sanity/page-builder-config";
8
12
  import {
9
- P_REF_PB_COMP_QUERY,
13
+ FOLDER_PATH_QUERY,
14
+ P_REF_DOC_PAGES_QUERY,
15
+ P_REV_FOLDER_DESCENDANTS_QUERY,
10
16
  P_REV_SLUGS_QUERY,
11
17
  } from "@/lib/integrations/sanity/queries";
12
- import type { P_REF_PB_COMP_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types";
18
+ import {
19
+ composeDescendantPaths,
20
+ composeResolvedSlug,
21
+ } from "@/lib/integrations/sanity/revalidate-paths";
22
+ import type {
23
+ FOLDER_PATH_QUERY_RESULT,
24
+ P_REF_DOC_PAGES_QUERY_RESULT,
25
+ P_REV_FOLDER_DESCENDANTS_QUERY_RESULT,
26
+ } from "@/lib/integrations/sanity/sanity.types";
27
+ import {
28
+ BLOG_COLLECTION_TAGS,
29
+ BLOG_COLLECTION_TYPES,
30
+ CROSS_DOC_TAG_DEPENDENCIES,
31
+ REFERENCEABLE_TYPES,
32
+ } from "@/lib/integrations/sanity/tags";
13
33
  import { getPagePath } from "@/lib/utils/sitemap";
34
+ import { getSlugTag } from "@/lib/utils/slug-tag";
14
35
 
15
36
  const ERRORS = {
16
37
  BAD_REQ: ["Bad Request", { status: 400 }],
@@ -21,11 +42,16 @@ type WebhookSlug = {
21
42
  current?: string | null;
22
43
  };
23
44
 
45
+ type WebhookReference = {
46
+ _ref?: string | null;
47
+ };
48
+
24
49
  type WebhookDocument = {
25
50
  _id: string;
26
51
  _type: string;
27
- resolvedSlug?: string | null;
28
52
  slug?: WebhookSlug | null;
53
+ pageFolder?: WebhookReference | null;
54
+ parentFolder?: WebhookReference | null;
29
55
  };
30
56
 
31
57
  type MutationOperation = "create" | "update" | "delete";
@@ -36,7 +62,27 @@ type RevalidateWebhookBody = WebhookDocument & {
36
62
  after?: Partial<WebhookDocument> | null;
37
63
  };
38
64
 
39
- const pageBuilderComponent = new Set<string>(pbrm.map((m) => m.documentType));
65
+ const referenceableTypes = new Set<string>([
66
+ ...pbrm.map((m) => m.documentType),
67
+ ...REFERENCEABLE_TYPES,
68
+ ]);
69
+
70
+ // Not `"max"`: a named profile expires a year out, so Next serves the stale entry
71
+ // once while refreshing. A publish should land on the next request, not the one after.
72
+ const PURGE = { expire: 0 } as const;
73
+
74
+ const bustTags = (tags: readonly string[]) => {
75
+ for (const tag of tags) {
76
+ revalidateTag(tag, PURGE);
77
+ }
78
+ };
79
+
80
+ // Both: the path clears the page's route, the tag clears what no page render
81
+ // touches — above all the markdown route, which answers at /api/<slug>.md.
82
+ const bustPage = (slug: string | null) => {
83
+ revalidatePath(getPagePath(slug));
84
+ revalidateTag(getSlugTag(slug), PURGE);
85
+ };
40
86
 
41
87
  const normalizeRevalidationSlug = (slug: string | null | undefined) => {
42
88
  if (slug === undefined) return null;
@@ -45,9 +91,9 @@ const normalizeRevalidationSlug = (slug: string | null | undefined) => {
45
91
  };
46
92
 
47
93
  const getCanonicalPageSlug = async (documentId: string) => {
48
- if (!client) return null;
94
+ if (!directClient) return null;
49
95
 
50
- const pageSlugs = await client.fetch<Array<{ slug: string | null }>>(
96
+ const pageSlugs = await directClient.fetch<Array<{ slug: string | null }>>(
51
97
  P_REV_SLUGS_QUERY,
52
98
  { documentIds: [documentId] },
53
99
  );
@@ -57,24 +103,114 @@ const getCanonicalPageSlug = async (documentId: string) => {
57
103
  );
58
104
  };
59
105
 
60
- const getPagesThatReferenceComp = async (documentId: string) => {
61
- if (!client) return [];
106
+ const getFolder = async (folderId: string | null | undefined) => {
107
+ if (!(directClient && folderId)) return null;
62
108
 
63
- const pages = await client.fetch<P_REF_PB_COMP_QUERY_RESULT>(
64
- P_REF_PB_COMP_QUERY,
65
- {
66
- documentId,
67
- },
109
+ const folder = await directClient.fetch<FOLDER_PATH_QUERY_RESULT>(
110
+ FOLDER_PATH_QUERY,
111
+ { folderId },
112
+ );
113
+
114
+ return folder ?? null;
115
+ };
116
+
117
+ const getPagesReferencing = async (documentIds: readonly string[]) => {
118
+ if (!(directClient && documentIds.length)) return [];
119
+
120
+ const pages = await directClient.fetch<P_REF_DOC_PAGES_QUERY_RESULT>(
121
+ P_REF_DOC_PAGES_QUERY,
122
+ { documentIds },
68
123
  );
69
124
 
70
125
  return (pages ?? []).map((page) => normalizeRevalidationSlug(page.slug));
71
126
  };
72
127
 
128
+ // The webhook carries the raw document, so a page's URL has to be rebuilt from
129
+ // its folder — `slug.current` alone is the page's own segment, which is empty
130
+ // for a folder-index page and missing the prefix for every nested one.
131
+ //
132
+ // `undefined` means "no such revision", distinct from the `null` that a page at
133
+ // the site root legitimately resolves to. Without that split, a payload missing
134
+ // its `before()` projection would purge the homepage on every delete.
135
+ const resolvePageSlug = async (
136
+ revision: Partial<WebhookDocument> | null | undefined,
137
+ ) => {
138
+ if (!revision) return undefined;
139
+
140
+ const folder = await getFolder(revision.pageFolder?._ref);
141
+
142
+ return composeResolvedSlug(folder?.path ?? null, revision.slug?.current);
143
+ };
144
+
145
+ // A folder rename or reparent rewrites the URL of everything beneath it. Neither
146
+ // the folder nor its descendants are `page` mutations, so nothing else in this
147
+ // route would touch them.
148
+ const revalidateFolderSubtree = async (body: RevalidateWebhookBody) => {
149
+ const { before, after } = body;
150
+
151
+ const previousFolderSlug = before?.slug?.current;
152
+ const moved =
153
+ previousFolderSlug !== after?.slug?.current ||
154
+ before?.parentFolder?._ref !== after?.parentFolder?._ref;
155
+
156
+ // A folder edit that touches neither the slug nor the parent — a title, say —
157
+ // changes no URL. `pageFolder` still busts the navbar and collection tags
158
+ // through CROSS_DOC_TAG_DEPENDENCIES below.
159
+ //
160
+ // Deletion is skipped outright: `pageFolder` and `parentFolder` are plain hard
161
+ // references, so Sanity refuses to delete a folder that still has descendants.
162
+ // There is no orphaned subtree to unwind, and querying for one would just cost
163
+ // two round trips to find nothing.
164
+ if (body.operation === "delete") return [];
165
+ if (!(directClient && moved && previousFolderSlug)) return [];
166
+
167
+ const previousParent = await getFolder(before?.parentFolder?._ref);
168
+
169
+ const descendants =
170
+ await directClient.fetch<P_REV_FOLDER_DESCENDANTS_QUERY_RESULT>(
171
+ P_REV_FOLDER_DESCENDANTS_QUERY,
172
+ { folderId: body._id },
173
+ );
174
+
175
+ const movedIds: string[] = [];
176
+
177
+ for (const descendant of descendants ?? []) {
178
+ const paths = composeDescendantPaths({
179
+ folderChain: descendant.folderChain ?? [],
180
+ ownSlug: descendant.ownSlug,
181
+ folderId: body._id,
182
+ previousFolderSlug,
183
+ previousParentPath: previousParent?.path ?? null,
184
+ });
185
+
186
+ if (!paths) {
187
+ console.error("Revalidation: unresolvable folder chain", descendant._id);
188
+ continue;
189
+ }
190
+
191
+ movedIds.push(descendant._id);
192
+ bustPage(paths.current);
193
+ bustPage(paths.previous);
194
+ }
195
+
196
+ // Pages linking *into* the subtree inline the old resolved slugs too.
197
+ return getPagesReferencing(movedIds);
198
+ };
199
+
73
200
  const getAffectedPageSlugsForWebhook = async (body: RevalidateWebhookBody) => {
74
201
  const pages: Array<string | null> = [];
75
202
 
76
- if (body.operation === "delete" && body?.before?.slug?.current) {
77
- revalidateTag(body.before.slug.current, "max");
203
+ if (body._type === "page" && body.before) {
204
+ const previousSlug = await resolvePageSlug(body.before);
205
+
206
+ // Resolved, not raw: a page moved to another folder keeps its own slug and
207
+ // still vacates its old URL, so comparing own slugs would miss it.
208
+ const vacated =
209
+ body.operation === "delete" ||
210
+ (body.operation === "update" &&
211
+ previousSlug !== (await resolvePageSlug(body.after)));
212
+
213
+ if (vacated && previousSlug !== undefined) bustPage(previousSlug);
78
214
  }
79
215
 
80
216
  // If the document is a page, get its slug
@@ -83,13 +219,17 @@ const getAffectedPageSlugsForWebhook = async (body: RevalidateWebhookBody) => {
83
219
  if (data !== null) pages.push(data);
84
220
  }
85
221
 
86
- // If the document is a page builder component, get the page slugs that reference it
87
- if (pageBuilderComponent.has(body._type)) {
88
- const data = await getPagesThatReferenceComp(body._id);
89
- pages.push(...data);
222
+ // Page-builder blocks, `author`, `blogCategory` and other pages are all
223
+ // inlined into pages that no other branch here revalidates.
224
+ if (referenceableTypes.has(body._type)) {
225
+ pages.push(...(await getPagesReferencing([body._id])));
90
226
  }
91
227
 
92
- return pages.filter((page): page is string => page !== null);
228
+ if (body._type === "pageFolder") {
229
+ pages.push(...(await revalidateFolderSubtree(body)));
230
+ }
231
+
232
+ return [...new Set(pages.filter((page): page is string => page !== null))];
93
233
  };
94
234
 
95
235
  export async function POST(request: NextRequest) {
@@ -107,15 +247,23 @@ export async function POST(request: NextRequest) {
107
247
  const affectedPageSlugs = await getAffectedPageSlugsForWebhook(body);
108
248
 
109
249
  for (const slug of affectedPageSlugs) {
110
- revalidatePath(getPagePath(slug));
250
+ bustPage(slug);
111
251
  }
112
252
 
113
253
  if (SANITY_LAYOUT_TAGS.includes(body?._type)) {
114
- revalidateTag(body._type, "max");
254
+ revalidateTag(body._type, PURGE);
115
255
  }
116
256
 
257
+ // Queries that read across document types — a `structuredData` entry that
258
+ // folds in `companyData`, a navbar that derefs pages.
259
+ bustTags(CROSS_DOC_TAG_DEPENDENCIES[body._type] ?? []);
260
+
261
+ // The content-collection block caches list/count/categories under their own
262
+ // tags, which no per-page revalidation above touches.
263
+ if (BLOG_COLLECTION_TYPES.has(body._type)) bustTags(BLOG_COLLECTION_TAGS);
264
+
117
265
  if (body._type === SANITY_REDIRECTS_TAG) {
118
- revalidateTag(SANITY_REDIRECTS_TAG, "max");
266
+ revalidateTag(SANITY_REDIRECTS_TAG, PURGE);
119
267
  }
120
268
 
121
269
  return NextResponse.json({ status: 200, now: Date.now() });
@@ -1,20 +1,27 @@
1
+ import { fetchSanity } from "@/lib/integrations/sanity/live";
1
2
  import { ALL_BLOG_ARTICLES_QUERY } from "@/lib/integrations/sanity/queries";
3
+ import type { ALL_BLOG_ARTICLES_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types";
4
+ import { FEED_TAG } from "@/lib/integrations/sanity/tags";
2
5
  import { generateRssFeed, rssErrorResponse } from "@/lib/utils/rss";
3
6
  import { getPageUrl, getSitemapBaseUrl } from "@/lib/utils/sitemap";
4
7
 
5
- export const dynamic = "force-dynamic";
6
-
8
+ // Not `force-dynamic`: feed readers poll, so per-request rendering charged a
9
+ // Sanity round trip per poll. The webhook busts FEED_TAG for `page`, `pageFolder`,
10
+ // `author` and `blogCategory` — this query derefs the byline and resolves slugs
11
+ // through folder chains.
7
12
  export async function GET() {
8
13
  const baseUrl = getSitemapBaseUrl();
9
14
 
10
15
  try {
11
- const sanityModule = await import("@/lib/integrations/sanity/client");
12
- const client = sanityModule?.client;
13
- if (!client) return rssErrorResponse();
16
+ const { data: articles } =
17
+ await fetchSanity<ALL_BLOG_ARTICLES_QUERY_RESULT>({
18
+ query: ALL_BLOG_ARTICLES_QUERY,
19
+ tags: [FEED_TAG],
20
+ });
14
21
 
15
- const articles = await client.fetch(ALL_BLOG_ARTICLES_QUERY);
22
+ if (!articles) return rssErrorResponse();
16
23
 
17
- const items = (articles ?? [])
24
+ const items = articles
18
25
  .filter((article) => article.resolvedSlug && !article.noIndex)
19
26
  .map((article) => ({
20
27
  title: article.title ?? "Untitled",
@@ -7,7 +7,8 @@ import {
7
7
  getSitemapBaseUrl,
8
8
  } from "@/lib/utils/sitemap";
9
9
 
10
- export const dynamic = "force-dynamic";
10
+ // Cached, not per-request: this bills itself as being for AI agents, so its
11
+ // traffic is crawler-driven. `getSitemap` tags the read; the webhook busts it.
11
12
 
12
13
  type PageDoc = PAGE_SITEMAP_QUERY_RESULT[number];
13
14
 
@@ -117,7 +118,6 @@ export const GET = async () => {
117
118
  headers: {
118
119
  "Content-Type": "text/markdown; charset=utf-8",
119
120
  "X-Content-Type-Options": "nosniff",
120
- "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=600",
121
121
  },
122
122
  });
123
123
  } catch (error) {
@@ -1,8 +1,23 @@
1
1
  "use client";
2
2
 
3
3
  import { NextStudio } from "next-sanity/studio";
4
+ import { isSanityConfigured } from "@/lib/integrations/check-integration";
4
5
  import config from "@/lib/integrations/sanity/sanity.config";
5
6
 
6
- const StudioPage = () => <NextStudio config={config} />;
7
+ // The Studio throws on an empty `projectId`, which `env.ts` falls back to when
8
+ // Sanity isn't configured — so this route would fail `next build`.
9
+ const StudioPage = () =>
10
+ isSanityConfigured() ? (
11
+ <NextStudio config={config} />
12
+ ) : (
13
+ <main style={{ padding: "2rem", fontFamily: "system-ui, sans-serif" }}>
14
+ <h1>Studio unavailable</h1>
15
+ <p>
16
+ Set <code>NEXT_PUBLIC_SANITY_PROJECT_ID</code> and{" "}
17
+ <code>NEXT_PUBLIC_SANITY_DATASET</code>, then restart, to load the
18
+ embedded Studio.
19
+ </p>
20
+ </main>
21
+ );
7
22
 
8
23
  export default StudioPage;
@@ -26,6 +26,7 @@ const LinkMark = ({ children, value }: LinkMarkProps) => {
26
26
  href={href}
27
27
  target={attrs.target}
28
28
  rel={attrs.rel}
29
+ className="text-blue underline underline-offset-2 transition-opacity hover:opacity-70"
29
30
  data-sanity-edit-target
30
31
  >
31
32
  {children}
@@ -41,7 +42,13 @@ export const RichText = ({ content }: RichTextProps) => {
41
42
  value={content}
42
43
  components={{
43
44
  types: {
44
- image: ({ value }) => <SanityImage image={value} maxWidth={1920} />,
45
+ image: ({ value }) => (
46
+ <SanityImage
47
+ image={value}
48
+ maxWidth={1920}
49
+ sizes="(min-width: 768px) 768px, 100vw"
50
+ />
51
+ ),
45
52
  table: ({ value }) => {
46
53
  const rows = value?.rows as
47
54
  | Array<{ _key?: string; cells?: string[] }>