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
@@ -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,9 +15,12 @@
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 .",
18
+ "knip": "knip",
19
+ "knip:fix": "knip --fix",
15
20
  "lighthouse": "bunx @unlighthouse/cli --site http://localhost:3000",
16
21
  "lint": "biome lint --max-diagnostics=200",
17
22
  "lint:fix": "biome check --write --unsafe --max-diagnostics=200",
23
+ "prepare": "lefthook install",
18
24
  "start": "next start",
19
25
  "typecheck": "tsgo --noEmit",
20
26
  "typecheck:compare": "bun run typecheck:tsc && bun run typecheck",
@@ -38,12 +44,14 @@
38
44
  "@svgr/webpack": "^8.1.0",
39
45
  "@tailwindcss/postcss": "^4",
40
46
  "@types/bun": "^1.3.6",
41
- "@types/node": "^20.19.30",
47
+ "@types/node": "^24.13.1",
42
48
  "@types/react": "^19.2.9",
43
49
  "@types/react-dom": "^19.2.3",
44
50
  "@typescript/native-preview": "^7.0.0-dev.20260122.3",
45
51
  "babel-plugin-react-compiler": "^1.0.0",
46
52
  "cross-env": "^10.1.0",
53
+ "knip": "^6.16.1",
54
+ "lefthook": "^1.13.0",
47
55
  "postcss-preset-env": "^10.6.1",
48
56
  "schema-dts": "^2.0.0",
49
57
  "tailwindcss": "^4",
@@ -1,5 +1,23 @@
1
+ # ============================================
2
+ # Basement Next Starter - Environment Variables
3
+ # ============================================
4
+ # This project uses dotenvx (https://dotenvx.com): the committed `.env` holds
5
+ # shared values, with secrets encrypted there. The private keys live in
6
+ # `.env.keys` (gitignored) — restore them with `bun run env:setup`.
7
+ #
8
+ # Add or change a variable in `.env` (not .env.local):
9
+ # - Secret (API key, token, …): bun run env:set KEY value (--preview / --prod)
10
+ # - Trivial / NEXT_PUBLIC_*: bun run env:set KEY value --plain
11
+ # - Bulk-encrypt a file edited by hand: bun run env:encrypt-all (--preview / --prod)
12
+ #
13
+ # Edge runtime (middleware, `runtime = "edge"`): dotenvx can't decrypt there.
14
+ # Set any secret those read directly in Vercel's env vars, not here.
15
+ #
16
+ # This file just documents the available variables; real values live in `.env`.
17
+ # ============================================
18
+
1
19
  # Base URL
2
- NEXT_PUBLIC_BASE_URL=http://localhost:3000
20
+ NEXT_PUBLIC_BASE_URL=
3
21
 
4
22
  # Draft Mode
5
23
  DRAFT_MODE_TOKEN=
