feat: add experience-toolbar starter example [EXT-7365]#11009
Merged
Jared Jolton (jjolton-contentful) merged 11 commits intoJul 9, 2026
Conversation
4 tasks
Contributor
⚔️ The Gauntlet — ✅ 0 Blockers · 2 advisory🤖 AI-powered · your code, through the lanes
Re-review (2026-07-09) covering the six commits since the last pass — canvas-highlight button, the Update (2026-07-09): the README staleness concern is resolved — the stale form-mode gating sentence was removed. Two nits remain open. Findings
🤖 Machine-readable findings (for agents){
"tool": "gauntlet",
"schema": "v1",
"reviewed_ref": "5e27e878f",
"verdict": { "blockers": 0, "concerns": 0, "nits": 2, "security": "clean" },
"findings": [
{ "severity": "nit", "location": "PR description footer", "lens": "doc-review / Memory rules — no local paths", "confidence": 88, "claim": "Orphaned reference-link definition still carries an Atlassian smartlink tracking token into a public repo.", "recommendation": "Delete the trailing reference-style definition; the inline top link suffices." },
{ "severity": "nit", "location": "src/locations/ExperienceToolbar.tsx:233", "lens": "code-quality-audit / Gaps", "confidence": 85, "claim": "formatPropertyValue's binding-type ternary has an unreachable false branch under app-sdk 4.63.1's EntryBinding shape.", "recommendation": "Simplify to a direct entry -> entryId template string; drop the ternary." }
]
}🎮 The Gauntlet · an AI review harness built by Josh C.S. Lewis · reviewed at |
eba492e to
45989e8
Compare
165d7b4 to
473df75
Compare
Wiz Scan Summary
To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension. |
Add a Create Contentful App example demonstrating the new ExO toolbar App SDK location (LOCATION_EXPERIENCE_TOOLBAR), scaffoldable via `npx create-contentful-app --example experience-toolbar`. Typed with ExperienceEditorToolbarAppSDK (@contentful/app-sdk@4.58.0), it demonstrates location detection, reading sdk.exo.context (experience vs. fragment), subscribing to selection changes, reading the selected node's properties via getNode, and reacting to UI mode changes. React-only; no Data Assembly or save/publish (per ticket scope). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-7365]
Address code review on the experience-toolbar starter:
- add a deferred-promise spec asserting the loading spinner
- add a spec for the getProperties rejection path (spinner clears, no table)
- cover the formatPropertyValue binding branch ("entry -> entryId")
- comment the previously-silent getProperties().catch() state reset
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…on [EXT-7365]
4.58.1 reshaped ComponentPropertyDescriptor.binding to the typed `Binding`
union (EntryBinding | ManualBinding), replacing `{ sourceType, entryId }`.
- formatPropertyValue narrows on `binding.type === 'entry'` to read entryId
off the EntryBinding arm (was destructuring the removed `sourceType`).
- Spec uses the EntryBinding fixture shape `{ type, entryId, fieldId }`.
- `area` rendering is unchanged — the discriminator is retained in the SDK.
- Bump @contentful/app-sdk 4.58.0 -> 4.58.1.
Verified: tsc --noEmit clean, 12 tests passing against 4.58.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Track the latest published ExO surface (DA definition-only trim landed in ui-extensions-sdk#2592, widget-renderer synced in experience-packages#3544). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…le [EXT-7497] Bump @contentful/app-sdk floor ^4.59.0 → ^4.60.0 and apply the Exo*→Experience* / sdk.exo→sdk.experiences rename across all example source, test, mock, and documentation files.
…lbar [EXT-7365] README referenced @contentful/app-sdk@4.58.0 (which shipped the old sdk.exo surface) while package.json pins ^4.60.0 (where sdk.experiences first exists), so a reader checking the version would hit a surface mismatch. Bumps both references to 4.60.0 and drops customer-facing "ExO" phrasing per the approved naming (internal-only abbreviation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app-sdk 4.63.1 removes the experience getUiMode()/onUiModeChanged() surface, which this starter demonstrated. Remove the mode badge, the form-mode notice, and the mode-gated highlight button; the highlight action now keys off whether a node is selected. Bump the app-sdk pin to ^4.63.1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
ee14997 to
81cf967
Compare
Josh Lewis (lewisjcs)
approved these changes
Jul 9, 2026
…XT-7365] UI mode tracking was dropped from the example in 35eb56c; the README still claimed the highlight button was disabled in form mode. Co-authored-by: Cursor <cursoragent@cursor.com>
Josh Lewis (lewisjcs)
approved these changes
Jul 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This example targets an App SDK location that's currently in limited/internal availability. The Experience Editor toolbar location isn't generally available yet, so an app built from this example won't be installable in most spaces for the time being. The example is published now so the code and patterns are here to explore and build against ahead of a wider rollout.
Especially curious? If you'd like to try the toolbar location early, reach out to Contentful support — we're happy to talk through early-access options.
EXT-7365
Summary
examples/experience-toolbarfor the new Experience Editor toolbar App SDK location (LOCATION_EXPERIENCE_TOOLBAR), scaffoldable vianpx create-contentful-app --example experience-toolbar.ExperienceEditorToolbarAppSDKfrom@contentful/app-sdk@^4.63.1. Demonstrates every pattern in the ticket AC:sdk.location.is(locations.LOCATION_EXPERIENCE_TOOLBAR)inApp.tsxsdk.experiences.contextto tell experience vs. fragment apart (+onContextChanged)sdk.experiences.experience.selection.onChange()sdk.experiences.experience.getNode(nodeId)and reading its propertiessdk.experiences.experience.selection.highlight()save()/publish()(per ticket excluded scope). Mirrorsexamples/typescriptconventions (Vite + Vitest + Forma 36).Two deviations from the AC (intentional — flagging for review)
--example, not--template. The AC says--template experience-toolbar, but the CLI scaffolds repo examples via--example <name>(resolved fromapps/examples/via the GitHub API onmaster).--templateis a fixed allowlist of framework starters (IGNORED_EXAMPLE_FOLDERS). Delivered as an example, matching howeditor-assignment,page-location, etc. ship. The ticket hedges with "(or equivalent)".app-definition.json. No example in the repo ships a manifest, and the toolbar location is not anEditorInterfacetarget state — visibility is determined solely by whether the location is registered on the app definition. Documented registration viacreate-app-definition/add-locationsin the README and aConfigScreennote instead of inventing a manifest the CLI would strip.Verification status
tsc --noEmitclean against the published app-sdk types.vite buildclean.sdk.experiencesis still rolling out (EXT-7363/EXT-7364). The README states this explicitly. API shapes match the published types exactly.Test plan
npm install && npm run buildinexamples/experience-toolbarsucceedsnpm run test:cipassesnpx create-contentful-app --example experience-toolbarscaffolds a working project (once merged tomaster, since the CLI reads examples from the GitHub API)experience-toolbarlocation, open an experience, and confirm context/selection/properties render liveGenerated with Claude Code