bsmnt 0.4.2 → 0.5.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 (188) hide show
  1. package/dist/application/add-integration/index.d.ts +24 -6
  2. package/dist/application/add-integration/index.d.ts.map +1 -1
  3. package/dist/application/add-integration/index.js +130 -82
  4. package/dist/application/add-integration/index.js.map +1 -1
  5. package/dist/application/create-project/map-selection-to-registry.js +1 -1
  6. package/dist/application/create-project/map-selection-to-registry.js.map +1 -1
  7. package/dist/application/shared/project-detection.d.ts +2 -2
  8. package/dist/application/shared/project-detection.d.ts.map +1 -1
  9. package/dist/application/shared/project-detection.js +2 -2
  10. package/dist/application/shared/project-detection.js.map +1 -1
  11. package/dist/core/create/internal-ids.d.ts +4 -1
  12. package/dist/core/create/internal-ids.d.ts.map +1 -1
  13. package/dist/core/create/internal-ids.js +6 -1
  14. package/dist/core/create/internal-ids.js.map +1 -1
  15. package/dist/domain/cms.d.ts +0 -7
  16. package/dist/domain/cms.d.ts.map +1 -1
  17. package/dist/domain/cms.js.map +1 -1
  18. package/dist/domain/forms.d.ts +17 -0
  19. package/dist/domain/forms.d.ts.map +1 -0
  20. package/dist/domain/forms.js +13 -0
  21. package/dist/domain/forms.js.map +1 -0
  22. package/dist/domain/integration.d.ts +30 -0
  23. package/dist/domain/integration.d.ts.map +1 -0
  24. package/dist/domain/integration.js +12 -0
  25. package/dist/domain/integration.js.map +1 -0
  26. package/dist/domain/skills.d.ts +32 -0
  27. package/dist/domain/skills.d.ts.map +1 -1
  28. package/dist/domain/skills.js +39 -0
  29. package/dist/domain/skills.js.map +1 -1
  30. package/dist/index.js +95 -37
  31. package/dist/index.js.map +1 -1
  32. package/dist/infrastructure/agents/register-sanity-mcp.js +9 -6
  33. package/dist/infrastructure/agents/register-sanity-mcp.js.map +1 -1
  34. package/dist/infrastructure/create/apply-package-json.d.ts.map +1 -1
  35. package/dist/infrastructure/create/apply-package-json.js +19 -0
  36. package/dist/infrastructure/create/apply-package-json.js.map +1 -1
  37. package/dist/infrastructure/create/install-dependencies.d.ts.map +1 -1
  38. package/dist/infrastructure/create/install-dependencies.js +4 -0
  39. package/dist/infrastructure/create/install-dependencies.js.map +1 -1
  40. package/dist/infrastructure/create/merge-registry.d.ts.map +1 -1
  41. package/dist/infrastructure/create/merge-registry.js +8 -0
  42. package/dist/infrastructure/create/merge-registry.js.map +1 -1
  43. package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
  44. package/dist/infrastructure/create/setup-agent.js +29 -6
  45. package/dist/infrastructure/create/setup-agent.js.map +1 -1
  46. package/dist/infrastructure/create/setup-sanity.d.ts.map +1 -1
  47. package/dist/infrastructure/create/setup-sanity.js +3 -0
  48. package/dist/infrastructure/create/setup-sanity.js.map +1 -1
  49. package/dist/infrastructure/integrations/inject-integration.d.ts +3 -3
  50. package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
  51. package/dist/infrastructure/integrations/inject-integration.js +81 -37
  52. package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
  53. package/dist/modules/features/cms/sanity/config.d.ts.map +1 -1
  54. package/dist/modules/features/cms/sanity/config.js +11 -5
  55. package/dist/modules/features/cms/sanity/config.js.map +1 -1
  56. package/dist/modules/features/cms/sanity/index.js +8 -2
  57. package/dist/modules/features/cms/sanity/index.js.map +1 -1
  58. package/dist/modules/features/cms/sanity/mergers/ci-workflow.d.ts +13 -0
  59. package/dist/modules/features/cms/sanity/mergers/ci-workflow.d.ts.map +1 -0
  60. package/dist/modules/features/cms/sanity/mergers/ci-workflow.js +38 -0
  61. package/dist/modules/features/cms/sanity/mergers/ci-workflow.js.map +1 -0
  62. package/dist/modules/features/cms/sanity/mergers/knip.d.ts +12 -0
  63. package/dist/modules/features/cms/sanity/mergers/knip.d.ts.map +1 -0
  64. package/dist/modules/features/cms/sanity/mergers/knip.js +38 -0
  65. package/dist/modules/features/cms/sanity/mergers/knip.js.map +1 -0
  66. package/dist/modules/features/cms/sanity/mergers/layout.d.ts.map +1 -1
  67. package/dist/modules/features/cms/sanity/mergers/layout.js +7 -3
  68. package/dist/modules/features/cms/sanity/mergers/layout.js.map +1 -1
  69. package/dist/modules/features/cms/sanity/mergers/sitemap.d.ts +3 -3
  70. package/dist/modules/features/cms/sanity/mergers/sitemap.d.ts.map +1 -1
  71. package/dist/modules/features/cms/sanity/mergers/sitemap.js +48 -62
  72. package/dist/modules/features/cms/sanity/mergers/sitemap.js.map +1 -1
  73. package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
  74. package/dist/modules/features/cms/sanity-pagebuilder/config.js +8 -5
  75. package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
  76. package/dist/modules/features/cms/sanity-pagebuilder/index.js +2 -2
  77. package/dist/modules/features/cms/sanity-pagebuilder/index.js.map +1 -1
  78. package/dist/modules/features/forms/hubspot/config.d.ts +31 -0
  79. package/dist/modules/features/forms/hubspot/config.d.ts.map +1 -0
  80. package/dist/modules/features/forms/hubspot/config.js +25 -0
  81. package/dist/modules/features/forms/hubspot/config.js.map +1 -0
  82. package/dist/paths.d.ts +8 -0
  83. package/dist/paths.d.ts.map +1 -1
  84. package/dist/paths.js +8 -0
  85. package/dist/paths.js.map +1 -1
  86. package/index.js +2 -2
  87. package/package.json +17 -9
  88. package/src/assets/check-node-version.mjs +22 -0
  89. package/src/modules/features/cms/sanity/files/app/blog/page.tsx +54 -0
  90. package/src/modules/features/cms/sanity/files/app/feed.xml/route.ts +36 -0
  91. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/components/disable-draft-mode.tsx +3 -3
  92. package/src/modules/features/cms/sanity/files/lib/integrations/sanity/schemas/article.ts +7 -7
  93. package/src/modules/features/cms/sanity/files/lib/scripts/setup-ci-secrets.ts +117 -0
  94. package/src/modules/features/cms/sanity/files/lib/utils/rss.ts +96 -0
  95. package/src/modules/features/cms/sanity-pagebuilder/files/.knip.json +8 -0
  96. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/[[...slug]]/route.ts +100 -0
  97. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/draft-mode/disable/route.ts +7 -0
  98. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/draft-mode/enable/route.ts +20 -0
  99. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +126 -0
  100. package/src/modules/features/cms/sanity-pagebuilder/files/app/feed.xml/route.ts +40 -0
  101. package/src/modules/features/cms/sanity-pagebuilder/files/app/sitemap.md/route.ts +124 -0
  102. package/src/modules/features/cms/sanity-pagebuilder/files/app/studio/[[...tool]]/page.tsx +8 -0
  103. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/draft-mode-toggle.tsx +27 -0
  104. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +87 -0
  105. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/visual-editing.tsx +28 -0
  106. package/src/modules/features/cms/sanity-pagebuilder/files/components/ui/sanity-image/index.tsx +41 -0
  107. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/check-integration.ts +5 -0
  108. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/client.ts +27 -0
  109. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  110. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-input.tsx +39 -0
  111. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  112. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-field.tsx +18 -0
  113. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-input.tsx +14 -0
  114. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  115. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/env.ts +34 -0
  116. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +48 -0
  117. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/redirects.ts +17 -0
  118. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +62 -0
  119. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/live/index.tsx +88 -0
  120. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  121. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +130 -0
  122. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-category.ts +28 -0
  123. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +420 -0
  124. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/pinned-pages.ts +54 -0
  125. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/presentation.ts +119 -0
  126. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +385 -0
  127. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.cli.ts +29 -0
  128. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.config.ts +113 -0
  129. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +4 -0
  130. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  131. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  132. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  133. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  134. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/content/author.ts +70 -0
  135. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  136. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +96 -0
  137. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/company-data.ts +62 -0
  138. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  139. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/navbar.ts +75 -0
  140. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/redirect.ts +120 -0
  141. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  142. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  143. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/metadata.ts +68 -0
  144. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  145. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-builder.ts +39 -0
  146. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  147. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +242 -0
  148. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  149. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +39 -0
  150. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +330 -0
  151. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/image.ts +8 -0
  152. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/link.ts +140 -0
  153. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +81 -0
  154. package/src/modules/features/cms/sanity-pagebuilder/files/lib/scripts/sanity-typegen.ts +45 -0
  155. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/check-redirect.ts +30 -0
  156. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/json-ld.tsx +212 -0
  157. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/metadata.ts +167 -0
  158. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/rss.ts +96 -0
  159. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/sitemap.ts +40 -0
  160. package/src/modules/features/cms/sanity-pagebuilder/files/proxy.ts +81 -0
  161. package/src/templates/next-default/.github/workflows/ci.yml +62 -0
  162. package/src/templates/next-default/README.md +22 -0
  163. package/src/templates/next-default/knip.json +14 -0
  164. package/src/templates/next-default/lefthook.yml +5 -0
  165. package/src/templates/next-default/package.json +8 -4
  166. package/src/templates/next-experiments/.github/workflows/ci.yml +62 -0
  167. package/src/templates/next-experiments/README.md +22 -0
  168. package/src/templates/next-experiments/knip.json +14 -0
  169. package/src/templates/next-experiments/lefthook.yml +30 -0
  170. package/src/templates/next-experiments/package.json +10 -2
  171. package/src/templates/next-pagebuilder/.github/workflows/ci.yml +70 -0
  172. package/src/templates/next-pagebuilder/README.md +34 -0
  173. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +6 -1
  174. package/src/templates/next-pagebuilder/app/(content)/layout.tsx +3 -12
  175. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +11 -10
  176. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +5 -3
  177. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +9 -10
  178. package/src/templates/next-pagebuilder/components/layout/wrapper/index.tsx +3 -11
  179. package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +1 -1
  180. package/src/templates/next-pagebuilder/knip.json +27 -0
  181. package/src/templates/next-pagebuilder/lefthook.yml +5 -0
  182. package/src/templates/next-pagebuilder/lib/scripts/setup-ci-secrets.ts +117 -0
  183. package/src/templates/next-pagebuilder/package.json +9 -3
  184. package/src/templates/next-webgl/.github/workflows/ci.yml +62 -0
  185. package/src/templates/next-webgl/README.md +22 -0
  186. package/src/templates/next-webgl/knip.json +13 -0
  187. package/src/templates/next-webgl/lefthook.yml +5 -0
  188. package/src/templates/next-webgl/package.json +8 -4
@@ -0,0 +1,385 @@
1
+ import { defineQuery } from "next-sanity";
2
+
3
+ const pageResolvedSlugExpression = `
4
+ select(
5
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current,
6
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current,
7
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current,
8
+ defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current,
9
+ defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current,
10
+ defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->slug.current,
11
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current,
12
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current,
13
+ defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current,
14
+ defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current,
15
+ defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current,
16
+ defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->slug.current + "/" + slug.current,
17
+ slug.current
18
+ )
19
+ `;
20
+
21
+ const linkItemProjection = `
22
+ ...,
23
+ _type == "pageReference" => {
24
+ page->{
25
+ _id,
26
+ _type,
27
+ slug,
28
+ title,
29
+ "resolvedSlug": select(
30
+ _type == "page" => ${pageResolvedSlugExpression},
31
+ slug.current
32
+ )
33
+ }
34
+ }
35
+ `;
36
+
37
+ // Helper for rich text link projections (expandable inside any array field)
38
+ const richTextLinkProjection = `
39
+ ...,
40
+ markDefs[]{
41
+ ...,
42
+ _type == "pageReference" => {
43
+ page->{
44
+ _id,
45
+ _type,
46
+ slug,
47
+ title,
48
+ "resolvedSlug": select(
49
+ _type == "page" => ${pageResolvedSlugExpression},
50
+ slug.current
51
+ )
52
+ }
53
+ }
54
+ }
55
+ `;
56
+
57
+ const pageBuilderProjection = `
58
+ pageBuilder[]{
59
+ _key,
60
+ ...@->{
61
+ ...,
62
+ _type == "blogContent" => {
63
+ ...,
64
+ categories[]->{
65
+ _id,
66
+ title,
67
+ slug
68
+ },
69
+ author->{
70
+ _id,
71
+ name,
72
+ avatar,
73
+ role
74
+ },
75
+ body[]{
76
+ ${richTextLinkProjection}
77
+ },
78
+ relatedPosts[]->{
79
+ _id,
80
+ title,
81
+ "resolvedSlug": ${pageResolvedSlugExpression},
82
+ metadata
83
+ }
84
+ }
85
+ }
86
+ }
87
+ `;
88
+
89
+ const pageProjection = `
90
+ _id,
91
+ _type,
92
+ title,
93
+ slug,
94
+ "resolvedSlug": ${pageResolvedSlugExpression},
95
+ ${pageBuilderProjection},
96
+ metadata,
97
+ _updatedAt
98
+ `;
99
+
100
+ const pageMetadataProjection = `
101
+ _id,
102
+ title,
103
+ metadata,
104
+ _updatedAt
105
+ `;
106
+
107
+ export const PAGE_QUERY = defineQuery(`
108
+ *[
109
+ _type == "page" &&
110
+ (
111
+ ($slug == null && !defined(pageFolder._ref) && (!defined(slug.current) || slug.current == "" || slug.current == "/")) ||
112
+ ${pageResolvedSlugExpression} == $slug
113
+ )
114
+ ][0] {
115
+ ${pageProjection}
116
+ }
117
+ `);
118
+
119
+ export const PAGE_METADATA_QUERY = defineQuery(`
120
+ *[
121
+ _type == "page" &&
122
+ (
123
+ ($slug == null && !defined(pageFolder._ref) && (!defined(slug.current) || slug.current == "" || slug.current == "/")) ||
124
+ ${pageResolvedSlugExpression} == $slug
125
+ )
126
+ ][0] {
127
+ ${pageMetadataProjection}
128
+ }
129
+ `);
130
+
131
+ export const ALL_PAGE_SLUGS_QUERY = defineQuery(`
132
+ *[_type == "page" && (defined(pageFolder->slug.current) || defined(slug.current))] | order(title asc) {
133
+ title,
134
+ "slug": ${pageResolvedSlugExpression},
135
+ _updatedAt
136
+ }
137
+ `);
138
+
139
+ export const P_REV_SLUGS_QUERY = defineQuery(`
140
+ *[
141
+ _type == "page" &&
142
+ _id in $documentIds
143
+ ] | order(_updatedAt desc) {
144
+ "slug": ${pageResolvedSlugExpression}
145
+ }
146
+ `);
147
+
148
+ export const P_REF_PB_COMP_QUERY = defineQuery(`
149
+ *[
150
+ _type == "page" &&
151
+ count(pageBuilder[_ref == $documentId]) > 0
152
+ ] | order(title asc) {
153
+ _id,
154
+ title,
155
+ "slug": ${pageResolvedSlugExpression}
156
+ }
157
+ `);
158
+
159
+ export const PAGE_SITEMAP_QUERY = defineQuery(`
160
+ *[
161
+ _type == "page" &&
162
+ (
163
+ _id in $pinnedIds ||
164
+ defined(pageFolder->slug.current) ||
165
+ defined(slug.current)
166
+ )
167
+ ] | order(title asc) {
168
+ title,
169
+ "slug": ${pageResolvedSlugExpression},
170
+ _updatedAt,
171
+ "noIndex": select(
172
+ defined(metadata.index) => !metadata.index,
173
+ defined(metadata.noIndex) => metadata.noIndex,
174
+ false
175
+ )
176
+ }
177
+ `);
178
+
179
+ // Blog collection -- fetches pages under a "blog" folder
180
+ // Reaches into the blogContent page-builder block for article-level fields
181
+ export const ALL_BLOG_ARTICLES_QUERY = defineQuery(`
182
+ *[
183
+ _type == "page" &&
184
+ pageFolder->slug.current == "blog" &&
185
+ defined(slug.current) &&
186
+ slug.current != "" &&
187
+ slug.current != "/"
188
+ ] | order(_updatedAt desc) {
189
+ _id,
190
+ title,
191
+ "slug": slug,
192
+ "resolvedSlug": ${pageResolvedSlugExpression},
193
+ "blogContent": pageBuilder[_ref in *[_type == "blogContent"]._id][0]->{
194
+ thumbnail{
195
+ ...,
196
+ alt
197
+ },
198
+ categories[]->{
199
+ _id,
200
+ title,
201
+ slug
202
+ },
203
+ date,
204
+ author->{
205
+ _id,
206
+ name,
207
+ avatar
208
+ }
209
+ },
210
+ metadata,
211
+ "noIndex": select(
212
+ defined(metadata.index) => !metadata.index,
213
+ defined(metadata.noIndex) => metadata.noIndex,
214
+ false
215
+ ),
216
+ _updatedAt
217
+ }
218
+ `);
219
+
220
+ export const BLOG_ARTICLES_PAGINATED_QUERY = defineQuery(`
221
+ *[
222
+ _type == "page" &&
223
+ pageFolder->slug.current == "blog" &&
224
+ defined(slug.current) &&
225
+ slug.current != "" &&
226
+ slug.current != "/" &&
227
+ (
228
+ !defined($category) ||
229
+ $category == "" ||
230
+ $category in pageBuilder[_ref in *[_type == "blogContent"]._id][0]->categories[]->slug.current
231
+ )
232
+ ] | order(_updatedAt desc)[$offset...$end] {
233
+ _id,
234
+ title,
235
+ "slug": slug,
236
+ "resolvedSlug": ${pageResolvedSlugExpression},
237
+ "blogContent": pageBuilder[_ref in *[_type == "blogContent"]._id][0]->{
238
+ thumbnail{
239
+ ...,
240
+ alt
241
+ },
242
+ categories[]->{
243
+ _id,
244
+ title,
245
+ slug
246
+ },
247
+ date,
248
+ author->{
249
+ _id,
250
+ name,
251
+ avatar
252
+ }
253
+ },
254
+ metadata,
255
+ _updatedAt
256
+ }
257
+ `);
258
+
259
+ export const BLOG_ARTICLES_COUNT_QUERY = defineQuery(`
260
+ count(*[
261
+ _type == "page" &&
262
+ pageFolder->slug.current == "blog" &&
263
+ defined(slug.current) &&
264
+ slug.current != "" &&
265
+ slug.current != "/" &&
266
+ (
267
+ !defined($category) ||
268
+ $category == "" ||
269
+ $category in pageBuilder[_ref in *[_type == "blogContent"]._id][0]->categories[]->slug.current
270
+ )
271
+ ])
272
+ `);
273
+
274
+ export const ALL_BLOG_CATEGORIES_QUERY = defineQuery(`
275
+ *[_type == "blogCategory"] | order(title asc) {
276
+ _id,
277
+ title,
278
+ slug
279
+ }
280
+ `);
281
+
282
+ // Company Data
283
+ export const COMPANY_DATA_QUERY = defineQuery(`
284
+ *[_type == "companyData"][0]{
285
+ socialLinks[]{
286
+ _key,
287
+ name,
288
+ icon,
289
+ url,
290
+ label
291
+ }
292
+ }
293
+ `);
294
+
295
+ // Navbar
296
+ // Shared link projection for navbar -- flattens array-of-one to single object
297
+ const navLinkProjection = `
298
+ "link": link[0]{
299
+ ${linkItemProjection}
300
+ }
301
+ `;
302
+
303
+ const navLeafItemProjection = `
304
+ _key,
305
+ title,
306
+ ${navLinkProjection}
307
+ `;
308
+
309
+ const navColumnProjection = `
310
+ _key,
311
+ title,
312
+ ${navLinkProjection},
313
+ items[]{
314
+ ${navLeafItemProjection}
315
+ }
316
+ `;
317
+
318
+ const navMegaMenuProjection = `
319
+ columns[]{
320
+ ${navColumnProjection}
321
+ }
322
+ `;
323
+
324
+ const navbarProjection = `
325
+ logo{
326
+ ...,
327
+ asset->{
328
+ _id,
329
+ url,
330
+ metadata { dimensions }
331
+ }
332
+ },
333
+ navigationItems[]{
334
+ _key,
335
+ title,
336
+ itemType,
337
+ ${navLinkProjection},
338
+ megaMenu{
339
+ ${navMegaMenuProjection}
340
+ }
341
+ },
342
+ ctaButtons[]{
343
+ _key,
344
+ label,
345
+ "link": link[0]{
346
+ ${linkItemProjection}
347
+ },
348
+ variant
349
+ }
350
+ `;
351
+
352
+ const footerProjection = `
353
+ links[]{
354
+ _key,
355
+ title,
356
+ items[]{
357
+ _key,
358
+ label,
359
+ href
360
+ }
361
+ }
362
+ `;
363
+
364
+ export const NAVBAR_QUERY = defineQuery(`
365
+ *[_type == "navbar"][0]{
366
+ ${navbarProjection}
367
+ }
368
+ `);
369
+
370
+ // Footer
371
+ export const FOOTER_QUERY = defineQuery(`
372
+ *[_type == "footer"][0]{
373
+ ${footerProjection}
374
+ }
375
+ `);
376
+
377
+ // Redirects -- source/destination rules applied by the proxy.
378
+ // `source` is a slug; flatten to its slash-free path string.
379
+ export const REDIRECTS_QUERY = defineQuery(`
380
+ *[_type == "redirect" && defined(source.current) && defined(destination)]{
381
+ "source": source.current,
382
+ destination,
383
+ permanent
384
+ }
385
+ `);
@@ -0,0 +1,29 @@
1
+ /**
2
+ * This configuration file lets you run `$ sanity [command]` in this folder
3
+ * Go to https://www.sanity.io/docs/cli to learn more.
4
+ **/
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { defineCliConfig } from "sanity/cli";
8
+ import { dataset, projectId } from "./env";
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+
12
+ export default defineCliConfig({
13
+ api: { projectId, dataset },
14
+ project: {
15
+ basePath: "/studio",
16
+ },
17
+ typegen: {
18
+ path: "./queries.ts",
19
+ schema: "./schema.json",
20
+ generates: "./sanity.types.ts",
21
+ },
22
+ vite: {
23
+ resolve: {
24
+ alias: {
25
+ "~": __dirname,
26
+ },
27
+ },
28
+ },
29
+ });
@@ -0,0 +1,113 @@
1
+ import { table } from "@sanity/table";
2
+ import { defineConfig } from "sanity";
3
+ import { structureTool } from "sanity/structure";
4
+ import { media } from "sanity-plugin-media";
5
+ import { createConfirmPublishAction } from "./confirm-publish-action";
6
+ import { dataset, projectId } from "./env";
7
+ import { PINNED_PAGE_ENTRIES, PINNED_PAGE_IDS } from "./pinned-pages";
8
+ import { presentation } from "./presentation";
9
+ import { schema } from "./schemas";
10
+ import { singletonComponentTypes } from "./singletons";
11
+ import { structure } from "./structure";
12
+
13
+ const isProd = process.env.NODE_ENV === "production";
14
+
15
+ const singletonDocumentActions = new Set([
16
+ "publish",
17
+ "discardChanges",
18
+ "restore",
19
+ ]);
20
+
21
+ const isSingletonDocument = (schemaType: string, documentId?: string) =>
22
+ singletonComponentTypes.has(schemaType) ||
23
+ (schemaType === "page" &&
24
+ documentId !== undefined &&
25
+ PINNED_PAGE_IDS.has(documentId));
26
+
27
+ export default defineConfig({
28
+ basePath: "/studio",
29
+ projectId,
30
+ dataset,
31
+ schema: {
32
+ ...schema,
33
+ templates: (previousTemplates) => [
34
+ ...previousTemplates.filter(
35
+ (template) =>
36
+ !PINNED_PAGE_IDS.has(template.id) &&
37
+ !["page-with-folder", "page-folder-with-parent"].includes(
38
+ template.id,
39
+ ),
40
+ ),
41
+ ...PINNED_PAGE_ENTRIES.map((entry) => ({
42
+ id: entry.id,
43
+ title: entry.title,
44
+ schemaType: "page",
45
+ value: {
46
+ title: entry.title,
47
+ ...(entry.slug ? { slug: { current: entry.slug } } : {}),
48
+ },
49
+ })),
50
+ {
51
+ id: "page-with-folder",
52
+ title: "Page in Folder",
53
+ schemaType: "page",
54
+ parameters: [
55
+ { name: "pageFolderId", title: "Page Folder ID", type: "string" },
56
+ ],
57
+ value: ({ pageFolderId }: { pageFolderId?: string }) => ({
58
+ pageFolder: pageFolderId
59
+ ? {
60
+ _type: "reference",
61
+ _ref: pageFolderId,
62
+ }
63
+ : undefined,
64
+ }),
65
+ },
66
+ {
67
+ id: "page-folder-with-parent",
68
+ title: "Page Folder in Folder",
69
+ schemaType: "pageFolder",
70
+ parameters: [
71
+ { name: "parentFolderId", title: "Parent Folder ID", type: "string" },
72
+ ],
73
+ value: ({ parentFolderId }: { parentFolderId?: string }) => ({
74
+ parentFolder: parentFolderId
75
+ ? {
76
+ _type: "reference",
77
+ _ref: parentFolderId,
78
+ }
79
+ : undefined,
80
+ }),
81
+ },
82
+ ],
83
+ },
84
+ document: {
85
+ actions: (previousActions, context) => {
86
+ const filtered = isSingletonDocument(
87
+ context.schemaType,
88
+ context.documentId,
89
+ )
90
+ ? previousActions.filter(
91
+ (action) =>
92
+ action.action !== undefined &&
93
+ singletonDocumentActions.has(action.action),
94
+ )
95
+ : previousActions;
96
+
97
+ if (!isProd) return filtered;
98
+
99
+ return filtered.map((action) =>
100
+ action.action === "publish"
101
+ ? createConfirmPublishAction(action)
102
+ : action,
103
+ );
104
+ },
105
+ newDocumentOptions: (previousOptions) =>
106
+ previousOptions.filter(
107
+ (option) =>
108
+ !singletonComponentTypes.has(option.templateId) &&
109
+ !PINNED_PAGE_IDS.has(option.templateId),
110
+ ),
111
+ },
112
+ plugins: [structureTool({ structure }), presentation, media(), table()],
113
+ });
@@ -0,0 +1,4 @@
1
+ export { blogContent } from "./reusable/blog-content";
2
+ export { description } from "./reusable/description";
3
+ export { hero } from "./reusable/hero";
4
+ export { blogCollection } from "./singleton/content-collection";
@@ -0,0 +1,89 @@
1
+ import { defineField, defineType } from "sanity";
2
+ import { contentIcon } from "@/lib/integrations/sanity/icons";
3
+
4
+ export const blogContent = defineType({
5
+ name: "blogContent",
6
+ title: "Blog Content",
7
+ type: "document",
8
+ icon: contentIcon,
9
+ fields: [
10
+ defineField({
11
+ name: "title",
12
+ title: "Title",
13
+ type: "string",
14
+ validation: (Rule) => Rule.required(),
15
+ }),
16
+ defineField({
17
+ name: "thumbnail",
18
+ title: "Thumbnail",
19
+ type: "image",
20
+ description: "Featured image for the article",
21
+ options: { hotspot: true },
22
+ fields: [
23
+ {
24
+ name: "alt",
25
+ title: "Alt Text",
26
+ type: "string",
27
+ description: "Alternative text for screen readers",
28
+ validation: (Rule) => Rule.required(),
29
+ },
30
+ ],
31
+ }),
32
+ defineField({
33
+ name: "categories",
34
+ title: "Categories",
35
+ type: "array",
36
+ of: [{ type: "reference", to: [{ type: "blogCategory" }] }],
37
+ description: "Category tags for filtering",
38
+ }),
39
+ defineField({
40
+ name: "date",
41
+ title: "Publication Date",
42
+ type: "date",
43
+ options: { dateFormat: "YYYY-MM-DD" },
44
+ }),
45
+ defineField({
46
+ name: "author",
47
+ title: "Author",
48
+ type: "reference",
49
+ to: [{ type: "author" }],
50
+ }),
51
+ defineField({
52
+ name: "body",
53
+ title: "Body",
54
+ type: "richText",
55
+ description: "Article content",
56
+ }),
57
+ defineField({
58
+ name: "relatedPosts",
59
+ title: "Related Posts",
60
+ type: "array",
61
+ of: [
62
+ {
63
+ type: "reference",
64
+ to: [{ type: "page" }],
65
+ options: {
66
+ filter:
67
+ 'pageFolder->slug.current == "blog" && defined(slug.current) && slug.current != ""',
68
+ },
69
+ },
70
+ ],
71
+ description: "Manually curated related blog pages",
72
+ validation: (Rule) => Rule.max(3),
73
+ }),
74
+ ],
75
+ preview: {
76
+ select: {
77
+ title: "title",
78
+ date: "date",
79
+ media: "thumbnail",
80
+ },
81
+ prepare({ title, date, media }) {
82
+ return {
83
+ title: title || "Blog Content",
84
+ subtitle: date || "No date set",
85
+ media,
86
+ };
87
+ },
88
+ },
89
+ });
@@ -0,0 +1,29 @@
1
+ import { defineField, defineType } from "sanity";
2
+ import { descriptionIcon } from "@/lib/integrations/sanity/icons";
3
+
4
+ export const description = defineType({
5
+ name: "description",
6
+ title: "Description",
7
+ type: "document",
8
+ icon: descriptionIcon,
9
+ fields: [
10
+ defineField({
11
+ name: "description",
12
+ title: "Description",
13
+ type: "text",
14
+ rows: 4,
15
+ validation: (Rule) => Rule.required(),
16
+ }),
17
+ ],
18
+ preview: {
19
+ select: {
20
+ description: "description",
21
+ },
22
+ prepare({ description }) {
23
+ return {
24
+ title: "Description",
25
+ subtitle: description || "Untitled",
26
+ };
27
+ },
28
+ },
29
+ });
@@ -0,0 +1,28 @@
1
+ import { defineField, defineType } from "sanity";
2
+ import { heroIcon } from "@/lib/integrations/sanity/icons";
3
+
4
+ export const hero = defineType({
5
+ name: "hero",
6
+ title: "Heading",
7
+ type: "document",
8
+ icon: heroIcon,
9
+ fields: [
10
+ defineField({
11
+ name: "headline",
12
+ title: "Heading",
13
+ type: "string",
14
+ validation: (Rule) => Rule.required(),
15
+ }),
16
+ ],
17
+ preview: {
18
+ select: {
19
+ title: "headline",
20
+ },
21
+ prepare({ title }) {
22
+ return {
23
+ title: title || "Untitled",
24
+ subtitle: "Heading",
25
+ };
26
+ },
27
+ },
28
+ });