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
@@ -1,9 +1,15 @@
1
1
  import type {
2
2
  Article,
3
3
  BreadcrumbList,
4
+ Event as EventSchema,
5
+ FAQPage,
6
+ ItemList,
7
+ JobPosting,
4
8
  Organization,
5
9
  SearchAction,
10
+ SoftwareApplication,
6
11
  Thing,
12
+ VideoObject,
7
13
  WebPage,
8
14
  WebSite,
9
15
  WithContext,
@@ -41,10 +47,10 @@ export function JsonLd<T extends Thing>({ data }: { data: WithContext<T> }) {
41
47
 
42
48
  interface WebSiteJsonLdOptions {
43
49
  name: string
44
- url?: string
45
- description?: string
50
+ url?: string | undefined
51
+ description?: string | undefined
46
52
  /** URL to site-wide search (e.g. "/search?q={search_term_string}") */
47
- searchUrl?: string
53
+ searchUrl?: string | undefined
48
54
  }
49
55
 
50
56
  export function generateWebSiteJsonLd(
@@ -70,21 +76,69 @@ export function generateWebSiteJsonLd(
70
76
  }
71
77
  }
72
78
 
79
+ interface OrganizationContactPoint {
80
+ email?: string | null
81
+ telephone?: string | null
82
+ contactType?: string | null
83
+ }
84
+
85
+ interface OrganizationAddress {
86
+ streetAddress?: string | null
87
+ locality?: string | null
88
+ region?: string | null
89
+ postalCode?: string | null
90
+ country?: string | null
91
+ }
92
+
73
93
  interface OrganizationJsonLdOptions {
74
94
  name: string
75
- url?: string
76
- logo?: string
77
- description?: string
78
- sameAs?: string[]
95
+ url?: string | undefined
96
+ logo?: string | undefined
97
+ description?: string | undefined
98
+ sameAs?: string[] | undefined
99
+ legalName?: string | undefined
100
+ contactPoint?: OrganizationContactPoint | null | undefined
101
+ address?: OrganizationAddress | null | undefined
79
102
  }
80
103
 
81
104
  export function generateOrganizationJsonLd(
82
105
  options: OrganizationJsonLdOptions
83
106
  ): WithContext<Organization> {
84
- const { name, url, logo, description, sameAs } = options
107
+ const { name, url, logo, description, sameAs, legalName, contactPoint, address } =
108
+ options
85
109
  const resolvedUrl = resolveUrl(url)
86
110
  const resolvedLogo = resolveUrl(logo)
87
111
 
112
+ const contactPointNode =
113
+ contactPoint &&
114
+ (contactPoint.email || contactPoint.telephone || contactPoint.contactType)
115
+ ? {
116
+ "@type": "ContactPoint" as const,
117
+ ...(contactPoint.email && { email: contactPoint.email }),
118
+ ...(contactPoint.telephone && { telephone: contactPoint.telephone }),
119
+ ...(contactPoint.contactType && {
120
+ contactType: contactPoint.contactType,
121
+ }),
122
+ }
123
+ : undefined
124
+
125
+ const addressNode =
126
+ address &&
127
+ (address.streetAddress ||
128
+ address.locality ||
129
+ address.region ||
130
+ address.postalCode ||
131
+ address.country)
132
+ ? {
133
+ "@type": "PostalAddress" as const,
134
+ ...(address.streetAddress && { streetAddress: address.streetAddress }),
135
+ ...(address.locality && { addressLocality: address.locality }),
136
+ ...(address.region && { addressRegion: address.region }),
137
+ ...(address.postalCode && { postalCode: address.postalCode }),
138
+ ...(address.country && { addressCountry: address.country }),
139
+ }
140
+ : undefined
141
+
88
142
  return {
89
143
  "@context": "https://schema.org",
90
144
  "@type": "Organization",
@@ -92,17 +146,20 @@ export function generateOrganizationJsonLd(
92
146
  ...(resolvedUrl && { url: resolvedUrl }),
93
147
  ...(resolvedLogo && { logo: resolvedLogo }),
94
148
  ...(description && { description }),
95
- ...(sameAs && { sameAs }),
149
+ ...(legalName && { legalName }),
150
+ ...(sameAs?.length && { sameAs }),
151
+ ...(contactPointNode && { contactPoint: contactPointNode }),
152
+ ...(addressNode && { address: addressNode }),
96
153
  }
97
154
  }
98
155
 
99
156
  interface WebPageJsonLdOptions {
100
157
  title: string
101
- url?: string
102
- description?: string
103
- image?: string
104
- datePublished?: string
105
- dateModified?: string
158
+ url?: string | undefined
159
+ description?: string | undefined
160
+ image?: string | undefined
161
+ datePublished?: string | undefined
162
+ dateModified?: string | undefined
106
163
  }
107
164
 
108
165
  export function generateWebPageJsonLd(
@@ -127,13 +184,13 @@ export function generateWebPageJsonLd(
127
184
 
128
185
  interface ArticleJsonLdOptions {
129
186
  title: string
130
- url?: string
131
- description?: string
132
- image?: string
133
- datePublished?: string
134
- dateModified?: string
135
- authorName?: string
136
- authorUrl?: string
187
+ url?: string | undefined
188
+ description?: string | undefined
189
+ image?: string | undefined
190
+ datePublished?: string | undefined
191
+ dateModified?: string | undefined
192
+ authorName?: string | undefined
193
+ authorUrl?: string | undefined
137
194
  }
138
195
 
139
196
  export function generateArticleJsonLd(
@@ -194,3 +251,252 @@ export function generateBreadcrumbJsonLd(
194
251
  }),
195
252
  }
196
253
  }
254
+
255
+ // Page-level generators for the schema.org blocks editors attach via
256
+ // `metadata.jsonLd`. Plain options keep them CMS-independent.
257
+
258
+ export interface FaqJsonLdItem {
259
+ question: string
260
+ answer: string
261
+ }
262
+
263
+ export function generateFaqJsonLd(
264
+ items: FaqJsonLdItem[]
265
+ ): WithContext<FAQPage> {
266
+ return {
267
+ "@context": "https://schema.org",
268
+ "@type": "FAQPage",
269
+ mainEntity: items.map((item) => ({
270
+ "@type": "Question" as const,
271
+ name: item.question,
272
+ acceptedAnswer: {
273
+ "@type": "Answer" as const,
274
+ text: item.answer,
275
+ },
276
+ })),
277
+ }
278
+ }
279
+
280
+ export interface JobPostingJsonLdOptions {
281
+ title: string
282
+ description: string
283
+ datePosted: string
284
+ validThrough?: string | undefined
285
+ employmentType?: string | undefined
286
+ organizationName?: string | undefined
287
+ organizationUrl?: string | undefined
288
+ remote?: boolean | undefined
289
+ locality?: string | undefined
290
+ region?: string | undefined
291
+ country?: string | undefined
292
+ }
293
+
294
+ export function generateJobPostingJsonLd(
295
+ options: JobPostingJsonLdOptions
296
+ ): WithContext<JobPosting> {
297
+ const {
298
+ title,
299
+ description,
300
+ datePosted,
301
+ validThrough,
302
+ employmentType,
303
+ organizationName,
304
+ organizationUrl,
305
+ remote,
306
+ locality,
307
+ region,
308
+ country,
309
+ } = options
310
+ const orgUrl = organizationUrl ? resolveUrl(organizationUrl) : undefined
311
+
312
+ const hiringOrganization = organizationName
313
+ ? {
314
+ "@type": "Organization" as const,
315
+ name: organizationName,
316
+ ...(orgUrl && { url: orgUrl }),
317
+ }
318
+ : undefined
319
+
320
+ const jobLocation =
321
+ locality || region || country
322
+ ? {
323
+ "@type": "Place" as const,
324
+ address: {
325
+ "@type": "PostalAddress" as const,
326
+ ...(locality && { addressLocality: locality }),
327
+ ...(region && { addressRegion: region }),
328
+ ...(country && { addressCountry: country }),
329
+ },
330
+ }
331
+ : undefined
332
+
333
+ return {
334
+ "@context": "https://schema.org",
335
+ "@type": "JobPosting",
336
+ title,
337
+ description,
338
+ datePosted,
339
+ ...(validThrough && { validThrough }),
340
+ ...(employmentType && { employmentType }),
341
+ ...(hiringOrganization && { hiringOrganization }),
342
+ ...(remote && { jobLocationType: "TELECOMMUTE" }),
343
+ ...(jobLocation && { jobLocation }),
344
+ }
345
+ }
346
+
347
+ export interface SoftwareApplicationJsonLdOptions {
348
+ name: string
349
+ description?: string | undefined
350
+ applicationCategory?: string | undefined
351
+ operatingSystem?: string | undefined
352
+ price?: number | undefined
353
+ currency?: string | undefined
354
+ url?: string | undefined
355
+ image?: string | undefined
356
+ }
357
+
358
+ export function generateSoftwareApplicationJsonLd(
359
+ options: SoftwareApplicationJsonLdOptions
360
+ ): WithContext<SoftwareApplication> {
361
+ const {
362
+ name,
363
+ description,
364
+ applicationCategory,
365
+ operatingSystem,
366
+ price,
367
+ currency,
368
+ url,
369
+ image,
370
+ } = options
371
+ const resolvedUrl = url ? resolveUrl(url) : undefined
372
+ const resolvedImage = image ? resolveUrl(image) : undefined
373
+
374
+ const offers =
375
+ typeof price === "number"
376
+ ? {
377
+ "@type": "Offer" as const,
378
+ price: price.toString(),
379
+ ...(currency && { priceCurrency: currency }),
380
+ }
381
+ : undefined
382
+
383
+ return {
384
+ "@context": "https://schema.org",
385
+ "@type": "SoftwareApplication",
386
+ name,
387
+ ...(description && { description }),
388
+ ...(applicationCategory && { applicationCategory }),
389
+ ...(operatingSystem && { operatingSystem }),
390
+ ...(resolvedUrl && { url: resolvedUrl }),
391
+ ...(resolvedImage && { image: resolvedImage }),
392
+ ...(offers && { offers }),
393
+ }
394
+ }
395
+
396
+ export interface ItemListEntry {
397
+ name: string
398
+ url?: string | undefined
399
+ }
400
+
401
+ export interface ItemListJsonLdOptions {
402
+ name?: string | undefined
403
+ items: ItemListEntry[]
404
+ }
405
+
406
+ export function generateItemListJsonLd(
407
+ options: ItemListJsonLdOptions
408
+ ): WithContext<ItemList> {
409
+ const { name, items } = options
410
+
411
+ return {
412
+ "@context": "https://schema.org",
413
+ "@type": "ItemList",
414
+ ...(name && { name }),
415
+ itemListElement: items.map((item, index) => {
416
+ const itemUrl = item.url ? resolveUrl(item.url) : undefined
417
+ return {
418
+ "@type": "ListItem" as const,
419
+ position: index + 1,
420
+ name: item.name,
421
+ ...(itemUrl && { url: itemUrl }),
422
+ }
423
+ }),
424
+ }
425
+ }
426
+
427
+ export interface EventJsonLdOptions {
428
+ name: string
429
+ description?: string | undefined
430
+ startDate: string
431
+ endDate?: string | undefined
432
+ locationName?: string | undefined
433
+ locationAddress?: string | undefined
434
+ url?: string | undefined
435
+ image?: string | undefined
436
+ }
437
+
438
+ export function generateEventJsonLd(
439
+ options: EventJsonLdOptions
440
+ ): WithContext<EventSchema> {
441
+ const {
442
+ name,
443
+ description,
444
+ startDate,
445
+ endDate,
446
+ locationName,
447
+ locationAddress,
448
+ url,
449
+ image,
450
+ } = options
451
+ const resolvedUrl = resolveUrl(url)
452
+ const resolvedImage = resolveUrl(image)
453
+
454
+ const location =
455
+ locationName || locationAddress
456
+ ? {
457
+ "@type": "Place" as const,
458
+ ...(locationName && { name: locationName }),
459
+ ...(locationAddress && { address: locationAddress }),
460
+ }
461
+ : undefined
462
+
463
+ return {
464
+ "@context": "https://schema.org",
465
+ "@type": "Event",
466
+ name,
467
+ startDate,
468
+ ...(endDate && { endDate }),
469
+ ...(description && { description }),
470
+ ...(resolvedUrl && { url: resolvedUrl }),
471
+ ...(resolvedImage && { image: resolvedImage }),
472
+ ...(location && { location }),
473
+ }
474
+ }
475
+
476
+ export interface VideoJsonLdOptions {
477
+ name: string
478
+ description: string
479
+ thumbnail: string
480
+ uploadDate: string
481
+ contentUrl?: string | undefined
482
+ embedUrl?: string | undefined
483
+ }
484
+
485
+ export function generateVideoJsonLd(
486
+ options: VideoJsonLdOptions
487
+ ): WithContext<VideoObject> {
488
+ const { name, description, thumbnail, uploadDate, contentUrl, embedUrl } =
489
+ options
490
+ const resolvedThumbnail = resolveUrl(thumbnail) ?? thumbnail
491
+
492
+ return {
493
+ "@context": "https://schema.org",
494
+ "@type": "VideoObject",
495
+ name,
496
+ description,
497
+ thumbnailUrl: resolvedThumbnail,
498
+ uploadDate,
499
+ ...(contentUrl && { contentUrl }),
500
+ ...(embedUrl && { embedUrl }),
501
+ }
502
+ }
@@ -5,6 +5,12 @@ const nextConfig: NextConfig = {
5
5
  reactStrictMode: true,
6
6
  reactCompiler: true,
7
7
  typedRoutes: true,
8
+ // Bundle the committed encrypted env files into serverless functions so
9
+ // instrumentation.ts can decrypt them at runtime. .env.keys is never listed
10
+ // (and is git/vercel-ignored); missing files are skipped.
11
+ outputFileTracingIncludes: {
12
+ "/**": ["./.env", "./.env.production", "./.env.preview"],
13
+ },
8
14
  turbopack: {
9
15
  rules: {
10
16
  "*.svg": {
@@ -3,7 +3,10 @@
3
3
  "description": "Basement Next.js starter template",
4
4
  "version": "0.1.0",
5
5
  "private": true,
6
- "packageManager": "bun@1.3.5",
6
+ "packageManager": "bun@1.3.14",
7
+ "engines": {
8
+ "node": ">=24"
9
+ },
7
10
  "scripts": {
8
11
  "analyze": "cross-env ANALYZE=true bun run build",
9
12
  "analyze:experimental": "next experimental-analyze",
@@ -12,8 +15,8 @@
12
15
  "dev:https": "bun ./lib/scripts/dev.ts --https",
13
16
  "dev:inspect": "bun ./lib/scripts/dev.ts --inspect",
14
17
  "format": "biome format --write .",
15
- "knip": "bunx knip",
16
- "knip:fix": "bunx knip --fix",
18
+ "knip": "knip",
19
+ "knip:fix": "knip --fix",
17
20
  "lighthouse": "bunx @unlighthouse/cli --site http://localhost:3000",
18
21
  "lint": "biome lint --max-diagnostics=200",
19
22
  "lint:fix": "biome check --write --unsafe --max-diagnostics=200",
@@ -42,13 +45,14 @@
42
45
  "@svgr/webpack": "^8.1.0",
43
46
  "@tailwindcss/postcss": "^4",
44
47
  "@types/bun": "^1.3.6",
45
- "@types/node": "^20.19.30",
48
+ "@types/node": "^24.13.1",
46
49
  "@types/react": "^19.2.9",
47
50
  "@types/react-dom": "^19.2.3",
48
51
  "@types/three": "^0.182.0",
49
52
  "@typescript/native-preview": "^7.0.0-dev.20260122.3",
50
53
  "babel-plugin-react-compiler": "^1.0.0",
51
54
  "cross-env": "^10.1.0",
55
+ "knip": "^6.16.1",
52
56
  "lefthook": "^1.13.0",
53
57
  "postcss-preset-env": "^10.6.1",
54
58
  "schema-dts": "^2.0.0",
@@ -1,244 +0,0 @@
1
- import type {
2
- Article,
3
- BreadcrumbList,
4
- Organization,
5
- SearchAction,
6
- Thing,
7
- WebPage,
8
- WebSite,
9
- WithContext,
10
- } from "schema-dts";
11
-
12
- const APP_BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
13
-
14
- function isAbsoluteUrl(value: string) {
15
- return /^https?:\/\//.test(value);
16
- }
17
-
18
- function resolveUrl(value?: string) {
19
- if (!value) return APP_BASE_URL;
20
- if (isAbsoluteUrl(value)) return value;
21
- if (!APP_BASE_URL) return undefined;
22
-
23
- return new URL(value, APP_BASE_URL).toString();
24
- }
25
-
26
- /* -------------------------------- Component ------------------------------- */
27
-
28
- export function JsonLd<T extends Thing>({ data }: { data: WithContext<T> }) {
29
- return (
30
- <script
31
- type="application/ld+json"
32
- dangerouslySetInnerHTML={{
33
- __html: JSON.stringify(data).replace(/</g, "\\u003c"),
34
- }}
35
- />
36
- );
37
- }
38
-
39
- /* -------------------------------- Generators ------------------------------ */
40
-
41
- interface WebSiteJsonLdOptions {
42
- name: string;
43
- url?: string;
44
- description?: string;
45
- /** URL to site-wide search (e.g. "/search?q={search_term_string}") */
46
- searchUrl?: string;
47
- }
48
-
49
- export function generateWebSiteJsonLd(
50
- options: WebSiteJsonLdOptions,
51
- ): WithContext<WebSite> {
52
- const { name, url, description, searchUrl } = options;
53
- const resolvedUrl = resolveUrl(url);
54
- const resolvedSearchUrl = resolveUrl(searchUrl);
55
-
56
- return {
57
- "@context": "https://schema.org",
58
- "@type": "WebSite",
59
- name,
60
- ...(resolvedUrl && { url: resolvedUrl }),
61
- ...(description && { description }),
62
- ...(resolvedSearchUrl && {
63
- potentialAction: {
64
- "@type": "SearchAction",
65
- target: resolvedSearchUrl,
66
- "query-input": "required name=search_term_string",
67
- } as SearchAction & { "query-input": string },
68
- }),
69
- };
70
- }
71
-
72
- interface OrganizationJsonLdOptions {
73
- name: string;
74
- url?: string;
75
- logo?: string;
76
- description?: string;
77
- sameAs?: string[];
78
- }
79
-
80
- export function generateOrganizationJsonLd(
81
- options: OrganizationJsonLdOptions,
82
- ): WithContext<Organization> {
83
- const { name, url, logo, description, sameAs } = options;
84
- const resolvedUrl = resolveUrl(url);
85
- const resolvedLogo = resolveUrl(logo);
86
-
87
- return {
88
- "@context": "https://schema.org",
89
- "@type": "Organization",
90
- name,
91
- ...(resolvedUrl && { url: resolvedUrl }),
92
- ...(resolvedLogo && { logo: resolvedLogo }),
93
- ...(description && { description }),
94
- ...(sameAs && { sameAs }),
95
- };
96
- }
97
-
98
- interface WebPageJsonLdOptions {
99
- title: string;
100
- url?: string;
101
- description?: string;
102
- image?: string;
103
- datePublished?: string;
104
- dateModified?: string;
105
- }
106
-
107
- export function generateWebPageJsonLd(
108
- options: WebPageJsonLdOptions,
109
- ): WithContext<WebPage> {
110
- const { title, url, description, image, datePublished, dateModified } =
111
- options;
112
- const resolvedUrl = resolveUrl(url);
113
- const resolvedImage = resolveUrl(image);
114
-
115
- return {
116
- "@context": "https://schema.org",
117
- "@type": "WebPage",
118
- name: title,
119
- ...(resolvedUrl && { url: resolvedUrl }),
120
- ...(description && { description }),
121
- ...(resolvedImage && { image: resolvedImage }),
122
- ...(datePublished && { datePublished }),
123
- ...(dateModified && { dateModified }),
124
- };
125
- }
126
-
127
- interface ArticleJsonLdOptions {
128
- title: string;
129
- url?: string;
130
- description?: string;
131
- image?: string;
132
- datePublished?: string;
133
- dateModified?: string;
134
- authorName?: string;
135
- authorUrl?: string;
136
- }
137
-
138
- export function generateArticleJsonLd(
139
- options: ArticleJsonLdOptions,
140
- ): WithContext<Article> {
141
- const {
142
- title,
143
- url,
144
- description,
145
- image,
146
- datePublished,
147
- dateModified,
148
- authorName,
149
- authorUrl,
150
- } = options;
151
- const resolvedUrl = resolveUrl(url);
152
- const resolvedImage = resolveUrl(image);
153
-
154
- return {
155
- "@context": "https://schema.org",
156
- "@type": "Article",
157
- headline: title,
158
- ...(resolvedUrl && { url: resolvedUrl }),
159
- ...(description && { description }),
160
- ...(resolvedImage && { image: resolvedImage }),
161
- ...(datePublished && { datePublished }),
162
- ...(dateModified && { dateModified }),
163
- ...(authorName && {
164
- author: {
165
- "@type": "Person",
166
- name: authorName,
167
- ...(authorUrl && { url: authorUrl }),
168
- },
169
- }),
170
- };
171
- }
172
-
173
- interface BreadcrumbItem {
174
- name: string;
175
- url: string;
176
- }
177
-
178
- export function generateBreadcrumbJsonLd(
179
- items: BreadcrumbItem[],
180
- ): WithContext<BreadcrumbList> {
181
- return {
182
- "@context": "https://schema.org",
183
- "@type": "BreadcrumbList",
184
- itemListElement: items.map((item, index) => {
185
- const resolvedItemUrl = resolveUrl(item.url);
186
-
187
- return {
188
- "@type": "ListItem",
189
- position: index + 1,
190
- name: item.name,
191
- ...(resolvedItemUrl && { item: resolvedItemUrl }),
192
- };
193
- }),
194
- };
195
- }
196
-
197
- /* ----------------------------- Sanity Helpers ----------------------------- */
198
-
199
- interface SanityDocument {
200
- title?: string;
201
- metadata?: {
202
- title?: string;
203
- description?: string;
204
- image?: { asset?: { url?: string } };
205
- };
206
- _updatedAt?: string;
207
- publishedAt?: string;
208
- }
209
-
210
- export function generateSanityArticleJsonLd(options: {
211
- document: SanityDocument;
212
- url?: string;
213
- authorName?: string;
214
- authorUrl?: string;
215
- }): WithContext<Article> {
216
- const { document, url, authorName, authorUrl } = options;
217
-
218
- return generateArticleJsonLd({
219
- title: document.metadata?.title || document.title || "",
220
- url,
221
- description: document.metadata?.description,
222
- image: document.metadata?.image?.asset?.url,
223
- datePublished: document.publishedAt,
224
- dateModified: document._updatedAt,
225
- authorName,
226
- authorUrl,
227
- });
228
- }
229
-
230
- export function generateSanityWebPageJsonLd(options: {
231
- document: SanityDocument;
232
- url?: string;
233
- }): WithContext<WebPage> {
234
- const { document, url } = options;
235
-
236
- return generateWebPageJsonLd({
237
- title: document.metadata?.title || document.title || "",
238
- url,
239
- description: document.metadata?.description,
240
- image: document.metadata?.image?.asset?.url,
241
- datePublished: document.publishedAt,
242
- dateModified: document._updatedAt,
243
- });
244
- }