Skip to content

feat(a2ui-playground): fix URI Too Long, add simulation controls, and polish UI#2555

Merged
Huxpro merged 2 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-playground-improvements
May 3, 2026
Merged

feat(a2ui-playground): fix URI Too Long, add simulation controls, and polish UI#2555
Huxpro merged 2 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-playground-improvements

Conversation

@Huxpro
Copy link
Copy Markdown
Collaborator

@Huxpro Huxpro commented May 3, 2026

Summary

  • Fix "URI Too Long": Serve demo JSONs as static files (demos/*.json via rsbuild output.copy) and reference them with ?demo=<id> (~95 char URLs) instead of inlining base64url payloads (~11,000 chars). All demo QR codes now work on the deployed site.
  • Simulation controls: Add a controls bar (only for known demos) with an ⓘ Simulated info indicator (click-toggleable tooltip) and a speed slider (0.25x–4x) to control streaming replay speed.
  • Lynx for Web fetch fix: render.tsx fetches demo JSONs in the browser context instead of relying on fetch() in Lynx's worker thread (where it's unavailable).
  • LAN IP for QR codes: Replace localhost/127.0.0.1 with the detected LAN IP in QR URLs so phones on the same network can reach the dev server.
  • Native preview short URLs: Use messagesUrl pointing to the static JSON for native preview (LynxExplorer), keeping those QR codes scannable too.
  • QR section polish: Hide when no render URL; show URL + Copy button for web preview; relabel as "Web Preview" vs "Native Preview" with clearer descriptions.
  • AI Chat: Update mock response to direct users to the Demos tab with a clickable link.
  • Sidebar active state: Replace the inset box-shadow left-bar style with a border outline for both Demos and Components pages.

Test plan

  • Select each of the 6 demos — verify all render without "URI Too Long" errors
  • Verify QR codes are generated for both Web Preview and Native Preview
  • Adjust the speed slider and verify streaming speed changes on re-render
  • Click the ⓘ Simulated button — verify tooltip toggles
  • Edit custom JSON and click Render — verify simulation bar disappears
  • Check AI Chat tab — verify mock response links to Demos tab
  • Verify QR URLs use LAN IP instead of localhost in dev
  • Build (pnpm --filter a2ui-playground build) succeeds with dist/demos/*.json present

Summary by CodeRabbit

  • New Features

    • Adjustable playback speed slider for controlling message streaming animations
    • Demo scenario loading and automatic JSON message file support
  • UI/UX Improvements

    • Added simulation information bar with speed controls to preview
    • Separated Web and Native preview sections for clearer layout
    • Refined sidebar styling with improved state indicators

Copilot AI review requested due to automatic review settings May 3, 2026 21:13
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 3, 2026

⚠️ No Changeset found

Latest commit: 2d5c5e5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

The PR adds configurable simulation speed controls to the a2ui-playground, enabling adjustable playback rate for streamed messages via a speed query parameter. It introduces demo JSON file handling through build configuration and runtime fetching, updates the render URL schema to support demo mode, and adds UI controls to toggle simulation info and adjust speed.

Changes

Simulation Speed & Demo File Support

Layer / File(s) Summary
Type & Interface Updates
src/utils/renderUrl.ts, src/render.tsx, src/pages/AIChatPage.tsx
RenderInit adds demoId? and speed? fields; InitData adds speed?; ChatMessage.content broadens from string to string | React.ReactNode.
Demo File Build & Fetch
rsbuild.config.ts, src/render.tsx
Rsbuild copies src/mock/messages/*.json to demos/[name][ext]; render.tsx mounts a useEffect to fetch ./demos/${demo}.json when demo query param is present, merging messages into initData.
Speed Parameter Propagation
src/render.tsx, src/utils/renderUrl.ts
parseInitDataFromQuery parses optional speed query param (finite positive number); buildGlobalPropsFromInitData includes speed in global props; buildRenderUrl sets demo query param for demo mode or base64url-inlines messages, and conditionally adds speed param when defined and not 1.
Core Streaming Delay Logic
lynx-src/App.tsx
Introduces DEFAULT_STREAM_DELAY_MS = 800; computes streamDelay via useMemo as DEFAULT_STREAM_DELAY_MS / speed (or default when missing/invalid); applies streamDelay to both simulated message streaming and action response processing loops; extends useEffect dependency to [effectiveData, streamDelay].
DemosPage Simulation State & Wiring
src/pages/DemosPage.tsx
Adds jsonEdited, speed, showSimTooltip state; computes networkBaseUrl from current page URL with localhost substitution; derives isSimulated state when scenario is known demo and jsonEdited is false; passes demoId, speed, networkBaseUrl to buildRenderUrl and lynxDevUrl query; resets jsonEdited on scenario selection/clear; marks jsonEdited true on editor changes.
UI Controls & Preview Sections
src/pages/DemosPage.tsx, src/pages/AIChatPage.tsx, src/styles.css
Adds simulation info bar with speed slider (visible when isSimulated); updates AIChatPage mock response to include JSX content with demos link and speed info; refactors QR preview from single section to separate "Web Preview" (renderUrl) and "Native Preview" (lynxDevUrl) blocks with dedicated copy buttons; updates sidebar item emphasis from box-shadow to border-based state system.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

  • feat: add A2UI playground init #2472 — This PR extends the a2ui-playground initial implementation by modifying the same core files (render.tsx, App.tsx, DemosPage, renderUrl.ts, rsbuild.config.ts, styles.css) to add simulation speed, streaming delay, and demo query handling.
  • feat: add playground native preview #2530 — Both PRs modify App.tsx and Lynx render/globalProps handling, extending initData and globalProps consumption patterns.
  • feat(website): host A2UI playground at /a2ui #2533 — Related at the build and runtime plumbing level, modifying rsbuild.config.ts (assetPrefix, copyOnBuild), renderUrl.ts (baseUrl handling), and shared playground configuration.

Suggested Reviewers

  • gaoachao
  • HuJean
  • PupilTong

Poem

🐰 A playground now speeds up its dance,
With demos that load at a glance,
Simulation controls take the stage,
Speed sliders turn each streaming page,
Our mock messages leap with sweet grace! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: fixing URI issues, adding simulation controls, and UI polish, all of which are core themes throughout the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 6/8 reviews remaining, refill in 9 minutes and 4 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR expands the A2UI playground deployment and preview flow so demo payloads can be shared with short URLs/QR codes, while adding simulation-related UI controls and some navigation polish. It fits into the website/docs experience by exposing the playground at /a2ui and making both web and native preview links more usable.

Changes:

  • Serve demo payloads as static JSON files and switch preview URLs from inlined payloads to short demo/message references.
  • Add simulation UI in the Demos page, including a tooltip and playback-speed slider, plus QR/link UX refinements.
  • Build and publish the A2UI playground into the website output and add a website nav entry for it.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
website/rspress.config.ts Adds an A2UI entry to the website navigation.
packages/genui/a2ui-playground/src/utils/renderUrl.ts Reworks render URL generation to use render.html, short demo IDs, and optional speed.
packages/genui/a2ui-playground/src/utils/demoUrl.ts Makes the web bundle path relative for subpath deployments.
packages/genui/a2ui-playground/src/styles.css Adds simulation-bar styles and tweaks active-state styling.
packages/genui/a2ui-playground/src/render.tsx Updates query parsing and fetches demo JSON in the browser before initializing <lynx-view>.
packages/genui/a2ui-playground/src/pages/DemosPage.tsx Adds simulation controls, LAN-aware preview URLs, and updated web/native QR presentation.
packages/genui/a2ui-playground/src/pages/AIChatPage.tsx Changes the mock AI response to link users to the Demos tab.
packages/genui/a2ui-playground/rsbuild.config.ts Copies demo JSON assets into build output and includes www assets in production builds.
packages/genui/a2ui-playground/lynx-src/App.tsx Adds URL-driven streaming speed support inside the Lynx runtime.
.github/workflows/workflow-website.yml Builds the A2UI playground and copies it into the website artifact.
Comments suppressed due to low confidence (1)

packages/genui/a2ui-playground/src/pages/DemosPage.tsx:226

  • When the dev payload store rewrites the render URL to messagesUrl/actionMocksUrl, it drops the new speed query parameter. In local dev this async rewrite overwrites the earlier URL from buildRenderUrl(), so the slider silently falls back to 1x after the fetch completes.
          if (messagesUrlAbs) {
            const r = new URL('render.html', networkBaseUrl);
            r.searchParams.set('protocol', protocol);
            r.searchParams.set('demoUrl', DEFAULT_DEMO_URL);
            r.searchParams.set('messagesUrl', messagesUrlAbs);
            if (actionMocksUrlAbs && actionMocks) {
              r.searchParams.set('actionMocksUrl', actionMocksUrlAbs);
            }
            setRenderUrl(r.toString());

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +136 to +145
const isKnownDemo = ALL_SCENARIOS.some((s) => s.id === scenario?.id);
setIsSimulated(isKnownDemo);
const url = buildRenderUrl(
{ protocol, demoUrl: DEFAULT_DEMO_URL, messages: parsed, actionMocks },
origin,
{
protocol,
demoUrl: DEFAULT_DEMO_URL,
messages: parsed,
actionMocks,
demoId: isKnownDemo ? scenario!.id : undefined,
speed,
Comment on lines 153 to 173
const seq = ++lynxUrlSeqRef.current;
if (rspeedyDevUrl) {
const uInline = new URL(rspeedyDevUrl);
uInline.searchParams.set('messages', JSON.stringify(parsed));
if (actionMocks) {
uInline.searchParams.set('actionMocks', JSON.stringify(actionMocks));
if (isKnownDemo) {
// Known demo: point to the static JSON served by the rsbuild dev server.
// Native Lynx supports fetch, so App.tsx will load it via messagesUrl.
const demosOrigin = new URL(networkBaseUrl).origin;
uInline.searchParams.set(
'messagesUrl',
`${demosOrigin}/demos/${scenario!.id}.json`,
);
} else {
uInline.searchParams.set('messages', JSON.stringify(parsed));
if (actionMocks) {
uInline.searchParams.set(
'actionMocks',
JSON.stringify(actionMocks),
);
}
}
setLynxDevUrl(uInline.toString());
Comment on lines 54 to +59
const messages = params.get('messages');
const actionMocks = params.get('actionMocks');
const actionMocksUrl = params.get('actionMocksUrl');
const demo = params.get('demo');

if (!protocol && !messagesUrl && !messages && !demoUrl) {
if (!protocol && !messagesUrl && !messages && !demoUrl && !demo) {
? 'QR code unavailable. Open this link with LynxExplorer instead.'
: 'Scan with LynxExplorer to load the rspeedy dev bundle.'}
{/* QR Code Section — only shown when there's a render URL */}
{renderUrl || lynxDevUrl
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx`:
- Around line 156-173: The native preview URL built in DemosPage.tsx omits the
selected replay speed, so add the current speed query param to uInline before
calling setLynxDevUrl: call uInline.searchParams.set('speed', String(speed)) (or
the actual slider variable name in scope) in both the isKnownDemo branch and the
else branch where messages/actionMocks are set, and do the same for the other
duplicate URL construction block (the similar logic around lines 205-214) so
Native Preview reads the slider-controlled speed.
- Around line 135-145: isKnownDemo currently returns true whenever a sidebar
scenario is selected, causing demoId to be sent even after the user edits the
JSON; change the check so a scenario is treated as "known" only if a scenario is
selected AND the current parsed messages match the scenario's original/default
messages (or a "pristine" flag that indicates the JSON hasn't been edited).
Concretely, update the isKnownDemo calculation (replace the
ALL_SCENARIOS.some(...) usage) to: 1) find the scenario by id (use scenario!.id
or find in ALL_SCENARIOS) and 2) compare parsed (the messages payload) to that
scenario's default messages (or consult a local isPristineJson boolean you set
when the user edits the editor). Then use that result for setIsSimulated and
pass demoId to buildRenderUrl only when the messages are unchanged (i.e., truly
a known demo).

In `@packages/genui/a2ui-playground/src/render.tsx`:
- Around line 57-60: The parser in render.tsx currently reads demo but ignores
the speed query; capture the speed via params.get('speed') (or parse it to a
number) and propagate it into the Lynx initialization payload by adding it to
the initData/globalProps object passed to the Lynx init routine (the same object
where messages/messagesUrl/demoUrl/demo are set). Ensure the symbol names
involved are updated: read speed alongside demo, then include that speed value
in the initData/globalProps that the Lynx init/render function consumes so web
preview honors ?speed=....
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 23086db1-6bea-45cc-b4bd-03b277a7fbb9

📥 Commits

Reviewing files that changed from the base of the PR and between f706c3a and 971617c.

📒 Files selected for processing (10)
  • .github/workflows/workflow-website.yml
  • packages/genui/a2ui-playground/lynx-src/App.tsx
  • packages/genui/a2ui-playground/rsbuild.config.ts
  • packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/render.tsx
  • packages/genui/a2ui-playground/src/styles.css
  • packages/genui/a2ui-playground/src/utils/demoUrl.ts
  • packages/genui/a2ui-playground/src/utils/renderUrl.ts
  • website/rspress.config.ts

Comment thread packages/genui/a2ui-playground/src/pages/DemosPage.tsx Outdated
Comment thread packages/genui/a2ui-playground/src/pages/DemosPage.tsx
Comment thread packages/genui/a2ui-playground/src/render.tsx
Huxpro added 2 commits May 3, 2026 23:28
… polish UI

- Fix "URI Too Long" error for large demos by serving demo JSONs as
  static files (demos/*.json) and referencing them via ?demo=<id>
  instead of inlining base64url payloads in the URL. Reduces render
  URLs from ~11,000 chars to ~95 chars.

- Add simulation controls bar (visible only for known demos):
  - "Simulated" info indicator with click-to-toggle tooltip explaining
    pre-recorded data
  - Speed slider (0.25x–4x) to control streaming replay speed

- Fix fetch crash in Lynx for Web worker thread by having render.tsx
  fetch demo JSONs in the browser context instead of the Lynx worker

- Use LAN IP instead of localhost for QR code URLs so phones can
  reach the dev server

- Use messagesUrl for native preview (LynxExplorer) to keep QR codes
  scannable for all demos

- Improve QR section: hide when no render URL, show URL + Copy button
  for web preview, clarify "Web Preview" vs "Native Preview" labels

- Update AI Chat mock response to direct users to the Demos tab

- Polish sidebar active state (border outline instead of inset bar)
  for both Demos and Components pages
- Track JSON edits so custom changes use inline payload instead of
  demoId (fixes isKnownDemo override after user edits)
- Forward speed param through render.tsx initData/globalProps so web
  preview honors the slider
- Add speed param to native preview URL for LynxExplorer
- Clear lynxDevUrl on Clear button to avoid stale QR codes
@Huxpro Huxpro force-pushed the Huxpro/a2ui-playground-improvements branch from 933044d to 2d5c5e5 Compare May 3, 2026 21:28
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/genui/a2ui-playground/src/pages/DemosPage.tsx (2)

223-231: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve speed when swapping the web preview to payload-store URLs.

This branch rebuilds render.html from scratch and never re-adds the selected speed, so once __a2ui_payload succeeds the web preview falls back to 1x even though buildRenderUrl() and render.tsx both support that query param.

Suggested fix
           if (messagesUrlAbs) {
             const r = new URL('render.html', networkBaseUrl);
             r.searchParams.set('protocol', protocol);
             r.searchParams.set('demoUrl', DEFAULT_DEMO_URL);
             r.searchParams.set('messagesUrl', messagesUrlAbs);
+            if (speed !== 1) {
+              r.searchParams.set('speed', String(speed));
+            }
             if (actionMocksUrlAbs && actionMocks) {
               r.searchParams.set('actionMocksUrl', actionMocksUrlAbs);
             }
             setRenderUrl(r.toString());
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx` around lines 223 -
231, The branch that constructs the preview URL when messagesUrlAbs is present
rebuilds render.html but omits the current speed query param, causing playback
to reset to 1x; update the URL construction in the messagesUrlAbs branch (the
block that creates new URL('render.html', networkBaseUrl) and calls
setRenderUrl) to preserve the existing speed value by reading the current speed
from the existing render URL or state (the same param used by
buildRenderUrl/render.tsx) and set it on r.searchParams (e.g.,
r.searchParams.set('speed', currentSpeed)) before calling setRenderUrl so the
selected speed persists when switching to payload-store URLs.

242-247: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

This bootstrap effect resets the preview on unrelated state changes.

Because doRender depends on jsonEdited, speed, networkBaseUrl, and rspeedyDevUrl, this effect re-runs whenever any of those change and always re-renders ALL_SCENARIOS[0]. A simple repro is: select another scenario, move the speed slider, and the preview jumps back to the first demo.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx` around lines 242 -
247, The effect at useEffect currently depends on doRender, causing re-renders
when unrelated state used by doRender changes; change the dependency list so
this bootstrap only runs on mount (use an empty array) or when scenarios change
(use [ALL_SCENARIOS] or [ALL_SCENARIOS[0]]), keeping the body that formats
messages with formatJson and calls doRender( json, ALL_SCENARIOS[0] ); remove
doRender from the deps to prevent the preview jumping back to the first
scenario.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx`:
- Around line 136-147: The code treats any entry in ALL_SCENARIOS as a
short/served demo which causes links for dynamic presets to point to
non-existent static JSONs; change the isKnownDemo check to only consider
STATIC_DEMOS (and still require !jsonEdited) so demoId is only set for actually
published static demos, and update the same logic in the second occurrence;
locate and modify the checks around isKnownDemo (used with
buildRenderUrl/demoId) to use STATIC_DEMOS.some(s => s.id === scenario?.id)
instead of ALL_SCENARIOS.

---

Outside diff comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx`:
- Around line 223-231: The branch that constructs the preview URL when
messagesUrlAbs is present rebuilds render.html but omits the current speed query
param, causing playback to reset to 1x; update the URL construction in the
messagesUrlAbs branch (the block that creates new URL('render.html',
networkBaseUrl) and calls setRenderUrl) to preserve the existing speed value by
reading the current speed from the existing render URL or state (the same param
used by buildRenderUrl/render.tsx) and set it on r.searchParams (e.g.,
r.searchParams.set('speed', currentSpeed)) before calling setRenderUrl so the
selected speed persists when switching to payload-store URLs.
- Around line 242-247: The effect at useEffect currently depends on doRender,
causing re-renders when unrelated state used by doRender changes; change the
dependency list so this bootstrap only runs on mount (use an empty array) or
when scenarios change (use [ALL_SCENARIOS] or [ALL_SCENARIOS[0]]), keeping the
body that formats messages with formatJson and calls doRender( json,
ALL_SCENARIOS[0] ); remove doRender from the deps to prevent the preview jumping
back to the first scenario.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 89f2f17d-3673-4207-bb9c-a282a16404b6

📥 Commits

Reviewing files that changed from the base of the PR and between 971617c and 933044d.

📒 Files selected for processing (2)
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/render.tsx

Comment on lines +136 to +147
// Use short demo ID only when the user hasn't edited the JSON.
const isKnownDemo = !jsonEdited
&& ALL_SCENARIOS.some((s) => s.id === scenario?.id);
setIsSimulated(isKnownDemo);
const url = buildRenderUrl(
{ protocol, demoUrl: DEFAULT_DEMO_URL, messages: parsed, actionMocks },
baseUrl,
{
protocol,
demoUrl: DEFAULT_DEMO_URL,
messages: parsed,
actionMocks,
demoId: isKnownDemo ? scenario!.id : undefined,
speed,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Only treat STATIC_DEMOS as short-URL demos.

isKnownDemo currently matches every ALL_SCENARIOS entry, but packages/genui/a2ui-playground/rsbuild.config.ts:48-53 only publishes static message JSONs under demos/[name].json. Any DYNAMIC_PRESETS selection will therefore produce ?demo=... / messagesUrl=... links to files that 404, breaking both previews until the user edits JSON.

Suggested fix
-      const isKnownDemo = !jsonEdited
-        && ALL_SCENARIOS.some((s) => s.id === scenario?.id);
+      const isKnownDemo = !jsonEdited
+        && scenario !== undefined
+        && STATIC_DEMOS.some((s) => s.id === scenario.id);

Also applies to: 161-168

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx` around lines 136 -
147, The code treats any entry in ALL_SCENARIOS as a short/served demo which
causes links for dynamic presets to point to non-existent static JSONs; change
the isKnownDemo check to only consider STATIC_DEMOS (and still require
!jsonEdited) so demoId is only set for actually published static demos, and
update the same logic in the second occurrence; locate and modify the checks
around isKnownDemo (used with buildRenderUrl/demoId) to use STATIC_DEMOS.some(s
=> s.id === scenario?.id) instead of ALL_SCENARIOS.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/genui/a2ui-playground/src/pages/DemosPage.tsx (2)

242-247: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Changing speed resets the preview to the first scenario.

This effect depends on doRender, which is recreated whenever speed changes (line 239). When the user adjusts the speed slider while viewing scenario #3, the effect fires and re-renders with ALL_SCENARIOS[0], unexpectedly jumping back to the first scenario.

Consider either:

  1. Making this a mount-only effect with an empty dependency array (lint-ignore the exhaustive-deps warning with a comment explaining the intent), or
  2. Adding a separate effect for speed changes that re-renders the current scenario.
Option 1: Mount-only effect
  useEffect(() => {
    if (ALL_SCENARIOS[0]) {
      const json = formatJson(ALL_SCENARIOS[0].messages);
      doRender(json, ALL_SCENARIOS[0]);
    }
+   // eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally run only on mount
-  }, [doRender]);
+  }, []);
Option 2: Separate effect for speed changes
+ // Re-render current scenario when speed changes
+ useEffect(() => {
+   if (currentScenario) {
+     doRender(customJson, currentScenario);
+   }
+   // eslint-disable-next-line react-hooks/exhaustive-deps -- only trigger on speed change
+ }, [speed]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx` around lines 242 -
247, The useEffect currently depends on doRender (which is recreated when speed
changes), causing the preview to reset to ALL_SCENARIOS[0] whenever speed
changes; fix by either making this effect run only on mount (remove doRender
from deps, add an eslint-disable-next-line comment and a short comment
explaining it's intentionally mount-only) so initial scenario is rendered once,
or implement a second effect that listens to speed changes and calls doRender
with the currently selected scenario (track currentScenario via state or ref and
use that in the speed-effect) so adjusting speed re-renders the active scenario
without jumping back to ALL_SCENARIOS[0]; reference doRender, ALL_SCENARIOS,
speed, and the existing useEffect when applying the change.

211-218: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Speed parameter lost when switching to reference-based URLs.

The async block creates a fresh URL from rspeedyDevUrl and overwrites lynxDevUrl, discarding the speed param set earlier at lines 158-160. Native preview will use default speed when reference-based URLs are available.

Proposed fix
          // Lynx dev bundle URL: drop inline messages, use references.
          const u = new URL(rspeedyDevUrl);
+         if (speed !== 1) {
+           u.searchParams.set('speed', String(speed));
+         }
          if (messagesUrlAbs) u.searchParams.set('messagesUrl', messagesUrlAbs);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx` around lines 211 -
218, When building the reference-based URL you currently replace lynxDevUrl with
a fresh URL from rspeedyDevUrl and drop the previously-set speed parameter;
preserve that by copying the speed into the new URL before calling
setLynxDevUrl. Concretely, after creating u = new URL(rspeedyDevUrl) (and before
setLynxDevUrl), if a local speed variable (the one set earlier around lines
158-160) exists set u.searchParams.set('speed', String(speed)); if you don’t
have that variable available, parse the current lynxDevUrl (new
URL(lynxDevUrl).searchParams.get('speed')) and, if present, set it on u; then
proceed to set messages/actionMocks params and call setLynxDevUrl(u.toString()).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.tsx`:
- Around line 242-247: The useEffect currently depends on doRender (which is
recreated when speed changes), causing the preview to reset to ALL_SCENARIOS[0]
whenever speed changes; fix by either making this effect run only on mount
(remove doRender from deps, add an eslint-disable-next-line comment and a short
comment explaining it's intentionally mount-only) so initial scenario is
rendered once, or implement a second effect that listens to speed changes and
calls doRender with the currently selected scenario (track currentScenario via
state or ref and use that in the speed-effect) so adjusting speed re-renders the
active scenario without jumping back to ALL_SCENARIOS[0]; reference doRender,
ALL_SCENARIOS, speed, and the existing useEffect when applying the change.
- Around line 211-218: When building the reference-based URL you currently
replace lynxDevUrl with a fresh URL from rspeedyDevUrl and drop the
previously-set speed parameter; preserve that by copying the speed into the new
URL before calling setLynxDevUrl. Concretely, after creating u = new
URL(rspeedyDevUrl) (and before setLynxDevUrl), if a local speed variable (the
one set earlier around lines 158-160) exists set u.searchParams.set('speed',
String(speed)); if you don’t have that variable available, parse the current
lynxDevUrl (new URL(lynxDevUrl).searchParams.get('speed')) and, if present, set
it on u; then proceed to set messages/actionMocks params and call
setLynxDevUrl(u.toString()).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a439faa4-7f7f-4a5f-9887-88fff00d822f

📥 Commits

Reviewing files that changed from the base of the PR and between 933044d and 2d5c5e5.

📒 Files selected for processing (7)
  • packages/genui/a2ui-playground/lynx-src/App.tsx
  • packages/genui/a2ui-playground/rsbuild.config.ts
  • packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/render.tsx
  • packages/genui/a2ui-playground/src/styles.css
  • packages/genui/a2ui-playground/src/utils/renderUrl.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/genui/a2ui-playground/lynx-src/App.tsx
  • packages/genui/a2ui-playground/src/render.tsx
  • packages/genui/a2ui-playground/rsbuild.config.ts
  • packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
  • packages/genui/a2ui-playground/src/styles.css

@codecov
Copy link
Copy Markdown

codecov Bot commented May 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@Huxpro Huxpro merged commit 4fc29ee into lynx-family:main May 3, 2026
38 of 39 checks passed
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 3, 2026

Merging this PR will degrade performance by 10.63%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 80 untouched benchmarks
⏩ 26 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
transform 1000 view elements 40 ms 44.7 ms -10.63%

Comparing Huxpro:Huxpro/a2ui-playground-improvements (2d5c5e5) with main (f706c3a)

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 3, 2026

React External

#877 Bundle Size — 680.82KiB (0%).

2d5c5e5(current) vs f706c3a main#867(baseline)

Bundle metrics  no changes
                 Current
#877
     Baseline
#867
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#877
     Baseline
#867
No change  Other 680.82KiB 680.82KiB

Bundle analysis reportBranch Huxpro:Huxpro/a2ui-playground-im...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 3, 2026

Web Explorer

#9335 Bundle Size — 900.03KiB (0%).

2d5c5e5(current) vs f706c3a main#9325(baseline)

Bundle metrics  no changes
                 Current
#9335
     Baseline
#9325
No change  Initial JS 44.46KiB 44.46KiB
No change  Initial CSS 2.22KiB 2.22KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 9 9
No change  Assets 11 11
No change  Modules 229 229
No change  Duplicate Modules 11 11
No change  Duplicate Code 27.28% 27.28%
No change  Packages 10 10
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#9335
     Baseline
#9325
No change  JS 495.9KiB 495.9KiB
No change  Other 401.92KiB 401.92KiB
No change  CSS 2.22KiB 2.22KiB

Bundle analysis reportBranch Huxpro:Huxpro/a2ui-playground-im...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 3, 2026

React Example (Element Template)

#30 Bundle Size — 198.61KiB (0%).

2d5c5e5(current) vs f706c3a main#20(baseline)

Bundle metrics  Change 2 changes
                 Current
#30
     Baseline
#20
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
Change  Modules 80(+3.9%) 77
No change  Duplicate Modules 23 23
Change  Duplicate Code 40.48%(-0.12%) 40.53%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#30
     Baseline
#20
No change  IMG 145.76KiB 145.76KiB
No change  Other 52.85KiB 52.85KiB

Bundle analysis reportBranch Huxpro:Huxpro/a2ui-playground-im...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 3, 2026

React MTF Example

#894 Bundle Size — 196.68KiB (0%).

2d5c5e5(current) vs f706c3a main#884(baseline)

Bundle metrics  no changes
                 Current
#894
     Baseline
#884
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 174 174
No change  Duplicate Modules 66 66
No change  Duplicate Code 44.05% 44.05%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#894
     Baseline
#884
No change  IMG 111.23KiB 111.23KiB
No change  Other 85.45KiB 85.45KiB

Bundle analysis reportBranch Huxpro:Huxpro/a2ui-playground-im...Project dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented May 3, 2026

React Example

#7762 Bundle Size — 225.52KiB (0%).

2d5c5e5(current) vs f706c3a main#7752(baseline)

Bundle metrics  no changes
                 Current
#7762
     Baseline
#7752
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 180 180
No change  Duplicate Modules 69 69
No change  Duplicate Code 44.54% 44.54%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#7762
     Baseline
#7752
No change  IMG 145.76KiB 145.76KiB
No change  Other 79.77KiB 79.77KiB

Bundle analysis reportBranch Huxpro:Huxpro/a2ui-playground-im...Project dashboard


Generated by RelativeCIDocumentationReport issue

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants