feat: BetaBloom feedback — seekable timeline, Ultra Fast speed, algorithm use-case tips, and landing page critical-path improvements - #216
Conversation
- Route-level code splitting: lazy-load app pages (VisualizerApp, panels, Monaco, Pyodide, Remotion) so the landing page ships a smaller initial bundle; Suspense fallback spinner for lazy routes - Cache GitHub repo data in localStorage (24h TTL) and defer refresh to idle, removing the render-blocking GitHub API chain from load - Extract cache-first GitHub data into githubRepoService with fallback and stale-while-revalidate handling - Target es2022 to drop legacy browser transforms - Preload the Inter latin woff2 in built index.html via a closeBundle plugin (rolldown-vite emits HTML outside generateBundle) - Mark decorative social icons aria-hidden (Google sign-in, YouTube, Instagram, TikTok) - Serve /llms.txt as markdown to LLM crawlers in the worker - Restore the URL global stub in useVideoExporter tests to fix a flaky singleFork coverage failure
|
Warning Review limit reached
Next review available in: 25 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThe PR adds seekable visualization timelines, algorithm use-case guidance, an algorithm tip toast, a fifth animation speed, cached GitHub metadata loading, lazy routes, font preloading, and direct ChangesVisualizer playback and guidance
Application delivery
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant ControlPanel
participant VisualizerApp
participant useVisualization
participant SignInPrompt
User->>ControlPanel: Select a timeline step
ControlPanel->>VisualizerApp: Call onSeek(index)
VisualizerApp->>useVisualization: Call seekToStep(index)
useVisualization-->>VisualizerApp: Update the selected step
User->>ControlPanel: Activate locked seeking
ControlPanel->>VisualizerApp: Call onGatedFeatureClick("timeline_scrub")
VisualizerApp->>SignInPrompt: Open the sign-in prompt
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Preview for Bayan Flow Staging ready!
Preview alias |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/pages/VisualizerApp.test.jsx (1)
92-96: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMake the timeline mock require available steps.
The sorting fixture has
totalSteps: 0, but the mock rendersseek-to-step-2andgated-seekwhenever the callbacks exist. Both timeline tests can therefore pass without a timeline.Render these controls only when
totalSteps > 0. Then switch the tests to the pathfinding fixture, which has two steps, or provide a dedicated sorting fixture with steps.Also applies to: 308-340, 819-828, 885-893
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/VisualizerApp.test.jsx` around lines 92 - 96, Update the timeline mock in VisualizerApp.test.jsx so seek-to-step-2 and gated-seek controls render only when totalSteps > 0, preventing tests from passing without available steps. Adjust the affected timeline tests to use the pathfinding fixture with two steps, or add steps to a dedicated sorting fixture while preserving the existing sorting coverage.src/pages/VisualizerApp.jsx (1)
637-656: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix the stale algorithm key used for the tip toast during cross-category favorite navigation.
In
handleFavoriteNavigate, whencategory !== algorithmType, the code callsapplyCategorySwitch(category)beforesetSelectedAlgorithmsupdatesselectedAlgorithms[category]toalgorithmKey. InsideapplyCategorySwitch,maybeShowAlgorithmTip(selectedAlgorithms[newType])reads the old selection for that category, not the algorithm the user is navigating to.This call marks the wrong algorithm key as "shown" in
shownAlgorithmTipsRef, even though its tip is immediately overwritten by the second, correctmaybeShowAlgorithmTip(algorithmKey)call. The wrong algorithm then never gets a tip shown later in the session, even though it was never actually displayed.Pass the target algorithm key into
applyCategorySwitchso it does not depend on state that has not updated yet.🐛 Proposed fix to pass the correct algorithm key explicitly
- const applyCategorySwitch = newType => { + const applyCategorySwitch = (newType, tipAlgorithmKey) => { const cfg = CATEGORY_CONFIG[newType]; if (cfg.sizeBinding === 'array') { const searchingKey = selectedAlgorithms[ALGORITHM_TYPES.SEARCHING]; if ( newType !== ALGORITHM_TYPES.SEARCHING || !isNodeLinkSearchingAlgorithm(searchingKey) ) { const raw = cfg.generateData(arraySize); setArray( newType === ALGORITHM_TYPES.SORTING ? finalizeSortingInputArray(raw, sortOrder) : raw ); } } setAlgorithmType(newType); visualizationMap[newType]?.reset(); - maybeShowAlgorithmTip(selectedAlgorithms[newType]); + maybeShowAlgorithmTip(tipAlgorithmKey ?? selectedAlgorithms[newType]); }; const handleFavoriteNavigate = (category, algorithmKey) => { if (category !== algorithmType) { - applyCategorySwitch(category); + applyCategorySwitch(category, algorithmKey); + } else { + maybeShowAlgorithmTip(algorithmKey); } setSelectedAlgorithms(prev => ({ ...prev, [category]: algorithmKey, })); - maybeShowAlgorithmTip(algorithmKey); visualizationMap[category]?.reset(); };Also applies to: 658-668
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/VisualizerApp.jsx` around lines 637 - 656, Update applyCategorySwitch to accept an optional target algorithm key and use it when calling maybeShowAlgorithmTip, falling back to selectedAlgorithms[newType] only when no target is supplied. In handleFavoriteNavigate, pass algorithmKey when switching categories so the tip tracking uses the destination algorithm rather than stale selected state.
🧹 Nitpick comments (2)
src/services/githubRepoService.test.js (1)
93-109: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for a non-OK repo response.
The current tests cover full success and full network failure, but not the case where
repoResponse.okisfalsewhilereleaseResponse.okistrue(or vice versa). That branch infetchGitHubRepo(lines 88-97 ofgithubRepoService.js) keeps fallbackurl/fullName/stars/forksbut still applies the parsed release tag, and it currently has no direct test.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/githubRepoService.test.js` around lines 93 - 109, Add a test alongside the existing cache-miss coverage that exercises fetchGitHubRepo when one response is non-OK and the other is OK. Assert the result preserves fallback url, fullName, stars, and forks while applying the parsed release versionTag, and verify the expected persistence/cache behavior using the existing helpers and symbols.src/services/githubRepoService.js (1)
110-126: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winDuplicate concurrent GitHub API calls from Footer and GitHubRepoBadge.
loadGitHubRepoDatahas no in-flight request cache, and bothFooter.jsxandGitHubRepoBadge.jsxindependently run the same cache-check-then-idle-load logic. When the cache is stale or missing and both components mount on the same page, each triggers its own call toloadGitHubRepoData(), doubling the GitHub API requests (repo + release) against the 60 requests/hour unauthenticated limit, and duplicating the same effect logic across two files.
src/services/githubRepoService.js#L110-L126: cache the in-flight promise (module-level singleton, cleared on settle) insideloadGitHubRepoDataso concurrent callers share one fetch instead of issuing separate requests.src/components/Footer.jsx#L13-L41: once the service dedups in-flight requests, this effect is safe as-is; optionally extract this cache-read/idle-load logic into a shared hook (e.g.,useGitHubRepoData) to remove the duplication withGitHubRepoBadge.jsx.src/components/GitHubRepoBadge.jsx#L47-L67: same as above — extract the shared hook once the service-level dedup is in place.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/githubRepoService.js` around lines 110 - 126, Prevent duplicate concurrent GitHub requests by adding a module-level in-flight promise singleton used by loadGitHubRepoData; return it to concurrent callers and clear it when the request settles, while preserving existing cache, fallback, and error behavior. In src/services/githubRepoService.js lines 110-126, implement the service-level deduplication. In src/components/Footer.jsx lines 13-41 and src/components/GitHubRepoBadge.jsx lines 47-67, no direct change is required once deduplication is added; optionally replace their duplicated cache-read/idle-load effects with a shared useGitHubRepoData hook.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@AGENTS.md`:
- Line 70: Update the speed-policy documentation in AGENTS.md to state that Free
users have all five speed presets and align Anonymous MEDIUM with the defined
3000ms value; only retain 4800ms if explicitly documented as an Anonymous-only
override.
In `@src/services/githubRepoService.js`:
- Around line 78-108: Update fetchGitHubRepo to bound both requests with a fixed
timeout using an AbortController or the project’s existing timeout utility.
Apply the same timeout to the repository and latest-release fetch calls, ensure
timeout failures are handled so the function returns the existing fallback data,
and preserve the current successful-response parsing behavior.
In `@src/test/setup.js`:
- Line 73: Align the shared ANIMATION_SPEEDS mock in src/test/setup.js:73-73
with the complete production values, including ULTRA_FAST: 350, without
accelerated values outside timing-specific tests. Update
src/config/settingsConfig.test.jsx:65-73 to assert the production values
directly and remove the expectation that reads values from mocked constants.
In `@worker/index.js`:
- Around line 66-75: Preserve the status from env.ASSETS.fetch in the /llms.txt
handler by passing llmsResponse.status when constructing the new Response, so
missing or failed assets retain their non-success status. Add a test in
worker/index.test.js covering a missing /llms.txt asset and asserting the
response status.
---
Outside diff comments:
In `@src/pages/VisualizerApp.jsx`:
- Around line 637-656: Update applyCategorySwitch to accept an optional target
algorithm key and use it when calling maybeShowAlgorithmTip, falling back to
selectedAlgorithms[newType] only when no target is supplied. In
handleFavoriteNavigate, pass algorithmKey when switching categories so the tip
tracking uses the destination algorithm rather than stale selected state.
In `@src/pages/VisualizerApp.test.jsx`:
- Around line 92-96: Update the timeline mock in VisualizerApp.test.jsx so
seek-to-step-2 and gated-seek controls render only when totalSteps > 0,
preventing tests from passing without available steps. Adjust the affected
timeline tests to use the pathfinding fixture with two steps, or add steps to a
dedicated sorting fixture while preserving the existing sorting coverage.
---
Nitpick comments:
In `@src/services/githubRepoService.js`:
- Around line 110-126: Prevent duplicate concurrent GitHub requests by adding a
module-level in-flight promise singleton used by loadGitHubRepoData; return it
to concurrent callers and clear it when the request settles, while preserving
existing cache, fallback, and error behavior. In
src/services/githubRepoService.js lines 110-126, implement the service-level
deduplication. In src/components/Footer.jsx lines 13-41 and
src/components/GitHubRepoBadge.jsx lines 47-67, no direct change is required
once deduplication is added; optionally replace their duplicated
cache-read/idle-load effects with a shared useGitHubRepoData hook.
In `@src/services/githubRepoService.test.js`:
- Around line 93-109: Add a test alongside the existing cache-miss coverage that
exercises fetchGitHubRepo when one response is non-OK and the other is OK.
Assert the result preserves fallback url, fullName, stars, and forks while
applying the parsed release versionTag, and verify the expected
persistence/cache behavior using the existing helpers and symbols.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f6308917-fb7e-4ace-bec4-a41dbf63067c
📒 Files selected for processing (35)
AGENTS.mddocs/AGENTS_REFERENCE.mddocs/ARCHITECTURE.mdpublic/markdown/app.mdsrc/AppRoutes.jsxsrc/AppRoutes.test.jsxsrc/components/AlgorithmTipToast.jsxsrc/components/AlgorithmTipToast.test.jsxsrc/components/ControlPanel.jsxsrc/components/ControlPanel.test.jsxsrc/components/Footer.jsxsrc/components/GitHubRepoBadge.jsxsrc/components/GitHubRepoBadge.test.jsxsrc/components/SettingsPanel.jsxsrc/components/SettingsPanel.test.jsxsrc/components/UserMenu.jsxsrc/config/settingsConfig.jssrc/config/settingsConfig.test.jsxsrc/constants/index.jssrc/constants/index.test.jssrc/hooks/useVisualization.jssrc/hooks/useVisualization.test.jssrc/i18n/i18n.test.jssrc/i18n/locales/ar/translation.jsonsrc/i18n/locales/en/translation.jsonsrc/i18n/locales/fr/translation.jsonsrc/pages/VisualizerApp.jsxsrc/pages/VisualizerApp.test.jsxsrc/services/githubRepoService.jssrc/services/githubRepoService.test.jssrc/test/setup.jssrc/video/constants.jssrc/video/useVideoExporter.test.jsvite.config.jsworker/index.js
- githubRepoService: add 10s fetch timeout via AbortController and dedupe concurrent in-flight requests - settingsConfig/setup: align ANIMATION_SPEEDS test mock with production values (5000/3000/1500/700/350) - worker: preserve ASSETS response status for /llms.txt - VisualizerApp: show algorithm tip for the target algorithm when navigating via favorites (was showing stale key) - VisualizerApp.test: render seek controls only when steps are available - Add coverage for non-OK repo responses, fetch timeout signal, in-flight dedup, and /llms.txt status passthrough
Contribution workflow
develop: This PR targetsdevelop, notmain.Description
Addresses feedback collected from the BetaBloom review of the visualizer UX. This branch ships three related improvements:
timeline_scrub) that opens the sign-in prompt.AlgorithmTipToast) and a Settings panel "Use cases" line explain the real-world value of each selected algorithm, translated into en/fr/ar.githubRepoService) with 24h TTL + stale-while-revalidate,es2022build target, Inter latin woff2 preload, decorative icons markedaria-hidden, and/llms.txtserved as markdown to LLM crawlers.Type of Change
Related Issues
Fixes #
Changes Made
ULTRA_FASTspeed preset and retune existing animation speeds insrc/constants/index.js(matchingsettingsConfig,video/constants, docs, and mocks)useVisualizationautoplay scheduler and addseekToStep()(clamped, silent, autoplay-aware)ControlPanelprogress bar a seekable timeline (Free tier) / gated button (anonymous tier) with grab handle and microcopyAlgorithmTipToastshown once per algorithm per session + "Use cases" line inSettingsPanelalgorithmUses.*copy for all 45 algorithms across en/fr/ar locales (verified 1:1 withALGORITHM_KNOWLEDGE)githubRepoService(localStorage cache, 24h TTL, stale-while-revalidate) and use it inFooterandGitHubRepoBadgeReact.lazy+Suspensefallback spinner inAppRouteses2022and preload Inter latin woff2 in builtindex.html(rolldowncloseBundleplugin)/llms.txtastext/markdownto LLM crawlers inworker/index.jsaria-hidden(Google sign-in, YouTube, Instagram, TikTok)Algorithm Details (if applicable)
N/A — no new algorithms; algorithm metadata additions only (use-case strings).
Testing
pnpm test:run)Test Results
Screenshots/GIFs
N/A
Code Quality
pnpm lint)pnpm format)Performance Impact
Accessibility
role="status"/aria-livetoast,aria-labelon slider,aria-hiddenon decorative icons)Breaking Changes
Checklist
Additional Notes
positionunused-variable warning inProComingSoonPage.jsxis pre-existing ondevelopand not touched by this branch.Summary by CodeRabbit
New Features
/llms.txtMarkdown endpoint.Accessibility
Performance