bsmnt 0.4.3 → 0.6.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 (266) hide show
  1. package/README.md +1 -0
  2. package/dist/application/add-hooks/index.d.ts.map +1 -1
  3. package/dist/application/add-hooks/index.js +1 -0
  4. package/dist/application/add-hooks/index.js.map +1 -1
  5. package/dist/application/add-integration/index.d.ts +33 -8
  6. package/dist/application/add-integration/index.d.ts.map +1 -1
  7. package/dist/application/add-integration/index.js +221 -90
  8. package/dist/application/add-integration/index.js.map +1 -1
  9. package/dist/application/create-project/build-context.d.ts +3 -1
  10. package/dist/application/create-project/build-context.d.ts.map +1 -1
  11. package/dist/application/create-project/build-context.js +2 -1
  12. package/dist/application/create-project/build-context.js.map +1 -1
  13. package/dist/application/create-project/index.d.ts +3 -1
  14. package/dist/application/create-project/index.d.ts.map +1 -1
  15. package/dist/application/create-project/index.js +4 -2
  16. package/dist/application/create-project/index.js.map +1 -1
  17. package/dist/application/create-project/map-selection-to-registry.js +1 -1
  18. package/dist/application/create-project/map-selection-to-registry.js.map +1 -1
  19. package/dist/application/install-skills/index.js +1 -1
  20. package/dist/application/install-skills/index.js.map +1 -1
  21. package/dist/application/shared/project-detection.d.ts +2 -2
  22. package/dist/application/shared/project-detection.d.ts.map +1 -1
  23. package/dist/application/shared/project-detection.js +2 -2
  24. package/dist/application/shared/project-detection.js.map +1 -1
  25. package/dist/core/create/execute-plan.d.ts +4 -0
  26. package/dist/core/create/execute-plan.d.ts.map +1 -1
  27. package/dist/core/create/execute-plan.js +8 -0
  28. package/dist/core/create/execute-plan.js.map +1 -1
  29. package/dist/core/create/internal-ids.d.ts +4 -1
  30. package/dist/core/create/internal-ids.d.ts.map +1 -1
  31. package/dist/core/create/internal-ids.js +6 -1
  32. package/dist/core/create/internal-ids.js.map +1 -1
  33. package/dist/core/create/types.d.ts +2 -0
  34. package/dist/core/create/types.d.ts.map +1 -1
  35. package/dist/domain/cms.d.ts +0 -7
  36. package/dist/domain/cms.d.ts.map +1 -1
  37. package/dist/domain/cms.js.map +1 -1
  38. package/dist/domain/forms.d.ts +17 -0
  39. package/dist/domain/forms.d.ts.map +1 -0
  40. package/dist/domain/forms.js +13 -0
  41. package/dist/domain/forms.js.map +1 -0
  42. package/dist/domain/integration.d.ts +30 -0
  43. package/dist/domain/integration.d.ts.map +1 -0
  44. package/dist/domain/integration.js +12 -0
  45. package/dist/domain/integration.js.map +1 -0
  46. package/dist/domain/skills.d.ts +58 -0
  47. package/dist/domain/skills.d.ts.map +1 -1
  48. package/dist/domain/skills.js +52 -0
  49. package/dist/domain/skills.js.map +1 -1
  50. package/dist/index.js +114 -38
  51. package/dist/index.js.map +1 -1
  52. package/dist/infrastructure/agents/register-sanity-mcp.js +9 -6
  53. package/dist/infrastructure/agents/register-sanity-mcp.js.map +1 -1
  54. package/dist/infrastructure/create/apply-package-json.d.ts.map +1 -1
  55. package/dist/infrastructure/create/apply-package-json.js +19 -0
  56. package/dist/infrastructure/create/apply-package-json.js.map +1 -1
  57. package/dist/infrastructure/create/executor.d.ts.map +1 -1
  58. package/dist/infrastructure/create/executor.js +5 -0
  59. package/dist/infrastructure/create/executor.js.map +1 -1
  60. package/dist/infrastructure/create/install-dependencies.d.ts.map +1 -1
  61. package/dist/infrastructure/create/install-dependencies.js +4 -0
  62. package/dist/infrastructure/create/install-dependencies.js.map +1 -1
  63. package/dist/infrastructure/create/lifecycle-registry.d.ts.map +1 -1
  64. package/dist/infrastructure/create/lifecycle-registry.js +2 -0
  65. package/dist/infrastructure/create/lifecycle-registry.js.map +1 -1
  66. package/dist/infrastructure/create/merge-registry.d.ts.map +1 -1
  67. package/dist/infrastructure/create/merge-registry.js +8 -0
  68. package/dist/infrastructure/create/merge-registry.js.map +1 -1
  69. package/dist/infrastructure/create/setup-agent.d.ts +2 -0
  70. package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
  71. package/dist/infrastructure/create/setup-agent.js +32 -8
  72. package/dist/infrastructure/create/setup-agent.js.map +1 -1
  73. package/dist/infrastructure/create/setup-dotenvx.d.ts +41 -0
  74. package/dist/infrastructure/create/setup-dotenvx.d.ts.map +1 -0
  75. package/dist/infrastructure/create/setup-dotenvx.js +502 -0
  76. package/dist/infrastructure/create/setup-dotenvx.js.map +1 -0
  77. package/dist/infrastructure/create/setup-sanity.d.ts +13 -1
  78. package/dist/infrastructure/create/setup-sanity.d.ts.map +1 -1
  79. package/dist/infrastructure/create/setup-sanity.js +74 -31
  80. package/dist/infrastructure/create/setup-sanity.js.map +1 -1
  81. package/dist/infrastructure/integrations/inject-integration.d.ts +3 -3
  82. package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
  83. package/dist/infrastructure/integrations/inject-integration.js +81 -37
  84. package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
  85. package/dist/modules/features/cms/sanity/config.d.ts.map +1 -1
  86. package/dist/modules/features/cms/sanity/config.js +13 -6
  87. package/dist/modules/features/cms/sanity/config.js.map +1 -1
  88. package/dist/modules/features/cms/sanity/index.js +8 -2
  89. package/dist/modules/features/cms/sanity/index.js.map +1 -1
  90. package/dist/modules/features/cms/sanity/mergers/ci-workflow.d.ts +13 -0
  91. package/dist/modules/features/cms/sanity/mergers/ci-workflow.d.ts.map +1 -0
  92. package/dist/modules/features/cms/sanity/mergers/ci-workflow.js +38 -0
  93. package/dist/modules/features/cms/sanity/mergers/ci-workflow.js.map +1 -0
  94. package/dist/modules/features/cms/sanity/mergers/knip.d.ts +12 -0
  95. package/dist/modules/features/cms/sanity/mergers/knip.d.ts.map +1 -0
  96. package/dist/modules/features/cms/sanity/mergers/knip.js +38 -0
  97. package/dist/modules/features/cms/sanity/mergers/knip.js.map +1 -0
  98. package/dist/modules/features/cms/sanity/mergers/layout.d.ts.map +1 -1
  99. package/dist/modules/features/cms/sanity/mergers/layout.js +17 -3
  100. package/dist/modules/features/cms/sanity/mergers/layout.js.map +1 -1
  101. package/dist/modules/features/cms/sanity/mergers/sitemap.d.ts +3 -3
  102. package/dist/modules/features/cms/sanity/mergers/sitemap.d.ts.map +1 -1
  103. package/dist/modules/features/cms/sanity/mergers/sitemap.js +48 -62
  104. package/dist/modules/features/cms/sanity/mergers/sitemap.js.map +1 -1
  105. package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
  106. package/dist/modules/features/cms/sanity-pagebuilder/config.js +8 -5
  107. package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
  108. package/dist/modules/features/cms/sanity-pagebuilder/index.js +2 -2
  109. package/dist/modules/features/cms/sanity-pagebuilder/index.js.map +1 -1
  110. package/dist/modules/features/env/dotenvx/config.d.ts +13 -0
  111. package/dist/modules/features/env/dotenvx/config.d.ts.map +1 -0
  112. package/dist/modules/features/env/dotenvx/config.js +47 -0
  113. package/dist/modules/features/env/dotenvx/config.js.map +1 -0
  114. package/dist/modules/features/forms/hubspot/config.d.ts +31 -0
  115. package/dist/modules/features/forms/hubspot/config.d.ts.map +1 -0
  116. package/dist/modules/features/forms/hubspot/config.js +25 -0
  117. package/dist/modules/features/forms/hubspot/config.js.map +1 -0
  118. package/dist/paths.d.ts +16 -0
  119. package/dist/paths.d.ts.map +1 -1
  120. package/dist/paths.js +16 -0
  121. package/dist/paths.js.map +1 -1
  122. package/package.json +21 -9
  123. package/src/agent-skills/json-ld/SKILL.md +85 -0
  124. package/src/agent-skills/manage-env/SKILL.md +67 -0
  125. package/src/assets/check-node-version.mjs +22 -0
  126. package/src/modules/features/cms/sanity/files/app/blog/[slug]/page.tsx +48 -21
  127. package/src/modules/features/cms/sanity/files/app/blog/page.tsx +54 -0
  128. package/src/modules/features/cms/sanity/files/app/feed.xml/route.ts +36 -0
  129. package/src/modules/features/cms/sanity/files/components/sanity/structured-data.tsx +83 -0
  130. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/components/disable-draft-mode.tsx +3 -3
  131. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/queries.ts +14 -0
  132. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/sanity.config.ts +19 -3
  133. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/sanity.types.ts +1 -0
  134. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/article.ts +7 -7
  135. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/index.ts +36 -1
  136. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/metadata.ts +12 -1
  137. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/structured-data-blocks.ts +416 -0
  138. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/structured-data.ts +100 -0
  139. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/structure.ts +37 -2
  140. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/utils/page-json-ld.ts +208 -0
  141. package/src/modules/features/cms/sanity/files/lib/scripts/setup-ci-secrets.ts +117 -0
  142. package/src/modules/features/cms/sanity/files/lib/utils/rss.ts +96 -0
  143. package/src/modules/features/cms/sanity-pagebuilder/files/.knip.json +8 -0
  144. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/[[...slug]]/route.ts +100 -0
  145. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/draft-mode/disable/route.ts +7 -0
  146. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/draft-mode/enable/route.ts +20 -0
  147. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +126 -0
  148. package/src/modules/features/cms/sanity-pagebuilder/files/app/feed.xml/route.ts +40 -0
  149. package/src/modules/features/cms/sanity-pagebuilder/files/app/sitemap.md/route.ts +124 -0
  150. package/src/modules/features/cms/sanity-pagebuilder/files/app/studio/[[...tool]]/page.tsx +8 -0
  151. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/draft-mode-toggle.tsx +27 -0
  152. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +87 -0
  153. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/visual-editing.tsx +28 -0
  154. package/src/modules/features/cms/sanity-pagebuilder/files/components/ui/sanity-image/index.tsx +41 -0
  155. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/check-integration.ts +5 -0
  156. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/client.ts +27 -0
  157. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  158. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-input.tsx +39 -0
  159. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  160. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/same-as-input.tsx +66 -0
  161. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-field.tsx +18 -0
  162. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-input.tsx +14 -0
  163. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  164. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/env.ts +34 -0
  165. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +67 -0
  166. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/redirects.ts +17 -0
  167. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +79 -0
  168. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/live/index.tsx +88 -0
  169. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  170. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +130 -0
  171. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-category.ts +28 -0
  172. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +420 -0
  173. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/pinned-pages.ts +54 -0
  174. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/presentation.ts +119 -0
  175. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +407 -0
  176. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.cli.ts +29 -0
  177. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.config.ts +113 -0
  178. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +4 -0
  179. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  180. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  181. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  182. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  183. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/content/author.ts +70 -0
  184. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  185. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +124 -0
  186. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/company-data.ts +70 -0
  187. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  188. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/navbar.ts +75 -0
  189. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/redirect.ts +120 -0
  190. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/structured-data.ts +124 -0
  191. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  192. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  193. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/metadata.ts +79 -0
  194. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  195. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-builder.ts +39 -0
  196. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  197. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +242 -0
  198. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  199. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/structured-data-blocks.ts +436 -0
  200. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +51 -0
  201. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +330 -0
  202. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/image.ts +8 -0
  203. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/link.ts +140 -0
  204. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +81 -0
  205. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-json-ld.ts +208 -0
  206. package/src/modules/features/cms/sanity-pagebuilder/files/lib/scripts/sanity-typegen.ts +45 -0
  207. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/check-redirect.ts +30 -0
  208. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/json-ld.tsx +521 -0
  209. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/metadata.ts +167 -0
  210. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/rss.ts +96 -0
  211. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/sitemap.ts +40 -0
  212. package/src/modules/features/cms/sanity-pagebuilder/files/proxy.ts +81 -0
  213. package/src/modules/features/env/dotenvx/files/decrypt-env.mjs +45 -0
  214. package/src/modules/features/env/dotenvx/files/gitleaks.yml +25 -0
  215. package/src/modules/features/env/dotenvx/files/instrumentation.ts +14 -0
  216. package/src/modules/features/env/dotenvx/files/push-keys.mjs +129 -0
  217. package/src/modules/features/env/dotenvx/files/save-key.mjs +108 -0
  218. package/src/modules/features/env/dotenvx/files/setup-env.mjs +67 -0
  219. package/src/modules/features/env/dotenvx/files/vercelignore +4 -0
  220. package/src/modules/features/env/dotenvx/files/write-env.mjs +47 -0
  221. package/src/templates/next-default/.env.example +14 -6
  222. package/src/templates/next-default/.github/workflows/ci.yml +83 -0
  223. package/src/templates/next-default/.vscode/extensions.json +3 -0
  224. package/src/templates/next-default/README.md +53 -0
  225. package/src/templates/next-default/knip.json +14 -0
  226. package/src/templates/next-default/lefthook.yml +5 -0
  227. package/src/templates/next-default/lib/utils/json-ld.tsx +327 -21
  228. package/src/templates/next-default/next.config.ts +6 -0
  229. package/src/templates/next-default/package.json +8 -4
  230. package/src/templates/next-experiments/.env.example +14 -6
  231. package/src/templates/next-experiments/.github/workflows/ci.yml +83 -0
  232. package/src/templates/next-experiments/.vscode/extensions.json +3 -0
  233. package/src/templates/next-experiments/README.md +53 -0
  234. package/src/templates/next-experiments/knip.json +14 -0
  235. package/src/templates/next-experiments/lefthook.yml +30 -0
  236. package/src/templates/next-experiments/lib/utils/json-ld.tsx +327 -21
  237. package/src/templates/next-experiments/next.config.ts +6 -0
  238. package/src/templates/next-experiments/package.json +10 -2
  239. package/src/templates/next-pagebuilder/.env.example +19 -1
  240. package/src/templates/next-pagebuilder/.github/workflows/ci.yml +90 -0
  241. package/src/templates/next-pagebuilder/.vscode/extensions.json +3 -0
  242. package/src/templates/next-pagebuilder/README.md +65 -0
  243. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +6 -1
  244. package/src/templates/next-pagebuilder/app/(content)/layout.tsx +3 -12
  245. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +11 -10
  246. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +5 -3
  247. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +38 -26
  248. package/src/templates/next-pagebuilder/components/layout/wrapper/index.tsx +3 -11
  249. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +1 -1
  250. package/src/templates/next-pagebuilder/components/page-document/index.tsx +38 -0
  251. package/src/templates/next-pagebuilder/knip.json +27 -0
  252. package/src/templates/next-pagebuilder/lefthook.yml +5 -0
  253. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +36 -2
  254. package/src/templates/next-pagebuilder/lib/scripts/setup-ci-secrets.ts +117 -0
  255. package/src/templates/next-pagebuilder/next.config.ts +6 -0
  256. package/src/templates/next-pagebuilder/package.json +9 -3
  257. package/src/templates/next-webgl/.env.example +14 -6
  258. package/src/templates/next-webgl/.github/workflows/ci.yml +83 -0
  259. package/src/templates/next-webgl/.vscode/extensions.json +3 -0
  260. package/src/templates/next-webgl/README.md +53 -0
  261. package/src/templates/next-webgl/knip.json +13 -0
  262. package/src/templates/next-webgl/lefthook.yml +5 -0
  263. package/src/templates/next-webgl/lib/utils/json-ld.tsx +327 -21
  264. package/src/templates/next-webgl/next.config.ts +6 -0
  265. package/src/templates/next-webgl/package.json +8 -4
  266. package/src/modules/features/cms/sanity/files/lib/utils/json-ld.tsx +0 -244
@@ -0,0 +1,124 @@
1
+ import { defineField, defineType } from "sanity";
2
+ import {
3
+ INCLUDED_COMPANY_PROFILES_QUERY,
4
+ SameAsInput,
5
+ } from "@/lib/integrations/sanity/components/same-as-input";
6
+ import { apiVersion } from "@/lib/integrations/sanity/env";
7
+ import { structuredDataIcon } from "@/lib/integrations/sanity/icons";
8
+
9
+ export const structuredData = defineType({
10
+ name: "structuredData",
11
+ title: "Structured Data",
12
+ type: "document",
13
+ icon: structuredDataIcon,
14
+ description:
15
+ "Site-wide identity emitted as JSON-LD (schema.org Organization + WebSite) on every page for search engines.",
16
+ fields: [
17
+ defineField({
18
+ name: "name",
19
+ title: "Organization Name",
20
+ type: "string",
21
+ description: "Public name of the organization (shown in rich results).",
22
+ validation: (Rule) => Rule.required(),
23
+ }),
24
+ defineField({
25
+ name: "legalName",
26
+ title: "Legal Name",
27
+ type: "string",
28
+ description:
29
+ "Registered legal entity name, if different from the public name.",
30
+ }),
31
+ defineField({
32
+ name: "logo",
33
+ title: "Logo",
34
+ type: "image",
35
+ description:
36
+ "Square or wide logo used in rich results. Min 112x112px, transparent PNG/SVG recommended.",
37
+ options: { hotspot: true },
38
+ }),
39
+ defineField({
40
+ name: "description",
41
+ title: "Description",
42
+ type: "text",
43
+ rows: 3,
44
+ description: "Short sentence describing the organization.",
45
+ }),
46
+ defineField({
47
+ name: "url",
48
+ title: "Canonical URL",
49
+ type: "url",
50
+ description:
51
+ "Optional override for the canonical site URL. Defaults to the deployed origin.",
52
+ }),
53
+ defineField({
54
+ name: "contactPoint",
55
+ title: "Contact Point",
56
+ type: "object",
57
+ options: { collapsible: true, collapsed: true },
58
+ fields: [
59
+ defineField({ name: "email", title: "Email", type: "string" }),
60
+ defineField({ name: "telephone", title: "Telephone", type: "string" }),
61
+ defineField({
62
+ name: "contactType",
63
+ title: "Contact Type",
64
+ type: "string",
65
+ description:
66
+ "e.g. 'customer support', 'sales', 'press'. See schema.org/ContactPoint.",
67
+ }),
68
+ ],
69
+ }),
70
+ defineField({
71
+ name: "address",
72
+ title: "Address",
73
+ type: "object",
74
+ options: { collapsible: true, collapsed: true },
75
+ fields: [
76
+ defineField({
77
+ name: "streetAddress",
78
+ title: "Street Address",
79
+ type: "string",
80
+ }),
81
+ defineField({ name: "locality", title: "City", type: "string" }),
82
+ defineField({
83
+ name: "region",
84
+ title: "Region / State",
85
+ type: "string",
86
+ }),
87
+ defineField({
88
+ name: "postalCode",
89
+ title: "Postal Code",
90
+ type: "string",
91
+ }),
92
+ defineField({ name: "country", title: "Country", type: "string" }),
93
+ ],
94
+ }),
95
+ defineField({
96
+ name: "sameAs",
97
+ title: "Same-As Profiles",
98
+ type: "array",
99
+ description:
100
+ "Additional official profiles representing this organization (LinkedIn, X, GitHub, etc.). Company Data social links with 'Include in Structured Data' enabled are merged in automatically.",
101
+ of: [
102
+ {
103
+ type: "url",
104
+ validation: (Rule) =>
105
+ Rule.custom(async (value, context) => {
106
+ if (!value) return true;
107
+ const client = context.getClient({ apiVersion });
108
+ const included = await client.fetch<
109
+ { url?: string | null }[] | null
110
+ >(INCLUDED_COMPANY_PROFILES_QUERY);
111
+ return (included ?? []).some((p) => p.url === value)
112
+ ? "Already included from Company Data — remove it here or toggle it off there."
113
+ : true;
114
+ }),
115
+ },
116
+ ],
117
+ validation: (Rule) => Rule.unique(),
118
+ components: { input: SameAsInput },
119
+ }),
120
+ ],
121
+ preview: {
122
+ prepare: () => ({ title: "Structured Data" }),
123
+ },
124
+ });
@@ -0,0 +1,125 @@
1
+ import { defineArrayMember, defineField, defineType } from "sanity";
2
+
3
+ /**
4
+ * Page Reference -- internal link to a Sanity page document.
5
+ */
6
+ export const pageReference = defineType({
7
+ name: "pageReference",
8
+ title: "Page",
9
+ type: "object",
10
+ fields: [
11
+ defineField({
12
+ name: "page",
13
+ title: "Page",
14
+ type: "reference",
15
+ to: [{ type: "page" }],
16
+ validation: (Rule) => Rule.required(),
17
+ }),
18
+ defineField({
19
+ name: "openInNewTab",
20
+ title: "Open in New Tab",
21
+ type: "boolean",
22
+ initialValue: false,
23
+ }),
24
+ ],
25
+ preview: {
26
+ select: {
27
+ text: "text",
28
+ pageTitle: "page.title",
29
+ },
30
+ prepare({ text, pageTitle }) {
31
+ return {
32
+ title: text || pageTitle || "Untitled",
33
+ subtitle: pageTitle ? `Page: ${pageTitle}` : "Page Reference",
34
+ };
35
+ },
36
+ },
37
+ });
38
+
39
+ /**
40
+ * External Link -- URL pointing outside the site (or to pages not yet in Sanity).
41
+ */
42
+ export const externalLink = defineType({
43
+ name: "externalLink",
44
+ title: "URL",
45
+ type: "object",
46
+ fields: [
47
+ defineField({
48
+ name: "href",
49
+ title: "URL",
50
+ type: "url",
51
+ validation: (Rule) =>
52
+ Rule.required().uri({
53
+ scheme: ["http", "https", "mailto", "tel"],
54
+ allowRelative: true,
55
+ }),
56
+ }),
57
+ defineField({
58
+ name: "openInNewTab",
59
+ title: "Open in New Tab",
60
+ type: "boolean",
61
+ initialValue: false,
62
+ }),
63
+ ],
64
+ preview: {
65
+ select: {
66
+ text: "text",
67
+ href: "href",
68
+ },
69
+ prepare({ text, href }) {
70
+ return {
71
+ title: text || href || "Untitled",
72
+ subtitle: href ? `URL: ${href}` : "External Link",
73
+ };
74
+ },
75
+ },
76
+ });
77
+
78
+ /**
79
+ * Link -- array-of-one wrapper that accepts either a page reference or external URL.
80
+ * Editors click "Add" and pick which type they need.
81
+ */
82
+ export const link = defineType({
83
+ name: "link",
84
+ title: "Link",
85
+ type: "array",
86
+ of: [
87
+ defineArrayMember({ type: "pageReference" }),
88
+ defineArrayMember({ type: "externalLink" }),
89
+ ],
90
+ validation: (Rule) => Rule.max(1),
91
+ });
92
+
93
+ /**
94
+ * Annotations for Portable Text -- both link types as separate mark annotations.
95
+ */
96
+ export const linkAnnotations = [
97
+ defineArrayMember({ type: "pageReference" }),
98
+ defineArrayMember({ type: "externalLink" }),
99
+ ];
100
+
101
+ // Helper field exports for easy reuse
102
+ export const linkField = defineField({
103
+ name: "link",
104
+ title: "Link",
105
+ type: "link",
106
+ });
107
+
108
+ type LinkFieldOptions = {
109
+ name?: string;
110
+ title?: string;
111
+ required?: boolean;
112
+ };
113
+
114
+ export function extendedLinkField({
115
+ name = "link",
116
+ title = "Link",
117
+ required = false,
118
+ }: LinkFieldOptions = {}) {
119
+ return defineField({
120
+ name,
121
+ title,
122
+ type: "link",
123
+ validation: required ? (Rule) => Rule.required().min(1) : undefined,
124
+ });
125
+ }
@@ -0,0 +1,9 @@
1
+ import { defineField } from "sanity";
2
+
3
+ export const logoField = defineField({
4
+ name: "logo",
5
+ title: "Logo",
6
+ type: "image",
7
+ options: { hotspot: true },
8
+ validation: (Rule) => Rule.required(),
9
+ });
@@ -0,0 +1,79 @@
1
+ import { defineArrayMember, defineField, defineType } from "sanity";
2
+ import { pageJsonLdMembers } from "./structured-data-blocks";
3
+
4
+ export const metadata = defineType({
5
+ name: "metadata",
6
+ title: "SEO & Metadata",
7
+ type: "object",
8
+ options: {
9
+ collapsible: true,
10
+ collapsed: true,
11
+ },
12
+ fields: [
13
+ defineField({
14
+ name: "metaTitle",
15
+ title: "Meta Title",
16
+ type: "string",
17
+ description: "Title used by search engines",
18
+ validation: (Rule) =>
19
+ Rule.max(60).warning(
20
+ "Title should be under 60 characters for optimal SEO",
21
+ ),
22
+ }),
23
+ defineField({
24
+ name: "metaDescription",
25
+ title: "Meta Description",
26
+ type: "text",
27
+ rows: 3,
28
+ description: "Description used by search engines",
29
+ validation: (Rule) =>
30
+ Rule.max(160).warning(
31
+ "Description should be under 160 characters for optimal SEO",
32
+ ),
33
+ }),
34
+ defineField({
35
+ name: "image",
36
+ title: "OG Image",
37
+ type: "image",
38
+ description: "Image for social sharing previews (1200x630px recommended)",
39
+ options: {
40
+ hotspot: true,
41
+ },
42
+ }),
43
+ defineField({
44
+ name: "index",
45
+ title: "Index",
46
+ type: "boolean",
47
+ description: "Allow search engines to index this page",
48
+ initialValue: true,
49
+ }),
50
+ defineField({
51
+ name: "jsonLd",
52
+ title: "Structured Data (JSON-LD)",
53
+ type: "array",
54
+ description:
55
+ "Page-level schema.org structured data emitted as JSON-LD. Pick a predefined type, or add a Custom JSON-LD block for anything not listed.",
56
+ of: pageJsonLdMembers.map((member) =>
57
+ defineArrayMember({ type: member.name }),
58
+ ),
59
+ }),
60
+ defineField({
61
+ name: "title",
62
+ title: "Legacy Meta Title",
63
+ type: "string",
64
+ hidden: true,
65
+ }),
66
+ defineField({
67
+ name: "description",
68
+ title: "Legacy Meta Description",
69
+ type: "text",
70
+ hidden: true,
71
+ }),
72
+ defineField({
73
+ name: "noIndex",
74
+ title: "Legacy No Index",
75
+ type: "boolean",
76
+ hidden: true,
77
+ }),
78
+ ],
79
+ });
@@ -0,0 +1,192 @@
1
+ import { defineArrayMember, defineField, defineType } from "sanity";
2
+
3
+ /**
4
+ * Nav Leaf Item
5
+ *
6
+ * Individual navigation link within a menu column.
7
+ */
8
+ export const navLeafItem = defineType({
9
+ name: "navLeafItem",
10
+ title: "Navigation Link",
11
+ type: "object",
12
+ fields: [
13
+ defineField({
14
+ name: "title",
15
+ title: "Title",
16
+ type: "string",
17
+ description: "Display text for the navigation link",
18
+ validation: (Rule) => Rule.required(),
19
+ }),
20
+ defineField({
21
+ name: "link",
22
+ title: "Link",
23
+ type: "link",
24
+ description:
25
+ "Optional -- leave empty for items with pages not yet created",
26
+ }),
27
+ ],
28
+ preview: {
29
+ select: {
30
+ title: "title",
31
+ internalTitle: "link.0.page.title",
32
+ externalHref: "link.0.href",
33
+ },
34
+ prepare({ title, internalTitle, externalHref }) {
35
+ return {
36
+ title: title || "Untitled Link",
37
+ subtitle: internalTitle || externalHref || "",
38
+ };
39
+ },
40
+ },
41
+ });
42
+
43
+ /**
44
+ * Nav Column
45
+ *
46
+ * A column within a mega-menu containing a group of leaf items.
47
+ * Title is optional to support unnamed column groups (e.g. Company's first column).
48
+ * Link is optional -- some column headers are clickable (Products), some are labels only (Solutions).
49
+ */
50
+ export const navColumn = defineType({
51
+ name: "navColumn",
52
+ title: "Menu Column",
53
+ type: "object",
54
+ fields: [
55
+ defineField({
56
+ name: "title",
57
+ title: "Column Title",
58
+ type: "string",
59
+ description:
60
+ "Column header text. Leave empty for unnamed groups (e.g. Company's first column).",
61
+ }),
62
+ defineField({
63
+ name: "link",
64
+ title: "Column Link",
65
+ type: "link",
66
+ description:
67
+ "Optional -- makes the column header clickable (e.g. Products column headers link to section pages)",
68
+ }),
69
+ defineField({
70
+ name: "items",
71
+ title: "Items",
72
+ type: "array",
73
+ of: [defineArrayMember({ type: "navLeafItem" })],
74
+ description: "Navigation links within this column",
75
+ }),
76
+ ],
77
+ preview: {
78
+ select: {
79
+ title: "title",
80
+ items: "items",
81
+ },
82
+ prepare({ title, items }) {
83
+ const itemCount = items?.length ?? 0;
84
+ return {
85
+ title: title || "Unnamed Column",
86
+ subtitle: `${itemCount} item${itemCount === 1 ? "" : "s"}`,
87
+ };
88
+ },
89
+ },
90
+ });
91
+
92
+ /**
93
+ * Nav Menu
94
+ *
95
+ * The content of a menu dropdown panel.
96
+ * Contains columns of navigation links.
97
+ */
98
+ export const navMegaMenu = defineType({
99
+ name: "navMegaMenu",
100
+ title: "Menu",
101
+ type: "object",
102
+ fields: [
103
+ defineField({
104
+ name: "columns",
105
+ title: "Columns",
106
+ type: "array",
107
+ of: [defineArrayMember({ type: "navColumn" })],
108
+ validation: (Rule) => Rule.required().min(1),
109
+ description: "Column groups within the menu dropdown",
110
+ }),
111
+ ],
112
+ preview: {
113
+ select: {
114
+ columns: "columns",
115
+ },
116
+ prepare({ columns }) {
117
+ const colCount = columns?.length ?? 0;
118
+ return {
119
+ title: "Menu",
120
+ subtitle: `${colCount} column${colCount === 1 ? "" : "s"}`,
121
+ };
122
+ },
123
+ },
124
+ });
125
+
126
+ /**
127
+ * Nav Item
128
+ *
129
+ * A top-level navigation item. Discriminated union:
130
+ * - "link" type: a simple direct navigation link (e.g. Customers, Resources, Pricing)
131
+ * - "mega-menu" type: opens a multi-column dropdown panel (e.g. Products, Solutions, Company)
132
+ */
133
+ export const navItem = defineType({
134
+ name: "navItem",
135
+ title: "Navigation Item",
136
+ type: "object",
137
+ fields: [
138
+ defineField({
139
+ name: "title",
140
+ title: "Title",
141
+ type: "string",
142
+ description: "Display text in the navigation bar",
143
+ validation: (Rule) => Rule.required(),
144
+ }),
145
+ defineField({
146
+ name: "itemType",
147
+ title: "Item Type",
148
+ type: "string",
149
+ options: {
150
+ list: [
151
+ { title: "Direct Link", value: "link" },
152
+ { title: "Menu", value: "mega-menu" },
153
+ ],
154
+ layout: "radio",
155
+ },
156
+ initialValue: "link",
157
+ validation: (Rule) => Rule.required(),
158
+ }),
159
+ defineField({
160
+ name: "link",
161
+ title: "Link",
162
+ type: "link",
163
+ description: "Destination for direct link items",
164
+ hidden: ({ parent }) => parent?.itemType !== "link",
165
+ }),
166
+ defineField({
167
+ name: "megaMenu",
168
+ title: "Menu",
169
+ type: "navMegaMenu",
170
+ description: "Dropdown menu content with columns",
171
+ hidden: ({ parent }) => parent?.itemType !== "mega-menu",
172
+ }),
173
+ ],
174
+ preview: {
175
+ select: {
176
+ title: "title",
177
+ itemType: "itemType",
178
+ columns: "megaMenu.columns",
179
+ },
180
+ prepare({ title, itemType, columns }) {
181
+ const colCount = columns?.length ?? 0;
182
+ const subtitle =
183
+ itemType === "mega-menu"
184
+ ? `Menu (${colCount} column${colCount === 1 ? "" : "s"})`
185
+ : "Direct Link";
186
+ return {
187
+ title: title || "Untitled Item",
188
+ subtitle,
189
+ };
190
+ },
191
+ },
192
+ });
@@ -0,0 +1,39 @@
1
+ import { defineArrayMember, defineType } from "sanity";
2
+ import { PageBuilderInput } from "@/lib/integrations/sanity/components/page-builder-input";
3
+ import {
4
+ pageBuilderInsertMenuGroups,
5
+ pageBuilderReferenceMembers,
6
+ } from "@/lib/integrations/sanity/page-builder-config";
7
+
8
+ export const pageBuilder = defineType({
9
+ name: "pageBuilder",
10
+ title: "Page Builder",
11
+ type: "array",
12
+ components: { input: PageBuilderInput },
13
+ options: {
14
+ insertMenu: {
15
+ filter: true,
16
+ groups: pageBuilderInsertMenuGroups,
17
+ },
18
+ },
19
+ of: pageBuilderReferenceMembers.map((member) =>
20
+ defineArrayMember({
21
+ name: member.name,
22
+ title: member.title,
23
+ type: "reference",
24
+ to: [{ type: member.documentType }],
25
+ ...(member.documentId
26
+ ? {
27
+ options: {
28
+ disableNew: true,
29
+ filter: "_id in [$documentId, $draftDocumentId]",
30
+ filterParams: {
31
+ documentId: member.documentId,
32
+ draftDocumentId: `drafts.${member.documentId}`,
33
+ },
34
+ },
35
+ }
36
+ : {}),
37
+ }),
38
+ ),
39
+ });
@@ -0,0 +1,124 @@
1
+ import { defineField, defineType } from "sanity";
2
+ import { apiVersion } from "@/lib/integrations/sanity/env";
3
+ import { pageFolderIcon } from "@/lib/integrations/sanity/icons";
4
+
5
+ type FolderValidationDocument = {
6
+ _id?: string;
7
+ };
8
+
9
+ export const pageFolder = defineType({
10
+ name: "pageFolder",
11
+ title: "Page Folder",
12
+ type: "document",
13
+ icon: pageFolderIcon,
14
+ fields: [
15
+ defineField({
16
+ name: "title",
17
+ title: "Title",
18
+ type: "string",
19
+ validation: (Rule) => Rule.required(),
20
+ }),
21
+ defineField({
22
+ name: "parentFolder",
23
+ title: "Parent Folder",
24
+ type: "reference",
25
+ to: [{ type: "pageFolder" }],
26
+ description: "Optional parent folder for nesting inside the Pages tree.",
27
+ hidden: true,
28
+ options: {
29
+ disableNew: true,
30
+ filter: ({ document }) => {
31
+ const currentId = (document as FolderValidationDocument | undefined)
32
+ ?._id;
33
+ const normalizedId = currentId?.replace(/^drafts\./, "");
34
+
35
+ return normalizedId
36
+ ? {
37
+ filter: `_type == "pageFolder" && !(_id in [$id, "drafts." + $id])`,
38
+ params: { id: normalizedId },
39
+ }
40
+ : { filter: `_type == "pageFolder"` };
41
+ },
42
+ },
43
+ validation: (Rule) =>
44
+ Rule.custom((value, context) => {
45
+ const document = context.document as
46
+ | FolderValidationDocument
47
+ | undefined;
48
+ const currentId = document?._id?.replace(/^drafts\./, "");
49
+
50
+ if (value?._ref && currentId && value._ref === currentId) {
51
+ return "A folder cannot be its own parent";
52
+ }
53
+
54
+ return true;
55
+ }),
56
+ }),
57
+ defineField({
58
+ name: "slug",
59
+ title: "Slug",
60
+ type: "slug",
61
+ description:
62
+ "Required full folder path for organization, for example blog or blog/guides.",
63
+ options: {
64
+ source: "title",
65
+ maxLength: 200,
66
+ },
67
+ validation: (Rule) =>
68
+ Rule.required().custom(async (slug, context) => {
69
+ if (!slug?.current) {
70
+ return "Slug is required";
71
+ }
72
+
73
+ if (!/^[a-z0-9-/]+$/.test(slug.current)) {
74
+ return "Slug must be lowercase with hyphens, letters, numbers, and forward slashes only";
75
+ }
76
+
77
+ if (slug.current.startsWith("/") || slug.current.endsWith("/")) {
78
+ return "Slug must not start or end with a forward slash";
79
+ }
80
+
81
+ const document = context.document as
82
+ | FolderValidationDocument
83
+ | undefined;
84
+ const id = document?._id?.replace(/^drafts\./, "");
85
+
86
+ if (!id) return true;
87
+
88
+ const client = context.getClient({ apiVersion });
89
+ const existing = await client.fetch<number>(
90
+ `count(*[
91
+ _type == "pageFolder" &&
92
+ slug.current == $slug &&
93
+ !(_id in [$id, "drafts." + $id])
94
+ ])`,
95
+ {
96
+ slug: slug.current,
97
+ id,
98
+ },
99
+ );
100
+
101
+ return existing === 0 || "Another page folder already uses this slug";
102
+ }),
103
+ }),
104
+ ],
105
+ preview: {
106
+ select: {
107
+ title: "title",
108
+ slug: "slug.current",
109
+ },
110
+ prepare({ title, slug }) {
111
+ return {
112
+ title: title || "Untitled Folder",
113
+ subtitle: slug ? `/${slug}` : "Folder",
114
+ };
115
+ },
116
+ },
117
+ orderings: [
118
+ {
119
+ title: "Title A-Z",
120
+ name: "titleAsc",
121
+ by: [{ field: "title", direction: "asc" }],
122
+ },
123
+ ],
124
+ });