Skip to content

feat(templates): add page-builder template using @sanity/presets#1084

Open
jordanl17 wants to merge 3 commits into
mainfrom
feat/page-builder-and-preset-template
Open

feat(templates): add page-builder template using @sanity/presets#1084
jordanl17 wants to merge 3 commits into
mainfrom
feat/page-builder-and-preset-template

Conversation

@jordanl17
Copy link
Copy Markdown
Member

@jordanl17 jordanl17 commented May 18, 2026

Description

SAPP-3677 tracks adding a starter Studio template that demonstrates @sanity/presets, a recently released package providing ready-made schema factories (definePage, defineImage, defineCta, defineRichText) for page-builder patterns. The CLI's init flow had no template that exercised the package.

This PR adds a page-builder template using definePage with hero/image/CTA/rich-text blocks, a shared presets registry configured so internal links target Page documents, and a custom hero block composing defineImage and defineCta inline. The picker entry is gated to non-production environments via SANITY_INTERNAL_ENV !== 'production' so the template can be tested in staging before broader release.

Screenshot 2026-05-18 at 15 06 53 Screenshot 2026-05-18 at 15 07 42

What to review

  • scaffoldTemplate.ts - extracted getTemplateChoices(env) as a pure helper so the gating is unit-testable; the --template flag path intentionally bypasses the env check
  • templates/pageBuilder.ts - shape mirrors moviedb.ts (configTemplate + dependencies)
  • schemaTypes/hero.js - references imageBlock rather than image because Sanity reserves image as a primitive type name
  • schemaTypes/index.js - shared presets registry; link.internalTypes: ['page'] cascades to CTAs and rich-text annotations

Testing

Unit tests cover the env-gating in both directions and assert the @sanity/presets dependency is declared. Smoke tested end-to-end by building the CLI, scaffolding a studio with SANITY_INTERNAL_ENV=staging sanity init, and verifying the Page document renders all four block types plus SEO.


Note

Low Risk
Low risk: changes are additive and the new template option is gated to non-production environments, leaving production init behavior unchanged aside from a small refactor of the template choice list.

Overview
Adds a new page-builder template to sanity init that scaffolds a simple page-builder schema using @sanity/presets (page, hero, image, CTA, rich-text) and includes a new template README.

Refactors template selection to use a new getTemplateChoices(getSanityEnv()) helper and gates the page-builder choice to non-production SANITY_INTERNAL_ENV values, with unit tests covering both the env gating and the template’s declared @sanity/presets dependency.

Reviewed by Cursor Bugbot for commit 1bbd83b. Bugbot is set up for automated code reviews on this repo. Configure here.

@claude
Copy link
Copy Markdown

claude Bot commented May 18, 2026

Claude finished @jordanl17's task in 4m 25s —— View job


Review

Scope is well-contained. Comments below are graded by impact.

Minor

packages/@sanity/cli/templates/page-builder/static/.gitkeep is empty. Every other template's static/.gitkeep contains the line Files placed here will be served by the Sanity server under the /static-prefix. Copy that contents in for consistency.

packages/@sanity/cli/templates/page-builder/README.md is the generic blurb. Since this template's whole point is to showcase @sanity/presets, consider one bullet pointing users at the presets docs or briefly noting that the schema is built with createPresetsRegistry so readers know where to look first.

Nits

packages/@sanity/cli/src/actions/init/templates/__tests__/pageBuilder.test.ts:7 only asserts the dependency declaration. Cheap to add an assertion that configTemplate references schemaTypes and the structureTool/visionTool plugins — that's the bit most likely to silently break across template iterations.

packages/@sanity/cli/src/actions/init/__tests__/scaffoldTemplate.test.ts exercises getTemplateChoices in both env directions, but the PR description specifically calls out that --template page-builder should still work in production (env bypass). There's no test pinning that contract — worth a promptForTemplate({template: 'page-builder', unattended: false}) style test so a future refactor doesn't silently re-gate it.

