bsmnt 0.2.11 → 0.3.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 (115) hide show
  1. package/dist/helpers/create/copy-template.d.ts +1 -1
  2. package/dist/helpers/create/copy-template.d.ts.map +1 -1
  3. package/dist/helpers/create/index.d.ts.map +1 -1
  4. package/dist/helpers/create/index.js +2 -1
  5. package/dist/helpers/create/index.js.map +1 -1
  6. package/dist/helpers/integrate/merge-config.d.ts.map +1 -1
  7. package/dist/helpers/integrate/merge-config.js +0 -2
  8. package/dist/helpers/integrate/merge-config.js.map +1 -1
  9. package/dist/helpers/integrate/sanity/config.d.ts.map +1 -1
  10. package/dist/helpers/integrate/sanity/config.js +3 -14
  11. package/dist/helpers/integrate/sanity/config.js.map +1 -1
  12. package/dist/index.js +84 -35
  13. package/dist/index.js.map +1 -1
  14. package/package.json +1 -1
  15. package/src/templates/next-pagebuilder/.env.example +11 -0
  16. package/src/templates/next-pagebuilder/README.md +23 -0
  17. package/src/templates/next-pagebuilder/_gitignore +67 -0
  18. package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +68 -0
  19. package/src/templates/next-pagebuilder/app/(content)/layout.tsx +13 -0
  20. package/src/templates/next-pagebuilder/app/api/[[...slug]]/route.ts +100 -0
  21. package/src/templates/next-pagebuilder/app/api/draft-mode/disable/route.ts +7 -0
  22. package/src/templates/next-pagebuilder/app/api/draft-mode/enable/route.ts +20 -0
  23. package/src/templates/next-pagebuilder/app/api/revalidate/route.ts +121 -0
  24. package/src/templates/next-pagebuilder/app/favicon.ico +0 -0
  25. package/src/templates/next-pagebuilder/app/layout.tsx +80 -0
  26. package/src/templates/next-pagebuilder/app/robots.ts +15 -0
  27. package/src/templates/next-pagebuilder/app/sitemap.md/route.ts +124 -0
  28. package/src/templates/next-pagebuilder/app/sitemap.xml/route.ts +80 -0
  29. package/src/templates/next-pagebuilder/app/studio/[[...tool]]/page.tsx +8 -0
  30. package/src/templates/next-pagebuilder/biome.json +239 -0
  31. package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +95 -0
  32. package/src/templates/next-pagebuilder/components/layout/header/components/cta-button.tsx +28 -0
  33. package/src/templates/next-pagebuilder/components/layout/header/components/mega-menu-panel.tsx +90 -0
  34. package/src/templates/next-pagebuilder/components/layout/header/components/nav-item-renderer.tsx +98 -0
  35. package/src/templates/next-pagebuilder/components/layout/header/components/nav-leaf-item.tsx +33 -0
  36. package/src/templates/next-pagebuilder/components/layout/header/components/types.ts +7 -0
  37. package/src/templates/next-pagebuilder/components/layout/header/header-client.tsx +110 -0
  38. package/src/templates/next-pagebuilder/components/layout/header/index.tsx +8 -0
  39. package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +45 -0
  40. package/src/templates/next-pagebuilder/components/layout/wrapper/index.tsx +30 -0
  41. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/index.tsx +83 -0
  42. package/src/templates/next-pagebuilder/components/page-builder/components/article-content/related-post-item.tsx +27 -0
  43. package/src/templates/next-pagebuilder/components/page-builder/components/description.tsx +17 -0
  44. package/src/templates/next-pagebuilder/components/page-builder/components/hero.tsx +17 -0
  45. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/content-card.tsx +66 -0
  46. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/content-grid.tsx +42 -0
  47. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/index.tsx +28 -0
  48. package/src/templates/next-pagebuilder/components/page-builder/components/post-collection/types.ts +16 -0
  49. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +36 -0
  50. package/src/templates/next-pagebuilder/components/page-builder/types.ts +23 -0
  51. package/src/templates/next-pagebuilder/components/page-document/index.tsx +91 -0
  52. package/src/templates/next-pagebuilder/components/sanity/draft-mode-toggle.tsx +27 -0
  53. package/src/templates/next-pagebuilder/components/sanity/rich-text.tsx +87 -0
  54. package/src/templates/next-pagebuilder/components/sanity/visual-editing.tsx +27 -0
  55. package/src/templates/next-pagebuilder/components/ui/image/index.tsx +216 -0
  56. package/src/templates/next-pagebuilder/components/ui/link/index.tsx +152 -0
  57. package/src/templates/next-pagebuilder/components/ui/sanity-image/index.tsx +41 -0
  58. package/src/templates/next-pagebuilder/lib/integrations/check-integration.ts +5 -0
  59. package/src/templates/next-pagebuilder/lib/integrations/sanity/client.ts +27 -0
  60. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
  61. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/page-builder-input.tsx +36 -0
  62. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/page-category-input.tsx +50 -0
  63. package/src/templates/next-pagebuilder/lib/integrations/sanity/components/rich-text.tsx +84 -0
  64. package/src/templates/next-pagebuilder/lib/integrations/sanity/confirm-publish-action.ts +40 -0
  65. package/src/templates/next-pagebuilder/lib/integrations/sanity/env.ts +34 -0
  66. package/src/templates/next-pagebuilder/lib/integrations/sanity/fetchers/layout.ts +35 -0
  67. package/src/templates/next-pagebuilder/lib/integrations/sanity/icons.ts +58 -0
  68. package/src/templates/next-pagebuilder/lib/integrations/sanity/live/index.tsx +61 -0
  69. package/src/templates/next-pagebuilder/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
  70. package/src/templates/next-pagebuilder/lib/integrations/sanity/page-builder-config.ts +132 -0
  71. package/src/templates/next-pagebuilder/lib/integrations/sanity/page-category.ts +28 -0
  72. package/src/templates/next-pagebuilder/lib/integrations/sanity/queries.ts +281 -0
  73. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.cli.ts +29 -0
  74. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.config.ts +211 -0
  75. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/index.ts +4 -0
  76. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
  77. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
  78. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
  79. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
  80. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/content/author.ts +70 -0
  81. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
  82. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/index.ts +96 -0
  83. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/company-data.ts +62 -0
  84. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
  85. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/layout/navbar.ts +74 -0
  86. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/link.ts +125 -0
  87. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
  88. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/metadata.ts +68 -0
  89. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
  90. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page-builder.ts +39 -0
  91. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
  92. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/page.ts +232 -0
  93. package/src/templates/next-pagebuilder/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
  94. package/src/templates/next-pagebuilder/lib/integrations/sanity/singletons.ts +44 -0
  95. package/src/templates/next-pagebuilder/lib/integrations/sanity/structure.ts +453 -0
  96. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/image.ts +8 -0
  97. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/link.ts +137 -0
  98. package/src/templates/next-pagebuilder/lib/integrations/sanity/utils/page-builder-markdown.ts +81 -0
  99. package/src/templates/next-pagebuilder/lib/scripts/sanity-typegen.ts +45 -0
  100. package/src/templates/next-pagebuilder/lib/styles/cn.ts +5 -0
  101. package/src/templates/next-pagebuilder/lib/styles/global.css +70 -0
  102. package/src/templates/next-pagebuilder/lib/utils/base-url.ts +17 -0
  103. package/src/templates/next-pagebuilder/lib/utils/format-date.ts +8 -0
  104. package/src/templates/next-pagebuilder/lib/utils/json-ld.tsx +213 -0
  105. package/src/templates/next-pagebuilder/lib/utils/metadata.ts +167 -0
  106. package/src/templates/next-pagebuilder/lib/utils/sitemap.ts +37 -0
  107. package/src/templates/next-pagebuilder/lib/utils/slug-tag.ts +6 -0
  108. package/src/templates/next-pagebuilder/next.config.ts +134 -0
  109. package/src/templates/next-pagebuilder/package.json +71 -0
  110. package/src/templates/next-pagebuilder/postcss.config.mjs +39 -0
  111. package/src/templates/next-pagebuilder/proxy.ts +81 -0
  112. package/src/templates/next-pagebuilder/svg.d.ts +5 -0
  113. package/src/templates/next-pagebuilder/tsconfig.json +38 -0
  114. package/src/helpers/integrate/sanity/files/lib/scripts/copy-sanity-mcp.ts +0 -23
  115. package/src/helpers/integrate/sanity/files/lib/scripts/generate-page.ts +0 -297
@@ -0,0 +1,50 @@
1
+ export interface MarkdownRoute {
2
+ /** Regex to match the public-facing URL */
3
+ regex: RegExp
4
+ /** API route path template (under /api/) */
5
+ apiPath: string
6
+ /** Public markdown URL template (for Link headers) */
7
+ publicPath: string
8
+ }
9
+
10
+ /**
11
+ * Routes that serve markdown versions for AI agents.
12
+ * All pages are backed by the shared `page` document type and resolved
13
+ * through the catch-all route handlers.
14
+ *
15
+ * How it works:
16
+ * - `regex`: match the public-facing URL (e.g. /about.md or /about)
17
+ * - `apiPath`: the internal API route that serves the markdown (e.g. /api/about.md)
18
+ * - Proxy rewrites .md URLs and Accept: text/markdown requests to the API route
19
+ * - Route handlers live under /api/ so page.tsx can coexist at the public path
20
+ */
21
+
22
+ /** .md extension routes -- rewrite to API endpoints */
23
+ export const mdExtensionRoutes: MarkdownRoute[] = [
24
+ {
25
+ regex: /^\/(.+)\.md$/,
26
+ apiPath: "/api/[slug].md",
27
+ publicPath: "/[slug].md",
28
+ },
29
+ ]
30
+
31
+ /** Accept: text/markdown routes -- content negotiation for HTML pages */
32
+ export const acceptHeaderRoutes: MarkdownRoute[] = [
33
+ {
34
+ regex: /^\/(.+)$/,
35
+ apiPath: "/api/[slug].md",
36
+ publicPath: "/[slug].md",
37
+ },
38
+ ]
39
+
40
+ /**
41
+ * Paths the proxy should never process.
42
+ * Studio, static files, Next.js internals.
43
+ */
44
+ export const ignoredPaths = [
45
+ "/studio",
46
+ "/api/",
47
+ "/_next/",
48
+ "/favicon.ico",
49
+ "/sitemap.md",
50
+ ]
@@ -0,0 +1,132 @@
1
+ import { contentIcon, pageIcon, type SanityStudioIcon } from "./icons"
2
+ import { singletonComponents } from "./singletons"
3
+
4
+ export type PageBuilderDocumentType =
5
+ | "hero"
6
+ | "description"
7
+ | "blogContent"
8
+ | (typeof singletonComponents)[number]["schemaType"]
9
+
10
+ type PageBuilderReferenceMember = {
11
+ documentType: PageBuilderDocumentType
12
+ name: string
13
+ title: string
14
+ documentId?: string
15
+ groups: PageBuilderGroupName[]
16
+ }
17
+
18
+ export type PageBuilderGroupName =
19
+ | "generic"
20
+ | "blogEntry"
21
+
22
+ export const pageBuilderPageTypes: Array<{
23
+ title: string
24
+ value: PageBuilderGroupName
25
+ }> = [
26
+ { title: "Generic", value: "generic" },
27
+ { title: "Blog Entry", value: "blogEntry" },
28
+ ]
29
+
30
+ const pageCategoryIcons: Record<PageBuilderGroupName, SanityStudioIcon> = {
31
+ generic: pageIcon,
32
+ blogEntry: contentIcon,
33
+ }
34
+
35
+ export const getPageCategoryIcon = (
36
+ pageType: PageBuilderGroupName | undefined | null
37
+ ) => pageCategoryIcons[pageType ?? "generic"]
38
+
39
+ const reusablePageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
40
+ {
41
+ documentType: "hero",
42
+ name: "heroReference",
43
+ title: "Heading",
44
+ groups: ["generic"],
45
+ },
46
+ {
47
+ documentType: "description",
48
+ name: "descriptionReference",
49
+ title: "Description",
50
+ groups: ["generic"],
51
+ },
52
+ {
53
+ documentType: "blogContent",
54
+ name: "blogContentReference",
55
+ title: "Blog Content",
56
+ groups: ["blogEntry"],
57
+ },
58
+ ]
59
+
60
+ const singletonPageBuilderReferenceMembers: PageBuilderReferenceMember[] =
61
+ singletonComponents.map((component) => ({
62
+ documentType: component.schemaType,
63
+ name: `${component.schemaType}Reference`,
64
+ title: component.title,
65
+ documentId: component.documentId,
66
+ groups: ["generic"],
67
+ }))
68
+
69
+ export const pageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
70
+ ...reusablePageBuilderReferenceMembers,
71
+ ...singletonPageBuilderReferenceMembers,
72
+ ]
73
+
74
+ export const getPageBuilderReferenceMember = (name: string) =>
75
+ pageBuilderReferenceMembers.find((member) => member.name === name)
76
+
77
+ export const getPageBuilderReferenceMemberByDocumentType = (
78
+ documentType: PageBuilderDocumentType
79
+ ) =>
80
+ pageBuilderReferenceMembers.find(
81
+ (member) => member.documentType === documentType
82
+ )
83
+
84
+ const isPageBuilderGroupVisible = (
85
+ pageType: PageBuilderGroupName | undefined,
86
+ group: PageBuilderGroupName
87
+ ) => (pageType ?? "generic") === group
88
+
89
+ export const getVisiblePageBuilderReferenceMembers = (
90
+ pageType: PageBuilderGroupName | undefined
91
+ ) =>
92
+ pageBuilderReferenceMembers.filter((member) =>
93
+ member.groups.some((group) => isPageBuilderGroupVisible(pageType, group))
94
+ )
95
+
96
+ export const getVisiblePageBuilderInsertMenuGroups = (
97
+ pageType: PageBuilderGroupName | undefined
98
+ ) =>
99
+ pageBuilderInsertMenuGroups.filter(
100
+ (group) => group.name === (pageType ?? "generic")
101
+ )
102
+
103
+ export const getInvalidPageBuilderDocumentTypes = (
104
+ pageType: PageBuilderGroupName | undefined,
105
+ documentTypes: PageBuilderDocumentType[]
106
+ ) =>
107
+ documentTypes.filter((documentType) => {
108
+ const member = getPageBuilderReferenceMemberByDocumentType(documentType)
109
+
110
+ if (!member) return false
111
+
112
+ return !member.groups.some((group) =>
113
+ isPageBuilderGroupVisible(pageType, group)
114
+ )
115
+ })
116
+
117
+ export const pageBuilderInsertMenuGroups = [
118
+ {
119
+ name: "generic",
120
+ title: "Generic",
121
+ of: pageBuilderReferenceMembers
122
+ .filter((member) => member.groups.includes("generic"))
123
+ .map((member) => member.name),
124
+ },
125
+ {
126
+ name: "blogEntry",
127
+ title: "Blog Entry",
128
+ of: pageBuilderReferenceMembers
129
+ .filter((member) => member.groups.includes("blogEntry"))
130
+ .map((member) => member.name),
131
+ },
132
+ ]
@@ -0,0 +1,28 @@
1
+ import type { PageBuilderGroupName } from "@/lib/integrations/sanity/page-builder-config"
2
+
3
+ type PageCategoryParams = {
4
+ slug?: string | null
5
+ folder?: string | null
6
+ }
7
+
8
+ export const isEmptyPageSlug = (slug?: string | null) =>
9
+ slug == null || slug === "" || slug === "/"
10
+
11
+ export const getGeneratedPageCategory = ({
12
+ slug,
13
+ folder,
14
+ }: PageCategoryParams): PageBuilderGroupName => {
15
+ if (!isEmptyPageSlug(slug) && folder === "blog") return "blogEntry"
16
+
17
+ return "generic"
18
+ }
19
+
20
+ export const pageCategoryExpression = `
21
+ select(
22
+ defined(slug.current) &&
23
+ slug.current != "" &&
24
+ slug.current != "/" &&
25
+ pageFolder->slug.current == "blog" => "blogEntry",
26
+ "generic"
27
+ )
28
+ `
@@ -0,0 +1,281 @@
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
+ export const PAGE_QUERY = defineQuery(`
101
+ *[
102
+ _type == "page" &&
103
+ (
104
+ ($slug == null && !defined(pageFolder._ref) && (!defined(slug.current) || slug.current == "" || slug.current == "/")) ||
105
+ ${pageResolvedSlugExpression} == $slug
106
+ )
107
+ ][0] {
108
+ ${pageProjection}
109
+ }
110
+ `)
111
+
112
+ export const ALL_PAGE_SLUGS_QUERY = defineQuery(`
113
+ *[_type == "page" && (defined(pageFolder->slug.current) || defined(slug.current))] | order(title asc) {
114
+ title,
115
+ "slug": ${pageResolvedSlugExpression},
116
+ _updatedAt
117
+ }
118
+ `)
119
+
120
+ export const P_REV_SLUGS_QUERY = defineQuery(`
121
+ *[
122
+ _type == "page" &&
123
+ _id in $documentIds
124
+ ] | order(_updatedAt desc) {
125
+ "slug": ${pageResolvedSlugExpression}
126
+ }
127
+ `)
128
+
129
+ export const P_REF_PB_COMP_QUERY = defineQuery(`
130
+ *[
131
+ _type == "page" &&
132
+ count(pageBuilder[_ref == $documentId]) > 0
133
+ ] | order(title asc) {
134
+ _id,
135
+ title,
136
+ "slug": ${pageResolvedSlugExpression}
137
+ }
138
+ `)
139
+
140
+ export const PAGE_SITEMAP_QUERY = defineQuery(`
141
+ *[
142
+ _type == "page" &&
143
+ (
144
+ _id == "page-homepage" ||
145
+ defined(pageFolder->slug.current) ||
146
+ defined(slug.current)
147
+ )
148
+ ] | order(title asc) {
149
+ title,
150
+ "slug": ${pageResolvedSlugExpression},
151
+ _updatedAt,
152
+ "noIndex": select(
153
+ defined(metadata.index) => !metadata.index,
154
+ defined(metadata.noIndex) => metadata.noIndex,
155
+ false
156
+ )
157
+ }
158
+ `)
159
+
160
+ // Blog collection -- fetches pages under a "blog" folder
161
+ // Reaches into the blogContent page-builder block for article-level fields
162
+ export const ALL_BLOG_ARTICLES_QUERY = defineQuery(`
163
+ *[
164
+ _type == "page" &&
165
+ pageFolder->slug.current == "blog" &&
166
+ defined(slug.current) &&
167
+ slug.current != "" &&
168
+ slug.current != "/"
169
+ ] | order(_updatedAt desc) {
170
+ _id,
171
+ title,
172
+ "slug": slug,
173
+ "resolvedSlug": ${pageResolvedSlugExpression},
174
+ "blogContent": pageBuilder[_ref in *[_type == "blogContent"]._id][0]->{
175
+ thumbnail{
176
+ ...,
177
+ alt
178
+ },
179
+ categories[]->{
180
+ _id,
181
+ title,
182
+ slug
183
+ },
184
+ date,
185
+ author->{
186
+ _id,
187
+ name,
188
+ avatar
189
+ }
190
+ },
191
+ metadata,
192
+ _updatedAt
193
+ }
194
+ `)
195
+
196
+ // Company Data
197
+ export const COMPANY_DATA_QUERY = defineQuery(`
198
+ *[_type == "companyData"][0]{
199
+ socialLinks[]{
200
+ _key,
201
+ name,
202
+ icon,
203
+ url,
204
+ label
205
+ }
206
+ }
207
+ `)
208
+
209
+ // Navbar
210
+ // Shared link projection for navbar -- flattens array-of-one to single object
211
+ const navLinkProjection = `
212
+ "link": link[0]{
213
+ ${linkItemProjection}
214
+ }
215
+ `
216
+
217
+ const navLeafItemProjection = `
218
+ _key,
219
+ title,
220
+ ${navLinkProjection}
221
+ `
222
+
223
+ const navColumnProjection = `
224
+ _key,
225
+ title,
226
+ ${navLinkProjection},
227
+ items[]{
228
+ ${navLeafItemProjection}
229
+ }
230
+ `
231
+
232
+ const navMegaMenuProjection = `
233
+ columns[]{
234
+ ${navColumnProjection}
235
+ }
236
+ `
237
+
238
+ export const NAVBAR_QUERY = defineQuery(`
239
+ *[_type == "navbar"][0]{
240
+ logo{
241
+ ...,
242
+ asset->{
243
+ _id,
244
+ url,
245
+ metadata { dimensions }
246
+ }
247
+ },
248
+ navigationItems[]{
249
+ _key,
250
+ title,
251
+ itemType,
252
+ ${navLinkProjection},
253
+ megaMenu{
254
+ ${navMegaMenuProjection}
255
+ }
256
+ },
257
+ ctaButtons[]{
258
+ _key,
259
+ label,
260
+ "link": link[0]{
261
+ ${linkItemProjection}
262
+ },
263
+ variant
264
+ }
265
+ }
266
+ `)
267
+
268
+ // Footer
269
+ export const FOOTER_QUERY = defineQuery(`
270
+ *[_type == "footer"][0]{
271
+ links[]{
272
+ _key,
273
+ title,
274
+ items[]{
275
+ _key,
276
+ label,
277
+ href
278
+ }
279
+ }
280
+ }
281
+ `)
@@ -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
+ })