feat(examples-chat): URL-based thread routing — /<mode>/:threadId#500
Merged
Conversation
Shareable, deep-linkable URLs for the canonical demo. Spec at docs/superpowers/specs/2026-05-20-url-thread-routing-design.md. URL becomes the source of truth for the active thread: - /embed → new chat (no persisted thread on first load) - /embed/<id> → load that thread - /popup/<id> → same, in popup mode - /sidebar/<id> → same, in sidebar mode Behaviors: - Pasting an invalid/deleted thread id silently redirects to the bare mode path (replaceUrl: true so back button doesn't loop) - Clicking a thread in the sidenav updates the URL - Switching modes (Embed → Popup) preserves the active thread id - Browser back/forward walks through visited threads - Drops the localStorage threadId persistence — URL IS persistence (browsers reopen last URL); cleaner than fighting URL vs storage Adds LangGraphThreadsAdapter.getThread(id) to validate pasted ids. Treats both 404 (no such thread) and 422 (malformed UUID) as "missing"; rethrows other errors so transport failures aren't masked. 4 new unit tests cover the new method. Verified locally via Chrome MCP: all four flows (bare, valid id, bogus id redirect, mode-switch preserves id) pass end-to-end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
4 tasks
blove
added a commit
that referenced
this pull request
May 21, 2026
…omponent instance (#504) PR #500 added a route entry per (mode, hasThreadId) — six entries total, two per mode. Navigating from `/embed` to `/embed/<id>` was a route CHANGE (different entry), which tore down EmbedMode and remounted it, killing the active stream when the agent auto-created a thread mid-send. Symptom: `examples/chat — e2e` test "failed stream surfaces an alert and the next send recovers" + "core controls expose expected accessible names" both fail because the assistant message never renders (stream died at remount time). Vercel deploy gates on e2e, so prod has been stuck on the pre-#500 bundle. Fix: collapse the per-mode pair into a single route entry via UrlMatcher. Both `/embed` and `/embed/<threadId>` now resolve to the same route, so the component instance survives the navigation and the stream keeps flowing. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 tasks
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.
Summary
Shareable, deep-linkable URLs for the canonical demo. Spec:
docs/superpowers/specs/2026-05-20-url-thread-routing-design.md.URL becomes the source of truth for the active thread:
/embed→ new chat/embed/<id>→ load that thread/popup/<id>//sidebar/<id>→ same, in those modesBehaviors:
replaceUrl: trueso back button doesn't loop)threadIdpersistence — URL IS persistence (browsers reopen last URL); cleaner than fighting URL vs storageNew API
LangGraphThreadsAdapter.getThread(id)— validates pasted ids. Returnsnullfor both 404 (no such thread) AND 422 (malformed UUID); rethrows other errors so transport failures aren't masked.Test plan
getThread()pass (vitest run threads-adapter)nx build langgraph+nx build examples-chat-angulargreen/embedbare → stays bare/embed/<valid-id>→ URL preserved/embed/<bogus>→ redirected to/embed/popup/<same-id>Out of scope (separate)
<title>/ og:* tags for richer link previews🤖 Generated with Claude Code