packages/@sanity/cli/src/actions/init/templates/pageBuilder.ts:30 pins @sanity/presets at ^0.4.1. With a 0.x package, ^ is equivalent to ~ (≥0.4.1 <0.5.0). Fine if intentional, but worth confirming you're OK with scaffolded studios sticking on 0.4.x until this string is bumped.

Changeset

feat(templates): add page-builder template using @sanity/presets is fine — the conventional-commit prefix gets parsed by .changeset/changelog.mjs into a scoped bullet, and minor matches a new template behind an env gate. The reviewer feedback from juice49 about inlining factory calls has been addressed by 1bbd83b.


  • Read changed files
  • Review scaffoldTemplate.ts + tests
  • Review pageBuilder template + schemaTypes
  • Check changeset & dependencies
  • Post review
    · Branch

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

📦 Bundle Stats — @sanity/cli

Compared against main (94b25c36)

@sanity/cli

Metric Value vs main (94b25c3)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 10.97 MB +98 B, +0.0%
Bundled (gzip) 2.06 MB +24 B, +0.0%
Import time 820ms -5ms, -0.6%

bin:sanity

Metric Value vs main (94b25c3)
Internal (raw) 1023 B -
Internal (gzip) 486 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 1.96s +1.05s, +114.8% ⚠️

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @sanity/cli-core

Compared against main (94b25c36)

Metric Value vs main (94b25c3)
Internal (raw) 97.0 KB +1.5 KB, +1.6%
Internal (gzip) 22.7 KB +248 B, +1.1%
Bundled (raw) 21.61 MB +1.5 KB, +0.0%
Bundled (gzip) 3.42 MB +263 B, +0.0%
Import time 780ms -11ms, -1.4%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — create-sanity

Compared against main (94b25c36)

Metric Value vs main (94b25c3)
Internal (raw) 908 B -68 B, -7.0%
Internal (gzip) 483 B -24 B, -4.7%
Bundled (raw) 931 B -70 B, -7.0%
Bundled (gzip) 491 B -23 B, -4.5%
Import time ❌ ChildProcess denied: node -
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Coverage Delta

File Statements
packages/@sanity/cli/src/actions/init/scaffoldTemplate.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/init/templates/index.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/init/templates/pageBuilder.ts 100.0% (new)

Comparing 3 changed files against main @ cd110e7c2b0cdad7438f53d958a0831fea2a3773

Overall Coverage

Metric Coverage
Statements 84.3% (+ 0.0%)
Branches 74.3% (+ 0.0%)
Functions 84.2% (±0%)
Lines 84.8% (+ 0.0%)

@jordanl17 jordanl17 requested a review from juice49 May 20, 2026 08:53
Comment thread packages/@sanity/cli/templates/page-builder/schemaTypes/index.js
@jordanl17 jordanl17 marked this pull request as ready for review May 21, 2026 17:01
@jordanl17 jordanl17 requested a review from a team as a code owner May 21, 2026 17:01
@jordanl17 jordanl17 requested a review from binoy14 May 21, 2026 17:02
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1bbd83b. Configure here.

types: schemaTypes,
},
})
`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant configTemplate duplicates the existing default template

Low Severity

The configTemplate string in pageBuilder.ts is functionally identical to the defaultTemplate already defined in createStudioConfig.ts (differing only in plugins array formatting). When a template omits configTemplate, createStudioConfig automatically falls back to defaultTemplate — as blog.ts, clean.ts, and quickstart.ts already do. This duplication adds maintenance burden with no functional benefit; the entire configTemplate constant and its assignment in pageBuilderTemplate can be removed.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1bbd83b. Configure here.

Copy link
Copy Markdown
Contributor

@jwoods02 jwoods02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jordanl17 looking great from AI Growth perspective, I'll let @juice49 approve the specifics of the template code.

Just a quick note that we plan to run a onboarding experiment in the next week or two so please give us a heads up in rd-ai-growth before putting this on in prod in case we're worried it could mess with our xp stats, but should be all good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants