feat(examples/chat): open the demo on a chosen suggestion via ?featured= - #832
Merged
Conversation
Researching the original design before implementing it turned up two problems. ChatComponent has no draft input, so prefilling the composer would mean adding a public input to @threadplane/chat — a semver-relevant change to a commercially licensed published package, for a marketing page. And free text in a URL lets any link display arbitrary chosen text inside the demo UI; the original design guarded against auto-execution but not against defacement. The demo already has the mechanism: welcome-suggestions renders a featured chip chosen by suggestionsForAppMode(). A keyed ?featured=<id> selects from that curated list — no library change, still never auto-sends, and an unknown id falls back to the default instead of rendering what the URL says. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The website's live-demo tabs need each homepage section to frame its own scenario. Without a way to say which, every section would embed the same empty demo under a different heading. The spec originally called for a free-text `?prompt=` that prefills the composer. Researching it first turned up two problems. `ChatComponent` has no draft input, so prefilling would mean adding a public input to `@threadplane/chat` — a semver-relevant change to a commercially licensed published package, for the sake of a marketing page. And free text in a URL lets any link display arbitrary chosen words inside the demo UI; the original design guarded against auto-execution but not against defacement. The demo already had the mechanism. `welcome-suggestions` renders a featured chip chosen by `suggestionsForAppMode()`, so `?featured=<id>` selects from that curated list instead. No library change, and selecting still requires a click. The id is treated as a KEY, never as content: an unrecognised id falls back to the default rather than rendering what the link supplied. That property is mutation-tested — making an unknown id synthesize a suggestion from the URL fails `falls back to the default when the id is unknown` — and verified in a browser: a `?featured=Free%20Bitcoin%20-%20click%20here` link renders the default chip and the string appears nowhere in the DOM. Suggestion ids are explicit rather than derived from labels at runtime, because the website links to them; renaming a label must not silently break a link. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
blove
added a commit
that referenced
this pull request
Aug 26, 2026
…bs (#833) Completes the switcher across all four homepage sections. Render and Ship gain video and code tabs, and every section gains a Live tab that frames the real demo opened on that section's own scenario. Two new clips, recorded against aimock fixtures so a recut reproduces frame-for-frame: - Render — the agent emits a spec and a real contact form mounts as Angular components, `render_a2ui_surface` visible in the tool call. - Ship — a rich markdown answer, then a page reload, and it all comes back. Durability was initially judged unwatchable; it is exactly watchable, and it is the claim that section makes. The live tab uses `?featured=` (merged in #832) so each section opens the demo on its own curated scenario instead of the same empty chat under four headings. `section-media.spec.ts` gains the guard that matters here: it reads the DEMO's actual suggestion list off disk and asserts every `live.featured` id exists there. `?featured=` falls back silently for an unknown id, so a typo would quietly turn a live tab back into the generic demo with nothing else failing. Mutation-tested — a one-character typo fails with `approve -> approve-before-a-destructiv: expected [...] to include`. The active-pane-only guarantee holds at full scale, which was the spec's main technical risk. The built homepage carries 4 tablists, **4** `<video>` elements rather than 12, and **0** iframes — the live iframe is not requested until its tab is selected. Verified in a browser too: clicking Live takes iframes 0 -> 1 and videos 5 -> 4 as the video pane unmounts. Co-authored-by: Claude Opus 5 <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.
Phase 2 groundwork for the homepage medium switcher. The website's live-demo tabs need each section to frame its own scenario — otherwise every section embeds the same empty demo under a different heading, which is the duplication the switcher exists to avoid.
Why not the
?prompt=the spec asked forI researched the specced design before building it, and it was the expensive path:
ChatComponenthas no draft input. Prefilling the composer means adding a public input to@threadplane/chat— a semver-relevant API addition to a commercially licensed published package, requiringnpm run generate-api-docs, for the sake of a marketing page.The demo already had what was needed:
welcome-suggestionsrenders a featured chip chosen bysuggestionsForAppMode(). So?featured=<id>selects from the curated list instead. No library change, and selecting still requires a click.The spec has been updated to record the deviation and why.
The id is a key, never content
An unrecognised id falls back to the default rather than rendering what the link supplied.
Mutation-tested — making an unknown id synthesize a suggestion from the URL fails the guard:
And verified in a browser, not just in tests. Loading
?featured=Free%20Bitcoin%20-%20click%20here:{ "featuredChip": "Generative UI: contact form", "urlTextLeakedAnywhereOnPage": false, "messageCount": 0 }The string appears nowhere in the DOM, and nothing auto-sent.
The happy path works too —
?featured=tell-me-about-coralfeatures that chip,messageCount: 0.Notes
appmode. Re-reading it reactively would let a later navigation reshuffle the chips under someone mid-session.Verification
npx vitest run --config examples/chat/angular/vite.config.mts: 110 passed, 0 failed (7 new)nx lint examples-chat-angular: 0 errorsnx build examples-chat-angular --configuration=production: succeeds🤖 Generated with Claude Code