@@ -0,0 +1,90 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+ push:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ ci:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+
19
+ # Node version is read from .nvmrc — the single source of truth.
20
+ - name: Setup Node
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version-file: ".nvmrc"
24
+
25
+ # Bun version is read from package.json's "packageManager" field — the
26
+ # single source of truth. Do NOT pin a version here, or the two can drift.
27
+ - name: Setup Bun
28
+ uses: oven-sh/setup-bun@v2
29
+
30
+ # Cache Bun's global install cache so dependencies aren't re-downloaded
31
+ # on every run. Keyed on the lockfile so it busts when deps change.
32
+ - name: Cache Bun dependencies
33
+ uses: actions/cache@v4
34
+ with:
35
+ path: ~/.bun/install/cache
36
+ key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
37
+ restore-keys: |
38
+ ${{ runner.os }}-bun-
39
+
40
+ - name: Install dependencies
41
+ run: bun install --frozen-lockfile
42
+
43
+ - name: Type check
44
+ run: bun run typecheck:compare
45
+
46
+ - name: Lint
47
+ run: bun run lint
48
+
49
+ # dotenvx needs the private key to decrypt secrets at build time. It's
50
+ # pulled from 1Password via an org-wide service-account token + the op-ref
51
+ # committed in .env. Optional: builds pass without it (only plaintext /
52
+ # NEXT_PUBLIC_* is read), and a per-repo DOTENV_PRIVATE_KEY secret still
53
+ # works as a fallback.
54
+ - name: Install 1Password CLI
55
+ if: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN != '' }}
56
+ uses: 1password/install-cli-action@v1
57
+
58
+ - name: Build
59
+ env:
60
+ OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
61
+ DOTENV_PRIVATE_KEY: ${{ secrets.DOTENV_PRIVATE_KEY }}
62
+ # Sanity project ID and dataset are public (they ship in the client
63
+ # bundle), so they are stored as repository variables. The Sanity read
64
+ # token is secret — add it under Settings → Secrets and variables →
65
+ # Actions. All three are empty (and harmless) until Sanity is set up.
66
+ NEXT_PUBLIC_SANITY_PROJECT_ID: ${{ vars.NEXT_PUBLIC_SANITY_PROJECT_ID }}
67
+ NEXT_PUBLIC_SANITY_DATASET: ${{ vars.NEXT_PUBLIC_SANITY_DATASET }}
68
+ SANITY_API_READ_TOKEN: ${{ secrets.SANITY_API_READ_TOKEN }}
69
+ run: |
70
+ if [ -n "$OP_SERVICE_ACCOUNT_TOKEN" ]; then
71
+ ref="$(grep -m1 '^DOTENV_PRIVATE_KEY_OP_REF=' .env | cut -d= -f2-)"
72
+ if [ -n "$ref" ]; then
73
+ DOTENV_PRIVATE_KEY="$(op read "$ref")"
74
+ echo "::add-mask::$DOTENV_PRIVATE_KEY"
75
+ export DOTENV_PRIVATE_KEY
76
+ fi
77
+ fi
78
+ bun run build
79
+
80
+ # Runs your tests if any exist; a fresh project with none passes cleanly.
81
+ - name: Test
82
+ run: |
83
+ if git ls-files '*.test.*' '*.spec.*' '*_test.*' '*_spec.*' | grep -q .; then
84
+ bun test
85
+ else
86
+ echo "No test files found — skipping bun test."
87
+ fi
88
+
89
+ - name: Knip
90
+ run: bun run knip
@@ -10,6 +10,9 @@
10
10
  // Sanity CMS (GROQ syntax + validation)
11
11
  "sanity-io.vscode-sanity",
12
12
 
13
+ // Env (dotenvx — view decrypted .env values inline)
14
+ "dotenv.dotenvx-vscode",
15
+
13
16
  // DX Enhancements
14
17
  "yoavbls.pretty-ts-errors"
15
18
  ]
@@ -21,3 +21,68 @@ bun dev
21
21
  - `bun build` - Production build
22
22
  - `bun lint` - Run linter
23
23
  - `bun sanity:typegen` - Generate Sanity types
24
+ - `bun env:set KEY value` - Encrypt one value into `.env` (`--plain`, `--preview`/`--prod`)
25
+ - `bun env:encrypt-all` - Bulk-encrypt every plaintext value in a file (`--preview`/`--prod`)
26
+ - `bun env:setup` - Restore `.env.keys` from 1Password
27
+ - `bun env:view` - Print the decrypted `.env` (`--preview` / `--prod`)
28
+ - `bun env:setup-remote` - Push private keys to GitHub / Vercel (`github`/`vercel`, or pick)
29
+ - `bun env:save` - Save the private key to 1Password (Development vault)
30
+
31
+ ## Environment variables
32
+
33
+ Secrets are encrypted at rest with [dotenvx](https://dotenvx.com): the committed `.env` holds encrypted values, the private keys live in `.env.keys` (gitignored), and dev/build run through `dotenvx run` so values decrypt automatically.
34
+
35
+ **First run.** `bun install` restores `.env.keys` from 1Password (via `DOTENV_PRIVATE_KEY_OP_REF` in `.env`), or run `bun run env:setup`. Needs 1Password access + the `op` CLI:
36
+
37
+ - macOS: `brew install --cask 1password-cli`
38
+ - Windows: `winget install 1password-cli`
39
+ - Linux / other: [1Password CLI docs](https://developer.1password.com/docs/cli/get-started/)
40
+
41
+ **Add or change a variable** (in `.env`):
42
+
43
+ - Secret: `bun run env:set KEY value` (`--preview`/`--prod` to target an environment)
44
+ - Public / `NEXT_PUBLIC_*`: `bun run env:set KEY value --plain`
45
+ - Bulk-encrypt a hand-edited file: `bun run env:encrypt-all`
46
+ - Inspect: `bun run env:view` (`--preview`/`--prod`)
47
+
48
+ **Per environment.** Scripts load `.env.$VERCEL_ENV` over `.env`. After adding a per-env file, push its key with `bun run env:setup-remote vercel` — `instrumentation.ts` uses it to decrypt at runtime.
49
+
50
+ **Edge runtime.** dotenvx decrypts only in the Node runtime; secrets read in `middleware.ts` or a `runtime = "edge"` route must be set as plain Vercel env vars.
51
+
52
+ A gitleaks pre-commit hook + CI scan block committed plaintext secrets (install: `brew install gitleaks`).
53
+
54
+ ## Continuous Integration
55
+
56
+ A GitHub Actions workflow (`.github/workflows/ci.yml`) runs on every pull request to `main` and on pushes to `main`. It runs type checking, linting, the production build, tests, and `knip`.
57
+
58
+ The workflow takes its runtime versions from your manifests, so there's a single source of truth and nothing to keep in sync by hand:
59
+
60
+ - **Node** comes from `.nvmrc`.
61
+ - **Bun** comes from the `packageManager` field in `package.json`.
62
+
63
+ It also caches Bun's install cache between runs, and the test step is a no-op until you add real test files.
64
+
65
+ The build decrypts the committed `.env` with the dotenvx private key, pulled from 1Password: set an **org-level** `OP_SERVICE_ACCOUNT_TOKEN` (a read-only [service account](https://developer.1password.com/docs/service-accounts/) scoped to the `Development` vault) — one secret for every repo — and CI reads the key via the op-ref committed in `.env`. A per-repo `DOTENV_PRIVATE_KEY` secret (`bun run env:setup-remote github`) works as a fallback; builds pass without either (only plaintext / `NEXT_PUBLIC_*` is read).
66
+
67
+ ### Sanity environment
68
+
69
+ The build reads Sanity config from GitHub Actions variables/secrets (empty and harmless until you configure Sanity). Once your repo is on GitHub, the quickest way to set them is:
70
+
71
+ ```bash
72
+ bun run ci:secrets
73
+ ```
74
+
75
+ This reads the values from `.env.local` and pushes them to this repo with the GitHub CLI — `NEXT_PUBLIC_SANITY_PROJECT_ID` / `NEXT_PUBLIC_SANITY_DATASET` as **Variables** (they are public) and `SANITY_API_READ_TOKEN` as a **Secret**. Requires the [GitHub CLI](https://cli.github.com), authenticated (`gh auth login`).
76
+
77
+ To set them by hand instead, go to **Settings → Secrets and variables → Actions** and add the two `NEXT_PUBLIC_*` values under **Variables** and the token under **Secrets**.
78
+
79
+ ### Branch protection
80
+
81
+ To block merges when CI fails, enable branch protection on `main`:
82
+
83
+ 1. Go to **Settings → Branches → Add branch ruleset** (or **Add rule**).
84
+ 2. Target the `main` branch.
85
+ 3. Enable **Require status checks to pass before merging** and select the **CI** check.
86
+ 4. (Recommended) Enable **Require a pull request before merging**.
87
+
88
+ Pull requests then cannot be merged until the CI workflow passes.
@@ -10,6 +10,7 @@ import type {
10
10
  ALL_PAGE_SLUGS_QUERY_RESULT,
11
11
  PAGE_QUERY_RESULT,
12
12
  } from "@/lib/integrations/sanity/sanity.types"
13
+ import { checkRedirect } from "@/lib/utils/check-redirect"
13
14
  import { generateSanityMetadata } from "@/lib/utils/metadata"
14
15
  import { getSlugTag } from "@/lib/utils/slug-tag"
15
16
 
@@ -71,7 +72,11 @@ export default async function CatchAllPage({
71
72
  const path = toPath(slug)
72
73
  const page = await getResolvedPage(path)
73
74
 
74
- if (!page) notFound()
75
+ if (!page) {
76
+ // Fall back to a CMS redirect before 404ing.
77
+ await checkRedirect(path)
78
+ notFound()
79
+ }
75
80
 
76
81
  return <PageDocument page={page} path={path} searchParams={searchParams} />
77
82
  }
@@ -1,21 +1,12 @@
1
1
  import { JsonLd } from "@/components/layout/json-ld"
2
2
  import { Wrapper } from "@/components/layout/wrapper"
3
3
  import { SanityVisualEditing } from "@/components/sanity/visual-editing"
4
- import { getSiteLayoutData } from "@/lib/integrations/sanity/fetchers/layout"
5
-
6
- const Layout = async ({ children }: { children: React.ReactNode }) => {
7
- const layoutData = await getSiteLayoutData()
8
4
 
5
+ const Layout = ({ children }: { children: React.ReactNode }) => {
9
6
  return (
10
7
  <>
11
- <JsonLd navbar={layoutData.navbar} companyData={layoutData.companyData} />
12
- <Wrapper
13
- navbar={layoutData.navbar}
14
- footer={layoutData.footer}
15
- companyData={layoutData.companyData}
16
- >
17
- {children}
18
- </Wrapper>
8
+ <JsonLd />
9
+ <Wrapper>{children}</Wrapper>
19
10
  <SanityVisualEditing />
20
11
  </>
21
12
  )
@@ -1,21 +1,22 @@
1
1
  import { Link } from "@/components/ui/link"
2
2
  import { SanityImage } from "@/components/ui/sanity-image"
3
- import type {
4
- CompanyData,
5
- FooterData,
3
+ import {
4
+ type CompanyData,
5
+ type FooterData,
6
+ getCompanyData,
7
+ getFooterData,
6
8
  } from "@/lib/integrations/sanity/fetchers/layout"
7
9
 
8
10
  type FooterLinkGroup = NonNullable<FooterData["links"]>[number]
9
11
  type FooterLinkItem = NonNullable<FooterLinkGroup["items"]>[number]
10
12
  type SocialLink = NonNullable<CompanyData["socialLinks"]>[number]
11
13
 
12
- export const Footer = ({
13
- footer,
14
- companyData,
15
- }: {
16
- footer: FooterData | null
17
- companyData: CompanyData | null
18
- }) => {
14
+ export const Footer = async () => {
15
+ const [footer, companyData] = await Promise.all([
16
+ getFooterData(),
17
+ getCompanyData(),
18
+ ])
19
+
19
20
  const links = footer?.links ?? []
20
21
 
21
22
  return (
@@ -1,6 +1,8 @@
1
- import type { NavbarData } from "@/lib/integrations/sanity/fetchers/layout"
1
+ import { getNavbarData } from "@/lib/integrations/sanity/fetchers/layout"
2
2
  import { HeaderClient } from "./header-client"
3
3
 
4
- export const Header = ({ data }: { data: NavbarData | null }) => {
5
- return <HeaderClient data={data} />
4
+ export const Header = async () => {
5
+ const navbar = await getNavbarData()
6
+
7
+ return <HeaderClient data={navbar} />
6
8
  }
@@ -1,7 +1,7 @@
1
1
  import { stegaClean } from "next-sanity"
2
- import type {
3
- CompanyData,
4
- NavbarData,
2
+ import {
3
+ getNavbarData,
4
+ getStructuredData,
5
5
  } from "@/lib/integrations/sanity/fetchers/layout"
6
6
  import {
7
7
  generateOrganizationJsonLd,
@@ -9,36 +9,48 @@ import {
9
9
  JsonLd as JsonLdBase,
10
10
  } from "@/lib/utils/json-ld"
11
11
 
12
- const APP_DESCRIPTION =
13
- "Basement is the AI-native platform for audit and advisory firms. Automate engagement workflows using AI agents trusted by 50% of top 100 firms."
12
+ const nonEmpty = (value: unknown): string | undefined =>
13
+ typeof value === "string" && value.trim() !== "" ? value : undefined
14
+
15
+ export const JsonLd = async () => {
16
+ const [structuredData, navbar] = await Promise.all([
17
+ getStructuredData(),
18
+ getNavbarData(),
19
+ ])
20
+
21
+ // Deep-clean stega artifacts before any value reaches the emitted markup.
22
+ const data = stegaClean(structuredData)
23
+
24
+ const name = nonEmpty(data?.name)
25
+
26
+ // Without an organization name there's nothing meaningful to emit. Editors
27
+ // fill in Layout -> Structured Data to enable site-wide JSON-LD.
28
+ if (!name) return null
14
29
 
15
- export const JsonLd = ({
16
- navbar,
17
- companyData,
18
- }: {
19
- navbar: NavbarData | null
20
- companyData: CompanyData | null
21
- }) => {
22
- const sameAs = companyData?.socialLinks
23
- ?.map((link) => stegaClean(link.url))
24
- .filter((url): url is string => Boolean(url))
30
+ const description = nonEmpty(data?.description)
31
+ const url = nonEmpty(data?.url)
25
32
 
26
- const logoUrl = navbar?.logo?.asset?.url
33
+ // Prefer the structured-data logo, fall back to the navbar logo.
34
+ const logo = nonEmpty(data?.logo) ?? nonEmpty(navbar?.logo?.asset?.url)
35
+
36
+ // Merged and deduped in GROQ (flagged Company Data links + manual profiles).
37
+ const sameAs = (data?.sameAs ?? [])
38
+ .map(nonEmpty)
39
+ .filter((value): value is string => Boolean(value))
27
40
 
28
41
  return (
29
42
  <>
30
- <JsonLdBase
31
- data={generateWebSiteJsonLd({
32
- name: "Basement",
33
- description: APP_DESCRIPTION,
34
- })}
35
- />
43
+ <JsonLdBase data={generateWebSiteJsonLd({ name, url, description })} />
36
44
  <JsonLdBase
37
45
  data={generateOrganizationJsonLd({
38
- name: "Basement",
39
- ...(logoUrl ? { logo: logoUrl } : {}),
40
- description: APP_DESCRIPTION,
41
- ...(sameAs?.length ? { sameAs } : {}),
46
+ name,
47
+ url,
48
+ logo,
49
+ description,
50
+ legalName: nonEmpty(data?.legalName),
51
+ sameAs: sameAs.length ? sameAs : undefined,
52
+ contactPoint: data?.contactPoint,
53
+ address: data?.address,
42
54
  })}
43
55
  />
44
56
  </>
@@ -1,13 +1,8 @@
1
1
  import Link from "next/link"
2
2
  import { Footer } from "@/components/layout/footer"
3
3
  import { Header } from "@/components/layout/header"
4
- import type { SiteLayoutData } from "@/lib/integrations/sanity/fetchers/layout"
5
4
  import { cn } from "@/lib/styles/cn"
6
5
 
7
- interface WrapperProps
8
- extends React.HTMLAttributes<HTMLDivElement>,
9
- SiteLayoutData {}
10
-
11
6
  const SkipToMainContent = () => (
12
7
  <Link
13
8
  href="#main-content"
@@ -20,14 +15,11 @@ const SkipToMainContent = () => (
20
15
  export const Wrapper = ({
21
16
  children,
22
17
  className,
23
- navbar,
24
- footer,
25
- companyData,
26
18
  ...props
27
- }: WrapperProps) => (
19
+ }: React.HTMLAttributes<HTMLDivElement>) => (
28
20
  <>
29
21
  <SkipToMainContent />
30
- <Header data={navbar} />
22
+ <Header />
31
23
  <main
32
24
  id="main-content"
33
25
  className={cn("relative flex grow flex-col", className)}
@@ -35,6 +27,6 @@ export const Wrapper = ({
35
27
  >
36
28
  {children}
37
29
  </main>
38
- <Footer footer={footer} companyData={companyData} />
30
+ <Footer />
39
31
  </>
40
32
  )
@@ -190,7 +190,7 @@ export async function ContentCollection({
190
190
  params: {
191
191
  category: canonicalCategory,
192
192
  offset: fetchOffset,
193
- limit: fetchLimit,
193
+ end: fetchOffset + fetchLimit,
194
194
  },
195
195
  tags: ["blog-articles"],
196
196
  })
@@ -3,8 +3,10 @@ import type { ContentCollectionSearchParams } from "@/components/page-builder/co
3
3
  import { Renderer } from "@/components/page-builder/renderer"
4
4
  import type { PAGE_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types"
5
5
  import { urlForImage } from "@/lib/integrations/sanity/utils/image"
6
+ import { buildPageJsonLd } from "@/lib/integrations/sanity/utils/page-json-ld"
6
7
  import {
7
8
  generateBreadcrumbJsonLd,
9
+ generateSanityArticleJsonLd,
8
10
  generateSanityWebPageJsonLd,
9
11
  JsonLd,
10
12
  } from "@/lib/utils/json-ld"
@@ -15,6 +17,11 @@ type PageDocumentProps = {
15
17
  searchParams: ContentCollectionSearchParams
16
18
  }
17
19
 
20
+ type PageBuilderBlock = NonNullable<
21
+ NonNullable<PAGE_QUERY_RESULT>["pageBuilder"]
22
+ >[number]
23
+ type BlogContentBlock = Extract<PageBuilderBlock, { _type: "blogContent" }>
24
+
18
25
  export const getPageSections = (
19
26
  page: NonNullable<PAGE_QUERY_RESULT>,
20
27
  searchParams: ContentCollectionSearchParams
@@ -79,6 +86,33 @@ export const PageDocument = ({
79
86
  const breadcrumbs = buildBreadcrumbs(path, cleanTitle)
80
87
  const hasBreadcrumbs = breadcrumbs.length > 1
81
88
 
89
+ // Editor-selected page-level structured data (FAQ, Event, custom, etc.).
90
+ const pageJsonLd = buildPageJsonLd(page.metadata?.jsonLd)
91
+
92
+ // Blog posts (pages with a Blog Content block) emit Article JSON-LD with
93
+ // fields derived from the post — no Custom block needed. Skipped when the
94
+ // editor already supplied an Article (via a Custom block) to avoid duplicates.
95
+ const blogBlock = page.pageBuilder?.find(
96
+ (block): block is BlogContentBlock => block?._type === "blogContent"
97
+ )
98
+ const hasManualArticle = pageJsonLd.some(
99
+ ({ data }) => (data as { "@type"?: unknown })["@type"] === "Article"
100
+ )
101
+ const articleJsonLd =
102
+ blogBlock && !hasManualArticle
103
+ ? generateSanityArticleJsonLd({
104
+ title: cleanTitle,
105
+ url: pageUrl,
106
+ description: cleanDescription || undefined,
107
+ image: blogBlock.thumbnail
108
+ ? urlForImage(blogBlock.thumbnail).width(1200).height(630).url()
109
+ : undefined,
110
+ datePublished: stegaClean(blogBlock.date) || undefined,
111
+ dateModified: page._updatedAt,
112
+ authorName: stegaClean(blogBlock.author?.name) || undefined,
113
+ })
114
+ : null
115
+
82
116
  return (
83
117
  <>
84
118
  <JsonLd
@@ -90,9 +124,13 @@ export const PageDocument = ({
90
124
  dateModified: page._updatedAt,
91
125
  })}
92
126
  />
127
+ {articleJsonLd ? <JsonLd data={articleJsonLd} /> : null}
93
128
  {hasBreadcrumbs ? (
94
129
  <JsonLd data={generateBreadcrumbJsonLd(breadcrumbs)} />
95
130
  ) : null}
131
+ {pageJsonLd.map(({ key, data }) => (
132
+ <JsonLd key={key} data={data} />
133
+ ))}
96
134
  <article className="mx-auto flex w-full max-w-6xl flex-1 flex-col gap-14 px-4 py-14 md:px-6 md:py-20">
97
135
  <h1>{title}</h1>
98
136
  {sections.length ? (
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://unpkg.com/knip@6/schema.json",
3
+ "entry": [
4
+ "lib/integrations/sanity/**/*.{ts,tsx}",
5
+ "lib/scripts/**/*.{ts,tsx}",
6
+ "lib/utils/**/*.{ts,tsx}",
7
+ "components/**/*.{ts,tsx}",
8
+ "app/actions/**/*.{ts,tsx}"
9
+ ],
10
+ "ignoreDependencies": [
11
+ "zod",
12
+ "react-use",
13
+ "@portabletext/types",
14
+ "@portabletext/react",
15
+ "@portabletext/markdown",
16
+ "@sanity/vision",
17
+ "@sanity/visual-editing",
18
+ "@sanity/ui",
19
+ "@svgr/webpack",
20
+ "postcss-functions",
21
+ "clsx",
22
+ "rxjs"
23
+ ],
24
+ "ignoreBinaries": [
25
+ "gh"
26
+ ]
27
+ }
@@ -14,6 +14,11 @@ pre-commit:
14
14
  run: bunx tsgo --noEmit --incremental false
15
15
  stage_fixed: false
16
16
 
17
+ pre-push:
18
+ commands:
19
+ knip:
20
+ run: bun run knip
21
+
17
22
  post-merge:
18
23
  commands:
19
24
  install-deps:
@@ -9,11 +9,18 @@ type SanityImageField = {
9
9
 
10
10
  type SanitySlug = { current?: string | null } | null
11
11
 
12
+ type JsonLdBlock = {
13
+ _type: string
14
+ _key: string
15
+ [key: string]: unknown
16
+ }
17
+
12
18
  type SanityPageMetadata = {
13
19
  metaTitle?: string | null
14
20
  metaDescription?: string | null
15
21
  og?: { image?: SanityImageField | null } | null
16
22
  index?: boolean | null
23
+ jsonLd?: JsonLdBlock[] | null
17
24
  title?: string | null
18
25
  description?: string | null
19
26
  image?: SanityImageField | null
@@ -89,6 +96,7 @@ type SocialLink = {
89
96
  icon?: unknown
90
97
  url?: string | null
91
98
  label?: string | null
99
+ includeInStructuredData?: boolean | null
92
100
  }
93
101
 
94
102
  type BlogCategory = {
@@ -194,13 +202,39 @@ export type PAGE_QUERY_RESULT = PageDocument | null
194
202
  export type PAGE_SITEMAP_QUERY_RESULT = PageSitemap[]
195
203
  export type ALL_BLOG_ARTICLES_QUERY_RESULT = BlogArticle[]
196
204
  export type P_REF_PB_COMP_QUERY_RESULT = PageRef[]
197
- export type COMPANY_DATA_QUERY_RESULT = { socialLinks?: SocialLink[] | null } | null
205
+ export type COMPANY_DATA_QUERY_RESULT = {
206
+ socialLinks?: SocialLink[] | null
207
+ } | null
208
+ export type STRUCTURED_DATA_QUERY_RESULT = {
209
+ name?: string | null
210
+ legalName?: string | null
211
+ description?: string | null
212
+ url?: string | null
213
+ logo?: string | null
214
+ contactPoint?: {
215
+ email?: string | null
216
+ telephone?: string | null
217
+ contactType?: string | null
218
+ } | null
219
+ address?: {
220
+ streetAddress?: string | null
221
+ locality?: string | null
222
+ region?: string | null
223
+ postalCode?: string | null
224
+ country?: string | null
225
+ } | null
226
+ sameAs?: string[] | null
227
+ } | null
198
228
  export type FOOTER_QUERY_RESULT = { links?: FooterLinkGroup[] | null } | null
199
229
  export type NAVBAR_QUERY_RESULT = {
200
230
  logo?: {
201
231
  url?: string | null
202
232
  metadata?: { dimensions?: unknown } | null
203
- asset?: { _id: string; url: string; metadata?: { dimensions?: unknown } | null } | null
233
+ asset?: {
234
+ _id: string
235
+ url: string
236
+ metadata?: { dimensions?: unknown } | null
237
+ } | null
204
238
  [key: string]: unknown
205
239
  } | null
206
240
  navigationItems?: NavItem[] | null