feat: add experience-toolbar starter example [EXT-7365]#11009
Open
Jared Jolton (jjolton-contentful) wants to merge 5 commits into
Open
feat: add experience-toolbar starter example [EXT-7365]#11009Jared Jolton (jjolton-contentful) wants to merge 5 commits into
Jared Jolton (jjolton-contentful) wants to merge 5 commits into
Conversation
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>
4 tasks
Contributor
⚔️ The Gauntlet — 🛡️ Clean · 4 advisory🤖 AI-powered · your code, through the lanes
No blockers. Security lane is clear, and both AC deviations ( Findings
🤖 Machine-readable findings (for agents){
"tool": "gauntlet",
"schema": "v1",
"reviewed_ref": "8d22108f4",
"verdict": { "blockers": 0, "concerns": 2, "nits": 2, "security": "clean" },
"findings": [
{ "severity": "concern", "location": "test/mocks/mockSdk.ts:16", "lens": "adversarial-review / Hidden Assumptions", "confidence": 93, "claim": "getProperties always resolves immediately and never rejects; loading-spinner and error UI paths untested.", "recommendation": "Add a deferred-promise spec for the spinner and a mockRejectedValueOnce for the error path." },
{ "severity": "concern", "location": "src/locations/ExperienceToolbar.tsx:222", "lens": "code-quality-audit / Gap", "confidence": 80, "claim": "binding branch of formatPropertyValue never exercised; no mock property has a binding.", "recommendation": "Add a mock property with binding {sourceType:'entry',entryId} and assert the rendered 'entry -> ...'." },
{ "severity": "nit", "location": "PR description footer", "lens": "doc-review / Memory rules — no local paths", "confidence": 88, "claim": "Orphaned [EXT-7365]: ?atlOrigin= reference-link leaks an Atlassian smartlink token; inline top link suffices.", "recommendation": "Delete the trailing reference-style definition." },
{ "severity": "nit", "location": "src/locations/ExperienceToolbar.tsx:101", "lens": "code-quality-standards / Rule 5", "confidence": 70, "claim": "Initial getProperties().catch() resets state silently with no log; models silent swallowing in a template.", "recommendation": "Add a code comment or surface a small error note." }
]
}🎮 The Gauntlet · an AI review harness built by Josh C.S. Lewis · reviewed at |
…-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>
eba492e to
45989e8
Compare
…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>
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.
EXT-7365
Summary
examples/experience-toolbarfor the new ExO toolbar App SDK location (LOCATION_EXPERIENCE_TOOLBAR), scaffoldable vianpx create-contentful-app --example experience-toolbar.ExperienceEditorToolbarAppSDKfrom@contentful/app-sdk@4.58.0(first example to pin 4.58.0). Demonstrates every pattern in the ticket AC:sdk.location.is(locations.LOCATION_EXPERIENCE_TOOLBAR)inApp.tsxsdk.exo.contextto tell experience vs. fragment apart (+onContextChanged)sdk.exo.experience.selection.onChange()sdk.exo.experience.getNode(nodeId)and reading its propertiessdk.exo.onUiModeChanged()(form/visual), with graceful form-mode degradationsave()/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 4.58.0 types.vite buildclean.sdk.exois 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/ui-mode/properties render liveGenerated with Claude Code