bsmnt 0.9.0 → 0.11.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.
- package/dist/application/add-integration/index.d.ts.map +1 -1
- package/dist/application/add-integration/index.js +19 -2
- package/dist/application/add-integration/index.js.map +1 -1
- package/dist/application/shared/node-version.js.map +1 -1
- package/dist/core/create/internal-ids.d.ts +3 -0
- package/dist/core/create/internal-ids.d.ts.map +1 -1
- package/dist/core/create/internal-ids.js +4 -0
- package/dist/core/create/internal-ids.js.map +1 -1
- package/dist/domain/agents.d.ts.map +1 -1
- package/dist/domain/animations.d.ts.map +1 -1
- package/dist/domain/cms.d.ts.map +1 -1
- package/dist/domain/forms.d.ts.map +1 -1
- package/dist/domain/hooks.d.ts.map +1 -1
- package/dist/domain/skills.d.ts.map +1 -1
- package/dist/domain/templates.d.ts +10 -0
- package/dist/domain/templates.d.ts.map +1 -1
- package/dist/domain/templates.js +5 -0
- package/dist/domain/templates.js.map +1 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/agents/register-sanity-mcp.js +3 -8
- package/dist/infrastructure/agents/register-sanity-mcp.js.map +1 -1
- package/dist/infrastructure/agents/register-storybook-mcp.d.ts +18 -0
- package/dist/infrastructure/agents/register-storybook-mcp.d.ts.map +1 -0
- package/dist/infrastructure/agents/register-storybook-mcp.js +157 -0
- package/dist/infrastructure/agents/register-storybook-mcp.js.map +1 -0
- package/dist/infrastructure/create/lifecycle-registry.d.ts.map +1 -1
- package/dist/infrastructure/create/lifecycle-registry.js +39 -1
- package/dist/infrastructure/create/lifecycle-registry.js.map +1 -1
- package/dist/infrastructure/create/merge-registry.d.ts.map +1 -1
- package/dist/infrastructure/create/merge-registry.js +4 -0
- package/dist/infrastructure/create/merge-registry.js.map +1 -1
- package/dist/infrastructure/create/sanity-auth.js.map +1 -1
- package/dist/infrastructure/create/setup-agent.d.ts +6 -1
- package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-agent.js +23 -21
- package/dist/infrastructure/create/setup-agent.js.map +1 -1
- package/dist/infrastructure/create/setup-dotenvx.js.map +1 -1
- package/dist/infrastructure/create/setup-remote.js.map +1 -1
- package/dist/infrastructure/create/setup-sanity.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-sanity.js +12 -1
- package/dist/infrastructure/create/setup-sanity.js.map +1 -1
- package/dist/infrastructure/integrations/ensure-studio-headers.d.ts +6 -0
- package/dist/infrastructure/integrations/ensure-studio-headers.d.ts.map +1 -0
- package/dist/infrastructure/integrations/ensure-studio-headers.js +153 -0
- package/dist/infrastructure/integrations/ensure-studio-headers.js.map +1 -0
- package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
- package/dist/infrastructure/integrations/inject-integration.js +2 -0
- package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
- package/dist/infrastructure/update/notifier.js.map +1 -1
- package/dist/modules/features/cms/index.d.ts.map +1 -1
- package/dist/modules/features/cms/index.js +2 -0
- package/dist/modules/features/cms/index.js.map +1 -1
- package/dist/modules/features/cms/sanity/config.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity/config.js +3 -1
- package/dist/modules/features/cms/sanity/config.js.map +1 -1
- package/dist/modules/features/cms/sanity/index.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity/index.js +10 -1
- package/dist/modules/features/cms/sanity/index.js.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/check-integration.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/check-integration.js +15 -6
- package/dist/modules/features/cms/sanity/mergers/check-integration.js.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/knip.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/knip.js +1 -0
- package/dist/modules/features/cms/sanity/mergers/knip.js.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/layout.js.map +1 -1
- package/dist/modules/features/cms/sanity/mergers/package-json.d.ts +12 -0
- package/dist/modules/features/cms/sanity/mergers/package-json.d.ts.map +1 -0
- package/dist/modules/features/cms/sanity/mergers/package-json.js +19 -0
- package/dist/modules/features/cms/sanity/mergers/package-json.js.map +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder/config.js +2 -1
- package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder/index.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder/index.js +7 -1
- package/dist/modules/features/cms/sanity-pagebuilder/index.js.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts +14 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts.map +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js +50 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js.map +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts +3 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/index.d.ts.map +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js +55 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/index.js.map +1 -0
- package/dist/modules/presets/index.d.ts.map +1 -1
- package/dist/modules/presets/index.js +2 -0
- package/dist/modules/presets/index.js.map +1 -1
- package/dist/modules/presets/next-pagebuilder-cache.d.ts +3 -0
- package/dist/modules/presets/next-pagebuilder-cache.d.ts.map +1 -0
- package/dist/modules/presets/next-pagebuilder-cache.js +10 -0
- package/dist/modules/presets/next-pagebuilder-cache.js.map +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +6 -0
- package/dist/paths.js.map +1 -1
- package/package.json +6 -3
- package/src/modules/features/cms/sanity/files/app/api/blog/[slug]/route.ts +4 -1
- package/src/modules/features/cms/sanity/files/app/sitemap.md/route.ts +2 -1
- package/src/modules/features/cms/sanity/files/components/ui/sanity-image/index.tsx +19 -5
- package/src/modules/features/cms/sanity/files/lib/integrations/check-integration.ts +7 -6
- package/src/modules/features/cms/sanity/files/lib/integrations/sanity/README.md +32 -1
- package/src/modules/features/cms/sanity/files/lib/integrations/sanity/components/rich-text.tsx +1 -0
- package/src/modules/features/cms/sanity/files/lib/integrations/sanity/env.ts +2 -2
- package/src/modules/features/cms/sanity/files/proxy.ts +9 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/app/api/[[...slug]]/route.ts +12 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +172 -24
- package/src/modules/features/cms/sanity-pagebuilder/files/app/feed.xml/route.ts +14 -7
- package/src/modules/features/cms/sanity-pagebuilder/files/app/sitemap.md/route.ts +8 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/app/studio/[[...tool]]/page.tsx +16 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +1 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/visual-editing.tsx +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/components/ui/sanity-image/index.tsx +15 -5
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/check-integration.ts +6 -5
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/client.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-field.tsx +13 -7
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/slug-notices.tsx +125 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/env.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +22 -52
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/live/index.tsx +4 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/markdown-proxy.config.ts +1 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +70 -57
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +119 -29
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +1 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +2 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/redirect.ts +35 -4
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/tags.ts +56 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/sitemap.ts +11 -8
- package/src/modules/features/cms/sanity-pagebuilder/files/proxy.ts +9 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/.knip.json +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/[[...slug]]/route.ts +112 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/disable/route.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/draft-mode/enable/route.ts +20 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/revalidate/route.ts +292 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/feed.xml/route.ts +66 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/sitemap.md/route.ts +132 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/layout.tsx +26 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/studio/[[...tool]]/page.tsx +23 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/draft-mode-toggle.tsx +27 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/rich-text.tsx +88 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/visual-editing.tsx +11 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/ui/sanity-image/index.tsx +51 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/check-integration.ts +6 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/client.ts +37 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/block-actions-item.tsx +81 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/disable-draft-mode.tsx +23 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-input.tsx +39 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-category-input.tsx +50 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/same-as-input.tsx +66 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-field.tsx +24 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-input.tsx +14 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/slug-notices.tsx +125 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/confirm-publish-action.ts +40 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/env.ts +34 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/layout.ts +39 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/redirects.ts +22 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +81 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/live/index.tsx +140 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/markdown-proxy.config.ts +50 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +144 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-category.ts +28 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-tree-pane.tsx +431 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/pinned-pages.ts +54 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +119 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +548 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/revalidate-paths.ts +70 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.cli.ts +29 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.config.ts +116 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/index.ts +6 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +89 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/description.ts +29 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +178 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +28 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +39 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +45 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/author.ts +70 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/content/blog-category.ts +55 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +134 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/company-data.ts +70 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/footer.ts +79 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/navbar.ts +75 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/redirect.ts +152 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/structured-data.ts +124 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/link.ts +125 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/logo-field.ts +9 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/metadata.ts +132 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/nav-objects.ts +192 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-builder.ts +43 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-folder.ts +124 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page.ts +265 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/richText.ts +63 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/structured-data-blocks.ts +436 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +51 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +334 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/tags.ts +89 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/image.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/link.ts +140 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-builder-markdown.ts +113 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/utils/page-json-ld.ts +208 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/scripts/sanity-typegen.ts +36 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/check-redirect.ts +30 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/json-ld.tsx +522 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/metadata.ts +189 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/rss.ts +96 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/sitemap.ts +58 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/proxy.ts +90 -0
- package/src/modules/features/env/dotenvx/files/vercelignore +5 -0
- package/src/templates/next-default/.env.example +4 -2
- package/src/templates/next-default/.github/workflows/ci.yml +1 -1
- package/src/templates/next-default/.vscode/settings.json +0 -2
- package/src/templates/next-default/app/robots.ts +2 -3
- package/src/templates/next-default/components/ui/image/index.tsx +2 -4
- package/src/templates/next-default/knip.json +1 -1
- package/src/templates/next-default/lefthook.yml +1 -1
- package/src/templates/next-default/lib/utils/README.md +18 -5
- package/src/templates/next-default/lib/utils/image-sizes.ts +72 -0
- package/src/templates/next-default/lib/utils/merge-refs.ts +56 -0
- package/src/templates/next-default/lib/utils/strings.ts +1 -51
- package/src/templates/next-default/next.config.ts +38 -5
- package/src/templates/next-default/package.json +9 -12
- package/src/templates/next-experiments/.env.example +4 -2
- package/src/templates/next-experiments/.github/workflows/ci.yml +1 -1
- package/src/templates/next-experiments/.vscode/settings.json +0 -2
- package/src/templates/next-experiments/app/page.tsx +1 -1
- package/src/templates/next-experiments/app/robots.ts +2 -3
- package/src/templates/next-experiments/components/ui/image/index.tsx +2 -4
- package/src/templates/next-experiments/knip.json +1 -1
- package/src/templates/next-experiments/lefthook.yml +1 -1
- package/src/templates/next-experiments/lib/utils/README.md +18 -5
- package/src/templates/next-experiments/lib/utils/image-sizes.ts +72 -0
- package/src/templates/next-experiments/lib/utils/merge-refs.ts +56 -0
- package/src/templates/next-experiments/lib/utils/strings.ts +1 -51
- package/src/templates/next-experiments/next.config.ts +38 -5
- package/src/templates/next-experiments/package.json +9 -12
- package/src/templates/next-pagebuilder/.env.example +3 -0
- package/src/templates/next-pagebuilder/.github/workflows/ci.yml +1 -1
- package/src/templates/next-pagebuilder/.vscode/settings.json +0 -2
- package/src/templates/next-pagebuilder/README.md +95 -0
- package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +24 -9
- package/src/templates/next-pagebuilder/app/robots.ts +2 -3
- package/src/templates/next-pagebuilder/app/sitemap.xml/route.ts +9 -4
- package/src/templates/next-pagebuilder/biome.json +2 -1
- package/src/templates/next-pagebuilder/components/layout/footer/index.tsx +3 -6
- package/src/templates/next-pagebuilder/components/layout/header/index.tsx +3 -2
- package/src/templates/next-pagebuilder/components/layout/json-ld/index.tsx +3 -8
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/content-filters.tsx +23 -40
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +88 -58
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/skeleton.tsx +41 -0
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/types.ts +14 -1
- package/src/templates/next-pagebuilder/components/page-builder/components/rich-text-block.tsx +16 -0
- package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +23 -3
- package/src/templates/next-pagebuilder/components/page-document/index.tsx +1 -0
- package/src/templates/next-pagebuilder/components/ui/image/index.tsx +2 -1
- package/src/templates/next-pagebuilder/knip.json +3 -2
- package/src/templates/next-pagebuilder/lefthook.yml +1 -1
- package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +1221 -977
- package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +72 -0
- package/src/templates/next-pagebuilder/lib/utils/merge-refs.ts +56 -0
- package/src/templates/next-pagebuilder/next.config.ts +35 -5
- package/src/templates/next-pagebuilder/package.json +8 -10
- package/src/templates/next-pagebuilder-cache/.biome/plugins/README.md +21 -0
- package/src/templates/next-pagebuilder-cache/.biome/plugins/no-anchor-element.grit +12 -0
- package/src/templates/next-pagebuilder-cache/.biome/plugins/no-relative-parent-imports.grit +10 -0
- package/src/templates/next-pagebuilder-cache/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
- package/src/templates/next-pagebuilder-cache/.env.example +40 -0
- package/src/templates/next-pagebuilder-cache/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/src/templates/next-pagebuilder-cache/.github/workflows/ci.yml +105 -0
- package/src/templates/next-pagebuilder-cache/.vscode/extensions.json +19 -0
- package/src/templates/next-pagebuilder-cache/.vscode/settings.json +103 -0
- package/src/templates/next-pagebuilder-cache/.zed/settings.json +47 -0
- package/src/templates/next-pagebuilder-cache/README.md +212 -0
- package/src/templates/next-pagebuilder-cache/_gitignore +65 -0
- package/src/templates/next-pagebuilder-cache/app/(content)/[[...slug]]/page.tsx +124 -0
- package/src/templates/next-pagebuilder-cache/app/(content)/layout.tsx +28 -0
- package/src/templates/next-pagebuilder-cache/app/actions/unlock-gated-content.ts +53 -0
- package/src/templates/next-pagebuilder-cache/app/favicon.ico +0 -0
- package/src/templates/next-pagebuilder-cache/app/layout.tsx +83 -0
- package/src/templates/next-pagebuilder-cache/app/robots.ts +13 -0
- package/src/templates/next-pagebuilder-cache/app/sitemap.xml/route.ts +84 -0
- package/src/templates/next-pagebuilder-cache/biome.json +257 -0
- package/src/templates/next-pagebuilder-cache/components/layout/footer/index.tsx +127 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/components/cta-button.tsx +28 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/components/mega-menu-panel.tsx +90 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-item-renderer.tsx +98 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/components/nav-leaf-item.tsx +33 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/components/types.ts +7 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/header-client.tsx +110 -0
- package/src/templates/next-pagebuilder-cache/components/layout/header/index.tsx +32 -0
- package/src/templates/next-pagebuilder-cache/components/layout/json-ld/index.tsx +79 -0
- package/src/templates/next-pagebuilder-cache/components/layout/wrapper/index.tsx +33 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/index.tsx +78 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/related-post-item.tsx +27 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-card.tsx +66 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-filters.tsx +76 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-grid.tsx +40 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/content-pagination-nav.tsx +71 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/index.tsx +306 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/skeleton.tsx +41 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/types.ts +32 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/description.tsx +17 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +169 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/hero.tsx +17 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/rich-text-block.tsx +16 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +71 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/types.ts +25 -0
- package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +147 -0
- package/src/templates/next-pagebuilder-cache/components/ui/image/index.tsx +216 -0
- package/src/templates/next-pagebuilder-cache/components/ui/link/index.tsx +152 -0
- package/src/templates/next-pagebuilder-cache/components.json +24 -0
- package/src/templates/next-pagebuilder-cache/knip.json +35 -0
- package/src/templates/next-pagebuilder-cache/lefthook.yml +25 -0
- package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +1588 -0
- package/src/templates/next-pagebuilder-cache/lib/scripts/setup-ci-secrets.ts +117 -0
- package/src/templates/next-pagebuilder-cache/lib/styles/cn.ts +5 -0
- package/src/templates/next-pagebuilder-cache/lib/styles/global.css +69 -0
- package/src/templates/next-pagebuilder-cache/lib/utils/base-url.ts +17 -0
- package/src/templates/next-pagebuilder-cache/lib/utils/format-date.ts +8 -0
- package/src/templates/next-pagebuilder-cache/lib/utils/slug-tag.ts +6 -0
- package/src/templates/next-pagebuilder-cache/next.config.ts +176 -0
- package/src/templates/next-pagebuilder-cache/package.json +62 -0
- package/src/templates/next-pagebuilder-cache/postcss.config.mjs +65 -0
- package/src/templates/next-pagebuilder-cache/svg.d.ts +6 -0
- package/src/templates/next-pagebuilder-cache/tsconfig.json +38 -0
- package/src/templates/next-webgl/.env.example +4 -2
- package/src/templates/next-webgl/.github/workflows/ci.yml +1 -1
- package/src/templates/next-webgl/.vscode/settings.json +0 -2
- package/src/templates/next-webgl/app/robots.ts +2 -3
- package/src/templates/next-webgl/components/ui/image/index.tsx +2 -4
- package/src/templates/next-webgl/knip.json +1 -1
- package/src/templates/next-webgl/lefthook.yml +1 -1
- package/src/templates/next-webgl/lib/utils/README.md +18 -5
- package/src/templates/next-webgl/lib/utils/image-sizes.ts +72 -0
- package/src/templates/next-webgl/lib/utils/merge-refs.ts +56 -0
- package/src/templates/next-webgl/lib/utils/strings.ts +1 -51
- package/src/templates/next-webgl/next.config.ts +38 -5
- package/src/templates/next-webgl/package.json +11 -14
- package/src/templates/next-experiments/tsconfig.tsbuildinfo +0 -1
- package/src/templates/next-pagebuilder/app/actions/refresh.ts +0 -5
- package/src/templates/next-webgl/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Badge, Card, Flex, Stack, Text } from "@sanity/ui";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { type ArrayOfPrimitivesInputProps, useClient } from "sanity";
|
|
4
|
+
import { apiVersion } from "../env";
|
|
5
|
+
|
|
6
|
+
type CompanyProfile = { name?: string | null; url?: string | null };
|
|
7
|
+
|
|
8
|
+
// Draft-first so editors see unpublished toggle changes.
|
|
9
|
+
export const INCLUDED_COMPANY_PROFILES_QUERY = `coalesce(
|
|
10
|
+
*[_id == "drafts.companyData"][0],
|
|
11
|
+
*[_id == "companyData"][0]
|
|
12
|
+
).socialLinks[includeInStructuredData == true]{ name, url }`;
|
|
13
|
+
|
|
14
|
+
// Shows which Company Data social links are merged into sameAs automatically.
|
|
15
|
+
export function SameAsInput(props: ArrayOfPrimitivesInputProps) {
|
|
16
|
+
const { renderDefault } = props;
|
|
17
|
+
const client = useClient({ apiVersion });
|
|
18
|
+
const [included, setIncluded] = useState<CompanyProfile[]>([]);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
let active = true;
|
|
22
|
+
client
|
|
23
|
+
.fetch<CompanyProfile[] | null>(INCLUDED_COMPANY_PROFILES_QUERY)
|
|
24
|
+
.then((rows) => {
|
|
25
|
+
if (active) setIncluded(rows ?? []);
|
|
26
|
+
})
|
|
27
|
+
.catch(() => {
|
|
28
|
+
// Best-effort preview — never block editing.
|
|
29
|
+
});
|
|
30
|
+
return () => {
|
|
31
|
+
active = false;
|
|
32
|
+
};
|
|
33
|
+
}, [client]);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Stack space={3}>
|
|
37
|
+
<Card padding={3} radius={2} border tone="transparent">
|
|
38
|
+
<Stack space={3}>
|
|
39
|
+
{included.length > 0 ? (
|
|
40
|
+
<>
|
|
41
|
+
<Text size={1} muted>
|
|
42
|
+
Included from Company Data (toggle off there to remove):
|
|
43
|
+
</Text>
|
|
44
|
+
{included.map((profile) => (
|
|
45
|
+
<Flex key={profile.url} gap={2} align="center">
|
|
46
|
+
<Badge fontSize={0} mode="outline">
|
|
47
|
+
{profile.name ?? "Profile"}
|
|
48
|
+
</Badge>
|
|
49
|
+
<Text size={1} muted textOverflow="ellipsis">
|
|
50
|
+
{profile.url}
|
|
51
|
+
</Text>
|
|
52
|
+
</Flex>
|
|
53
|
+
))}
|
|
54
|
+
</>
|
|
55
|
+
) : (
|
|
56
|
+
<Text size={1} muted>
|
|
57
|
+
No Company Data social links are included yet — enable "Include in
|
|
58
|
+
Structured Data" on a social link to add it here.
|
|
59
|
+
</Text>
|
|
60
|
+
)}
|
|
61
|
+
</Stack>
|
|
62
|
+
</Card>
|
|
63
|
+
{renderDefault(props)}
|
|
64
|
+
</Stack>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Stack } from "@sanity/ui";
|
|
2
|
+
import { type FieldProps, useFormValue } from "sanity";
|
|
3
|
+
import { SlugRedirectNotice } from "@/lib/integrations/sanity/components/slug-notices";
|
|
4
|
+
import { getPinnedPageById } from "@/lib/integrations/sanity/pinned-pages";
|
|
5
|
+
|
|
6
|
+
const DEFAULT_DESCRIPTION = "URL path without leading slash.";
|
|
7
|
+
const PINNED_DESCRIPTION =
|
|
8
|
+
"URL path without leading slash. Disabled on 📌 pinned pages.";
|
|
9
|
+
|
|
10
|
+
// Swaps the slug description on pinned pages (plain-string field, hence 📌).
|
|
11
|
+
export function SlugField(props: FieldProps) {
|
|
12
|
+
const documentId = useFormValue(["_id"]) as string | undefined;
|
|
13
|
+
const pinned = getPinnedPageById(documentId);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Stack space={3}>
|
|
17
|
+
{props.renderDefault({
|
|
18
|
+
...props,
|
|
19
|
+
description: pinned ? PINNED_DESCRIPTION : DEFAULT_DESCRIPTION,
|
|
20
|
+
})}
|
|
21
|
+
<SlugRedirectNotice pinnedPath={pinned?.path} />
|
|
22
|
+
</Stack>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SlugInputProps } from "sanity";
|
|
2
|
+
|
|
3
|
+
// Adds a not-allowed cursor to the slug field when it's read-only (pinned pages).
|
|
4
|
+
export function SlugInput(props: SlugInputProps) {
|
|
5
|
+
if (!props.readOnly) {
|
|
6
|
+
return props.renderDefault(props);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<div style={{ cursor: "not-allowed" }}>
|
|
11
|
+
<div style={{ pointerEvents: "none" }}>{props.renderDefault(props)}</div>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Box, Button, Card, Stack, Text } from "@sanity/ui";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useClient, useFormValue } from "sanity";
|
|
4
|
+
import { useRouter } from "sanity/router";
|
|
5
|
+
import { apiVersion } from "@/lib/integrations/sanity/env";
|
|
6
|
+
import { isEmptyPageSlug } from "@/lib/integrations/sanity/page-category";
|
|
7
|
+
import { FOLDER_PATH_QUERY } from "@/lib/integrations/sanity/queries";
|
|
8
|
+
|
|
9
|
+
const REDIRECT_QUERY = `*[_type == "redirect" && source.current == $source][0]._id`;
|
|
10
|
+
|
|
11
|
+
// The slug field writes on every keystroke.
|
|
12
|
+
const LOOKUP_DEBOUNCE_MS = 400;
|
|
13
|
+
|
|
14
|
+
interface SlugRedirectNoticeProps {
|
|
15
|
+
/** Public path of a pinned page, whose URL is fixed rather than slug-derived. */
|
|
16
|
+
pinnedPath?: string | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Warns when a published redirect claims this page's URL — the catch-all
|
|
21
|
+
* route only runs `checkRedirect` after a page lookup misses, so the page
|
|
22
|
+
* wins and the redirect silently never fires.
|
|
23
|
+
*
|
|
24
|
+
* Reads the `page` form shape; don't reuse for other slug types.
|
|
25
|
+
*/
|
|
26
|
+
export function SlugRedirectNotice({ pinnedPath }: SlugRedirectNoticeProps) {
|
|
27
|
+
const client = useClient({ apiVersion });
|
|
28
|
+
const router = useRouter();
|
|
29
|
+
const slug = useFormValue(["slug", "current"]) as string | undefined;
|
|
30
|
+
const folderId = useFormValue(["pageFolder", "_ref"]) as string | undefined;
|
|
31
|
+
const [folderPath, setFolderPath] = useState("");
|
|
32
|
+
const [redirectId, setRedirectId] = useState<string | null>(null);
|
|
33
|
+
|
|
34
|
+
// Separate effect so the folder chain isn't re-resolved on every keystroke.
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!folderId) {
|
|
37
|
+
setFolderPath("");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let active = true;
|
|
42
|
+
const published = client.withConfig({ perspective: "published" });
|
|
43
|
+
|
|
44
|
+
published
|
|
45
|
+
// Leaf joins in JS below, so this tracks the live slug rather than the
|
|
46
|
+
// last saved draft.
|
|
47
|
+
.fetch<{ path: string | null } | null>(FOLDER_PATH_QUERY, { folderId })
|
|
48
|
+
.then((folder) => {
|
|
49
|
+
if (active) setFolderPath(folder?.path ?? "");
|
|
50
|
+
})
|
|
51
|
+
.catch(() => {
|
|
52
|
+
if (active) setFolderPath("");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
active = false;
|
|
57
|
+
};
|
|
58
|
+
}, [client, folderId]);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
const leaf = isEmptyPageSlug(slug) ? "" : slug;
|
|
62
|
+
const source = pinnedPath
|
|
63
|
+
? pinnedPath.replace(/^\/+/, "")
|
|
64
|
+
: [folderPath, leaf].filter(Boolean).join("/");
|
|
65
|
+
|
|
66
|
+
if (!source) {
|
|
67
|
+
setRedirectId(null);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let active = true;
|
|
72
|
+
// Drafts never reach visitors, so an unpublished redirect isn't a conflict.
|
|
73
|
+
const published = client.withConfig({ perspective: "published" });
|
|
74
|
+
|
|
75
|
+
const timer = setTimeout(async () => {
|
|
76
|
+
try {
|
|
77
|
+
const id = await published.fetch<string | null>(REDIRECT_QUERY, {
|
|
78
|
+
source,
|
|
79
|
+
});
|
|
80
|
+
if (active) setRedirectId(id);
|
|
81
|
+
} catch {
|
|
82
|
+
if (active) setRedirectId(null);
|
|
83
|
+
}
|
|
84
|
+
}, LOOKUP_DEBOUNCE_MS);
|
|
85
|
+
|
|
86
|
+
return () => {
|
|
87
|
+
active = false;
|
|
88
|
+
clearTimeout(timer);
|
|
89
|
+
};
|
|
90
|
+
}, [client, folderPath, pinnedPath, slug]);
|
|
91
|
+
|
|
92
|
+
if (!redirectId) return null;
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Card border padding={3} radius={2} tone="caution">
|
|
96
|
+
<Stack space={3}>
|
|
97
|
+
<Stack space={2}>
|
|
98
|
+
<Text size={1} weight="semibold">
|
|
99
|
+
A redirect already claims this URL
|
|
100
|
+
</Text>
|
|
101
|
+
<Text muted size={1}>
|
|
102
|
+
Visitors reach this page instead — a redirect only runs when no page
|
|
103
|
+
matches its path. Remove the redirect, or move this page to another
|
|
104
|
+
slug.
|
|
105
|
+
</Text>
|
|
106
|
+
</Stack>
|
|
107
|
+
<Box>
|
|
108
|
+
<Button
|
|
109
|
+
fontSize={1}
|
|
110
|
+
mode="ghost"
|
|
111
|
+
onClick={() =>
|
|
112
|
+
router.navigateIntent("edit", {
|
|
113
|
+
id: redirectId,
|
|
114
|
+
type: "redirect",
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
padding={3}
|
|
118
|
+
text="Go to redirect"
|
|
119
|
+
tone="caution"
|
|
120
|
+
/>
|
|
121
|
+
</Box>
|
|
122
|
+
</Stack>
|
|
123
|
+
</Card>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
DocumentActionComponent,
|
|
4
|
+
DocumentActionDialogProps,
|
|
5
|
+
DocumentActionProps,
|
|
6
|
+
} from "sanity";
|
|
7
|
+
|
|
8
|
+
export function createConfirmPublishAction(
|
|
9
|
+
originalPublishAction: DocumentActionComponent,
|
|
10
|
+
): DocumentActionComponent {
|
|
11
|
+
const ConfirmPublishAction = (props: DocumentActionProps) => {
|
|
12
|
+
const original = originalPublishAction(props);
|
|
13
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
14
|
+
|
|
15
|
+
if (!original) return null;
|
|
16
|
+
|
|
17
|
+
const { dialog: _originalDialog, ...originalWithoutDialog } = original;
|
|
18
|
+
const dialog: DocumentActionDialogProps | false = dialogOpen
|
|
19
|
+
? {
|
|
20
|
+
type: "confirm",
|
|
21
|
+
tone: "critical",
|
|
22
|
+
message:
|
|
23
|
+
"This will make these changes live on the production site immediately. Continue?",
|
|
24
|
+
onCancel: () => setDialogOpen(false),
|
|
25
|
+
onConfirm: () => {
|
|
26
|
+
setDialogOpen(false);
|
|
27
|
+
original.onHandle?.();
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
: false;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
...originalWithoutDialog,
|
|
34
|
+
onHandle: () => setDialogOpen(true),
|
|
35
|
+
dialog,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return ConfirmPublishAction;
|
|
40
|
+
}
|
package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/env.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanity Environment Configuration
|
|
3
|
+
*
|
|
4
|
+
* All values have safe defaults to allow the app to build and run
|
|
5
|
+
* without Sanity configured. Use isSanityConfigured() to check
|
|
6
|
+
* if Sanity is properly set up before making API calls.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Floor, not a preference: Content Releases need 2025-02-19 or later. */
|
|
10
|
+
export const apiVersion =
|
|
11
|
+
process.env.NEXT_PUBLIC_SANITY_API_VERSION || "2025-02-19";
|
|
12
|
+
|
|
13
|
+
/** Sanity dataset name - defaults to 'production' */
|
|
14
|
+
export const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET || "production";
|
|
15
|
+
|
|
16
|
+
/** Sanity project ID - empty string if not configured */
|
|
17
|
+
export const projectId =
|
|
18
|
+
process.env.NEXT_PUBLIC_SANITY_PROJECT_ID ||
|
|
19
|
+
process.env.SANITY_STUDIO_PROJECT_ID ||
|
|
20
|
+
"";
|
|
21
|
+
|
|
22
|
+
/** Sanity Studio URL for visual editing */
|
|
23
|
+
export const studioUrl =
|
|
24
|
+
process.env.NODE_ENV === "development"
|
|
25
|
+
? "http://localhost:3000/studio"
|
|
26
|
+
: `${process.env.NEXT_PUBLIC_BASE_URL || ""}/studio`;
|
|
27
|
+
|
|
28
|
+
export const sanityToken = process.env.SANITY_API_READ_TOKEN || "";
|
|
29
|
+
|
|
30
|
+
/** Preview URL for draft mode */
|
|
31
|
+
export const previewURL =
|
|
32
|
+
process.env.NODE_ENV === "development"
|
|
33
|
+
? "http://localhost:3000"
|
|
34
|
+
: process.env.NEXT_PUBLIC_BASE_URL || "";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DynamicFetchOptions,
|
|
3
|
+
sanityFetch,
|
|
4
|
+
toSanityFetchOptions,
|
|
5
|
+
} from "@/lib/integrations/sanity/live"
|
|
6
|
+
import { LAYOUT_QUERY } from "@/lib/integrations/sanity/queries"
|
|
7
|
+
import type { LAYOUT_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types"
|
|
8
|
+
import { SANITY_LAYOUT_TAGS } from "@/lib/integrations/sanity/tags"
|
|
9
|
+
|
|
10
|
+
export type LayoutData = LAYOUT_QUERY_RESULT
|
|
11
|
+
export type NavbarData = NonNullable<LayoutData["navbar"]>
|
|
12
|
+
export type FooterData = NonNullable<LayoutData["footer"]>
|
|
13
|
+
export type CompanyData = NonNullable<LayoutData["companyData"]>
|
|
14
|
+
export type StructuredData = NonNullable<LayoutData["structuredData"]>
|
|
15
|
+
|
|
16
|
+
const EMPTY_LAYOUT: LayoutData = {
|
|
17
|
+
navbar: null,
|
|
18
|
+
footer: null,
|
|
19
|
+
companyData: null,
|
|
20
|
+
structuredData: null,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// One entry for all four layout singletons: header, footer and json-ld call this
|
|
24
|
+
// with the same options, so they share one fetch instead of four.
|
|
25
|
+
//
|
|
26
|
+
// Don't cap the empty branch — this renders in every route's shell, and a nested
|
|
27
|
+
// lifetime propagates upwards as a min().
|
|
28
|
+
export async function getLayoutData(
|
|
29
|
+
fetchOptions: DynamicFetchOptions
|
|
30
|
+
): Promise<LayoutData> {
|
|
31
|
+
"use cache"
|
|
32
|
+
const { data } = await sanityFetch({
|
|
33
|
+
query: LAYOUT_QUERY,
|
|
34
|
+
...toSanityFetchOptions(fetchOptions),
|
|
35
|
+
tags: [...SANITY_LAYOUT_TAGS],
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return (data as LayoutData | null) ?? EMPTY_LAYOUT
|
|
39
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PUBLISHED_FETCH_OPTIONS,
|
|
3
|
+
sanityFetch,
|
|
4
|
+
toSanityFetchOptions,
|
|
5
|
+
} from "@/lib/integrations/sanity/live"
|
|
6
|
+
import { REDIRECTS_QUERY } from "@/lib/integrations/sanity/queries"
|
|
7
|
+
import type { REDIRECTS_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types"
|
|
8
|
+
import { SANITY_REDIRECTS_TAG } from "@/lib/integrations/sanity/tags"
|
|
9
|
+
|
|
10
|
+
export type RedirectEntry = REDIRECTS_QUERY_RESULT[number]
|
|
11
|
+
|
|
12
|
+
// Routing infra, not preview content — always read published and cache it.
|
|
13
|
+
export async function getRedirects(): Promise<REDIRECTS_QUERY_RESULT> {
|
|
14
|
+
"use cache"
|
|
15
|
+
const { data } = await sanityFetch({
|
|
16
|
+
query: REDIRECTS_QUERY,
|
|
17
|
+
...toSanityFetchOptions(PUBLISHED_FETCH_OPTIONS),
|
|
18
|
+
tags: [SANITY_REDIRECTS_TAG],
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
return (data as REDIRECTS_QUERY_RESULT | null) ?? []
|
|
22
|
+
}
|
package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Icon, IconProps } from "@phosphor-icons/react";
|
|
2
|
+
import {
|
|
3
|
+
AppWindowIcon,
|
|
4
|
+
ArrowBendUpRightIcon,
|
|
5
|
+
ArticleNyTimesIcon,
|
|
6
|
+
BracketsCurlyIcon,
|
|
7
|
+
BriefcaseIcon,
|
|
8
|
+
BrowsersIcon,
|
|
9
|
+
BuildingsIcon,
|
|
10
|
+
CalendarBlankIcon,
|
|
11
|
+
CardsIcon,
|
|
12
|
+
FileTextIcon,
|
|
13
|
+
FolderOpenIcon,
|
|
14
|
+
FootprintsIcon,
|
|
15
|
+
LayoutIcon,
|
|
16
|
+
ListBulletsIcon,
|
|
17
|
+
ListIcon,
|
|
18
|
+
LockKeyIcon,
|
|
19
|
+
PackageIcon,
|
|
20
|
+
QuestionIcon,
|
|
21
|
+
RocketIcon,
|
|
22
|
+
ShapesIcon,
|
|
23
|
+
ShareNetworkIcon,
|
|
24
|
+
TagIcon,
|
|
25
|
+
TextAlignLeftIcon,
|
|
26
|
+
TextTIcon,
|
|
27
|
+
TreeStructureIcon,
|
|
28
|
+
UserCircleIcon,
|
|
29
|
+
VideoCameraIcon,
|
|
30
|
+
} from "@phosphor-icons/react/dist/ssr";
|
|
31
|
+
import { createElement, forwardRef } from "react";
|
|
32
|
+
|
|
33
|
+
export type SanityStudioIcon = Icon;
|
|
34
|
+
|
|
35
|
+
const asDuotoneIcon = (IconComponent: Icon): SanityStudioIcon => {
|
|
36
|
+
const DuotoneIcon = forwardRef<SVGSVGElement, IconProps>((props, ref) =>
|
|
37
|
+
createElement(IconComponent, { ...props, ref, weight: "duotone" }),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
DuotoneIcon.displayName = `${IconComponent.displayName ?? "Phosphor"}Duotone`;
|
|
41
|
+
|
|
42
|
+
return DuotoneIcon;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const pageBuilderCardIcon = asDuotoneIcon(PackageIcon);
|
|
46
|
+
export const pageBuilderCardListIcon = asDuotoneIcon(ListIcon);
|
|
47
|
+
|
|
48
|
+
export const authorIcon = asDuotoneIcon(UserCircleIcon);
|
|
49
|
+
|
|
50
|
+
export const pageListIcon = asDuotoneIcon(ListBulletsIcon);
|
|
51
|
+
|
|
52
|
+
export const blogCategoryIcon = asDuotoneIcon(TagIcon);
|
|
53
|
+
|
|
54
|
+
export const componentsFolderIcon = asDuotoneIcon(ShapesIcon);
|
|
55
|
+
|
|
56
|
+
export const companyDataIcon = asDuotoneIcon(BuildingsIcon);
|
|
57
|
+
export const socialLinksIcon = asDuotoneIcon(ShareNetworkIcon);
|
|
58
|
+
export const navbarIcon = asDuotoneIcon(ListIcon);
|
|
59
|
+
export const footerIcon = asDuotoneIcon(FootprintsIcon);
|
|
60
|
+
export const redirectIcon = asDuotoneIcon(ArrowBendUpRightIcon);
|
|
61
|
+
export const layoutFolderIcon = asDuotoneIcon(LayoutIcon);
|
|
62
|
+
export const structuredDataIcon = asDuotoneIcon(TreeStructureIcon);
|
|
63
|
+
|
|
64
|
+
export const faqJsonLdIcon = asDuotoneIcon(QuestionIcon);
|
|
65
|
+
export const eventJsonLdIcon = asDuotoneIcon(CalendarBlankIcon);
|
|
66
|
+
export const videoJsonLdIcon = asDuotoneIcon(VideoCameraIcon);
|
|
67
|
+
export const jobPostingJsonLdIcon = asDuotoneIcon(BriefcaseIcon);
|
|
68
|
+
export const softwareApplicationJsonLdIcon = asDuotoneIcon(AppWindowIcon);
|
|
69
|
+
export const itemListJsonLdIcon = asDuotoneIcon(CardsIcon);
|
|
70
|
+
export const customJsonLdIcon = asDuotoneIcon(BracketsCurlyIcon);
|
|
71
|
+
|
|
72
|
+
export const heroIcon = asDuotoneIcon(RocketIcon);
|
|
73
|
+
export const descriptionIcon = asDuotoneIcon(TextAlignLeftIcon);
|
|
74
|
+
export const richTextIcon = asDuotoneIcon(TextTIcon);
|
|
75
|
+
export const contentIcon = asDuotoneIcon(ArticleNyTimesIcon);
|
|
76
|
+
export const gatedContentIcon = asDuotoneIcon(LockKeyIcon);
|
|
77
|
+
|
|
78
|
+
export const pageIcon = asDuotoneIcon(FileTextIcon);
|
|
79
|
+
export const pagesFolderIcon = asDuotoneIcon(BrowsersIcon);
|
|
80
|
+
export const pageFolderIcon = asDuotoneIcon(FolderOpenIcon);
|
|
81
|
+
export const contentFolderIcon = asDuotoneIcon(FolderOpenIcon);
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { cacheLife, cacheTag } from "next/cache";
|
|
2
|
+
import type { QueryParams } from "next-sanity";
|
|
3
|
+
import {
|
|
4
|
+
defineLive,
|
|
5
|
+
type LivePerspective,
|
|
6
|
+
resolvePerspectiveFromCookies,
|
|
7
|
+
resolveVariantFromCookies,
|
|
8
|
+
type StrictDefinedFetchType,
|
|
9
|
+
type StrictDefinedLiveProps,
|
|
10
|
+
} from "next-sanity/live";
|
|
11
|
+
import { cookies, draftMode } from "next/headers";
|
|
12
|
+
import type { ComponentType } from "react";
|
|
13
|
+
import { isSanityConfigured } from "@/lib/integrations/check-integration";
|
|
14
|
+
import { client } from "../client";
|
|
15
|
+
import { sanityToken } from "../env";
|
|
16
|
+
|
|
17
|
+
const isConfigured = isSanityConfigured() && client;
|
|
18
|
+
|
|
19
|
+
// `strict: true` requires perspective/stega at every call site, resolved outside
|
|
20
|
+
// the `'use cache'` boundary so published reads can land in the static shell.
|
|
21
|
+
const liveExports =
|
|
22
|
+
isConfigured && client
|
|
23
|
+
? defineLive({
|
|
24
|
+
client,
|
|
25
|
+
browserToken: sanityToken ?? false,
|
|
26
|
+
serverToken: sanityToken ?? false,
|
|
27
|
+
strict: true,
|
|
28
|
+
})
|
|
29
|
+
: null;
|
|
30
|
+
|
|
31
|
+
export interface DynamicFetchOptions {
|
|
32
|
+
perspective: LivePerspective;
|
|
33
|
+
stega: boolean;
|
|
34
|
+
// Required, not optional: absence is valid, but an optional key lets a call
|
|
35
|
+
// site drop it and serve base content to someone previewing a release.
|
|
36
|
+
variant: string | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// What every static branch reads. Shared so a new field can't be missed at one
|
|
40
|
+
// call site.
|
|
41
|
+
export const PUBLISHED_FETCH_OPTIONS: DynamicFetchOptions = {
|
|
42
|
+
perspective: "published",
|
|
43
|
+
stega: false,
|
|
44
|
+
variant: undefined,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Under `exactOptionalPropertyTypes` an explicit `undefined` variant is a type
|
|
48
|
+
// error, so raw `DynamicFetchOptions` can't be spread into a fetch. That's the
|
|
49
|
+
// point: it forces call sites through here instead of dropping `variant`.
|
|
50
|
+
export const toSanityFetchOptions = ({
|
|
51
|
+
perspective,
|
|
52
|
+
stega,
|
|
53
|
+
variant,
|
|
54
|
+
}: DynamicFetchOptions) => ({
|
|
55
|
+
perspective,
|
|
56
|
+
stega,
|
|
57
|
+
...(variant === undefined ? {} : { variant }),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Null-returning stubs keep the template buildable without Sanity env.
|
|
61
|
+
const fallbackFetch = (async () => ({
|
|
62
|
+
data: null,
|
|
63
|
+
sourceMap: null,
|
|
64
|
+
tags: [],
|
|
65
|
+
})) as unknown as StrictDefinedFetchType;
|
|
66
|
+
|
|
67
|
+
export const sanityFetch: StrictDefinedFetchType =
|
|
68
|
+
liveExports?.sanityFetch ?? fallbackFetch;
|
|
69
|
+
|
|
70
|
+
export const SanityLive: ComponentType<StrictDefinedLiveProps> =
|
|
71
|
+
liveExports?.SanityLive ?? (() => null);
|
|
72
|
+
|
|
73
|
+
// Prerender-safe: `draftMode()` resolves false without bailing out, and
|
|
74
|
+
// `cookies()` is only read once draft mode is on. `strict: true` disables
|
|
75
|
+
// next-sanity's own cookie resolution, so the variant must be read here.
|
|
76
|
+
export async function getDynamicFetchOptions(): Promise<DynamicFetchOptions> {
|
|
77
|
+
const { isEnabled: isDraftMode } = await draftMode();
|
|
78
|
+
if (!isDraftMode)
|
|
79
|
+
return { perspective: "published", stega: false, variant: undefined };
|
|
80
|
+
|
|
81
|
+
const jar = await cookies();
|
|
82
|
+
const [perspective, variant] = await Promise.all([
|
|
83
|
+
resolvePerspectiveFromCookies({ cookies: jar }),
|
|
84
|
+
resolveVariantFromCookies({ cookies: jar }),
|
|
85
|
+
]);
|
|
86
|
+
return { perspective: perspective ?? "drafts", stega: true, variant };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// For `generateStaticParams`: cookies aren't available at build time and stega
|
|
90
|
+
// is never wanted in route params, so both are hardcoded.
|
|
91
|
+
export async function sanityFetchStaticParams<T = unknown>({
|
|
92
|
+
query,
|
|
93
|
+
params = {},
|
|
94
|
+
}: {
|
|
95
|
+
query: string;
|
|
96
|
+
params?: QueryParams;
|
|
97
|
+
}): Promise<{ data: T | null }> {
|
|
98
|
+
"use cache";
|
|
99
|
+
const { data } = await sanityFetch({
|
|
100
|
+
query,
|
|
101
|
+
params,
|
|
102
|
+
...toSanityFetchOptions(PUBLISHED_FETCH_OPTIONS),
|
|
103
|
+
});
|
|
104
|
+
return { data: (data as T | null) ?? null };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Cached read for contexts that render no DOM next to <VisualEditing>. `tags` is
|
|
108
|
+
// required, not optional: the markdown route answers at /api/<slug>.md, which no
|
|
109
|
+
// `revalidatePath` reaches, so an untagged entry is stranded for the ~1y lifetime.
|
|
110
|
+
// Takes the whole options object and overrides `stega` itself, so call sites
|
|
111
|
+
// can't hand-pick fields and drop `variant`.
|
|
112
|
+
export async function sanityFetchCached<T = unknown>({
|
|
113
|
+
query,
|
|
114
|
+
params = {},
|
|
115
|
+
tags,
|
|
116
|
+
...fetchOptions
|
|
117
|
+
}: {
|
|
118
|
+
query: string;
|
|
119
|
+
params?: QueryParams;
|
|
120
|
+
tags: string[];
|
|
121
|
+
} & DynamicFetchOptions): Promise<{ data: T | null }> {
|
|
122
|
+
"use cache";
|
|
123
|
+
const { data } = await sanityFetch({
|
|
124
|
+
query,
|
|
125
|
+
params,
|
|
126
|
+
...toSanityFetchOptions(fetchOptions),
|
|
127
|
+
stega: false,
|
|
128
|
+
});
|
|
129
|
+
const result = (data as T | null) ?? null;
|
|
130
|
+
|
|
131
|
+
if (result === null) {
|
|
132
|
+
// No document, so no publish clears this — and any URL can mint one.
|
|
133
|
+
cacheLife("hours");
|
|
134
|
+
} else {
|
|
135
|
+
// Tagged on a hit only, for that same reason — mirrors `getCachedPage`.
|
|
136
|
+
cacheTag(...tags);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { data: result };
|
|
140
|
+
}
|
|
@@ -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
|
+
];
|