Exhaustive agent lookup: inventories, architecture map, CI detail, test catalog, and add-algorithm checklists. The lean always-on guide is
AGENTS.md— update this file when factual inventory changes; update the root file only for behavioral rules.
- Product:
Bayan Flow(Bayan / بيان = clarity in Arabic) - Package name:
bayan-flow - App type: client-side React SPA with routes
/,/app,/roadmap,/pro,/settings/profile,/privacy,/terms - Version target in
package.json:0.5.0 - License:
Elastic-2.0 OR Commercial(seeLICENSE,COMMERCIAL_LICENSE.md,TRADEMARK.md,NOTICE) - Repository/homepage:
https://github.com/ayoub3bidi/bayan-flow- Production:
https://bayanflow.com(main) - Dev/beta:
https://dev.bayanflow.com(develop) - Contact:
contact@bayanflow.com
- Tooling: React 19, React Router 7, Rolldown Vite 7, Tailwind CSS 4, Vitest 3, React Testing Library, Framer Motion, Remotion 4 (
remotion,@remotion/web-renderer,@remotion/media), i18next, Monaco Editor, Tone.js, @phosphor-icons/react, react-icons (SimpleIcons for brand logos), Octokit, Playwright (export SFX script only) - Python execution: Pyodide
0.27.5loaded client-side in a worker - Engines: Node
>=24.11.1, pnpm>=8.15.9(CI uses pnpm 9) - Contribution flow: PRs target
develop, notmain; PRs tomainare gated by.github/workflows/ensure-pr-source-develop.yml - Algorithm inventory: 45 algorithms across 5 categories (14 sorting, 9 pathfinding, 9 searching, 6 tree traversal, 7 graph algorithms)
- Python parity: 45
.pyfiles undersrc/algorithms/python/(one per algorithm) - Test surface: 152
*.test.js/*.test.jsxfiles undersrc/(~1,823 tests) - Source surface: 224 non-test
*.js/*.jsxfiles undersrc/, 45 Python files undersrc/algorithms/python/, 1src/index.css - Path alias:
@/→src/(Vite + Vitest)
- Treat runtime registries and config files as the source of truth when docs drift:
src/constants/index.js— category keys, algorithm keys, complexity maps, visual state enums, size defaultssrc/constants/algorithmKnowledge.js— insight metadata registry (translated copy lives in locales)src/constants/githubRepo.js— GitHub owner/name/URL constants for the repo badgesrc/registry/categoryConfig.js— per-category wiring (defaults, i18n, size controls, groups, features)src/registry/visualizerRegistry.jssrc/registry/extraVisualizerProps.jssrc/registry/videoSceneRegistry.jsxsrc/registry/complexityDatasetRegistry.jssrc/registry/searchingSubstrate.jssrc/registry/graphAlgorithmRegistry.js— profiles, scenarios,GRAPH_ALGORITHM_KEYS,GRAPH_ALGORITHM_GROUPSsrc/config/algorithmConfig.js—useAlgorithmConfig(),buildAlgorithmsForCategory(),buildGroupsForCategory()src/config/settingsConfig.js—useSettingsConfig()(grid size + speed option labels)src/motion/chromeMotion.js— shared chrome UI motion presets (drawers/modals/menus/marketing); do not invent local spring params for chrome
docs/ARCHITECTURE.md,docs/DEVELOPMENT.md,README.md, andCONTRIBUTING.mdare useful, but they can lag behind the live category/runtime wiring.- Runtime completeness tests are important because the app depends heavily on synchronized registries (
categoryRuntimeCompleteness.test.js).
- Categories:
sortingpathfindingsearchingtreeTraversalgraphAlgorithm
- Sorting algorithms (14):
bubbleSort,quickSort,mergeSort,selectionSort,insertionSort,heapSort,shellSort,radixSort,countingSort,bucketSort,cycleSort,combSort,timSort,bogoSort
- Pathfinding algorithms (9):
bfs,dijkstra,aStar,bidirectionalSearch,greedyBestFirstSearch,jumpPointSearch,bellmanFord,idaStar,dStarLite
- Searching algorithms (9):
- array substrate:
linearSearch,binarySearch,ternarySearch,jumpSearch,interpolationSearch,exponentialSearch,fibonacciSearch - node-link substrate:
depthFirstSearch,breadthFirstSearchGraph
- array substrate:
- Tree traversal algorithms (6):
inorderTraversal,preorderTraversal,postorderTraversal,levelOrderTraversal,zigzagLevelOrderTraversal,morrisTraversal
- Graph algorithms (7):
topologicalSort,kahnAlgorithm,kruskalAlgorithm,primAlgorithm,tarjanAlgorithm,kosarajuAlgorithm,floydWarshallAlgorithm
- Playback: manual vs autoplay (
VISUALIZATION_MODES), five speed presets (ANIMATION_SPEEDS) - Mobile: horizontal swipe for manual step forward/back (
useSwipe), one-time swipe tutorial (SwipeTutorial) - Full-screen visualization mode (
useFullScreen) reuses the same control panel and visualizer registry - Light/dark theme with system preference fallback (
ThemeContext,ThemeToggle,useTheme) - i18n: English, French, Arabic with RTL (
rtlManager,LanguageSwitcher) - Optional visualization sound (Tone.js); persisted in
localStorageunderbayan-flow:sound-enabled - Code panel (lazy): Python + pseudocode tabs in one panel (
PythonCodePanel), Monaco editor, Pyodide worker execution, editable custom test cases, predefined tests (TestCasesPanel,OutputConsole) - Algorithm insight panel with history, intuition, facts, optional YouTube embed (
AlgorithmInsightPanel,InsightFloatingActionButton) - Pseudocode: localized strings and syntax highlighting inside
PythonCodePanel(pseudocodeHighlight.js,pseudocode/localize.js) — not a separate overlay - Auto-hiding color legend on visualizers (
AutoHidingLegend) - Complexity panel after completion; exported video includes a complexity segment
- Video export: horizontal/vertical orientation, MP4/H.264 via
@remotion/web-renderer, progress modal, watermark, export audio cues via@remotion/media - Landing page with hero, features, algorithm-type grid, GitHub repo badge (Octokit live stats)
- Roadmap page driven by
src/data/roadmapData.js - Document title syncs with route/i18n (
DocumentTitle) - Side FABs:
FloatingActionButton(code/pseudocode panel),InsightFloatingActionButton(insight panel) - Feature gating:
SignInPromptModalblocks Code Panel, Insight Panel, Video Export, Sound, and Fullscreen until the user signs in with Google - Profile settings (signed-in):
/settings/profile— editdisplay_name, toggleavatar_preference(google|generated);RequireAuthguard;profileService.updateProfile()
- Supabase project:
bayan-flow(eu-central-1); migrations insupabase/migrations/ - Client:
src/lib/supabaseClient.js(anon key viaVITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEYonly) - Services:
src/services/authService.js,src/services/profileService.js,src/services/entitlementService.js,src/services/accessService.js,src/services/waitlistService.js,src/services/favoritesService.js,src/services/notesService.js - Hooks:
src/hooks/useFavorites.js,src/hooks/useNoteAutosave.js - Constants:
src/constants/personalLearning.js(favorite slot limits, note length cap) - Components:
src/components/FavoritesDropdown.jsx,src/components/AlgorithmNotesTab.jsx,src/components/NoteEditor.jsx(lazy TipTap) - Edge Functions (deployed via
deploy-supabase-functions.ymlafter green CI):supabase/functions/before-signup/— signup ban gate (fail-closed)supabase/functions/post-signup/— post-signup side effectssupabase/functions/platform-access/— signed-in ban check (accessService.checkPlatformAccess(); fail-open on transport)supabase/functions/waitlist-welcome/— Pro waitlist confirmation email via Resend (fail-open; invoked after client insert)supabase/functions/sync-contacts/— JWT-authenticated Resend contact upsert + one-time Free welcome email on sign-in (fail-open; identity from JWT only; atomic claim onprofiles.welcome_email_sent_at; Resend segment viaRESEND_SEGMENT_IDor legacyRESEND_AUDIENCE_ID)supabase/functions/delete-account/— self-service account deletion
- Shared email HTML:
supabase/functions/_shared/transactionalEmails.ts - Not in 0.5.0: LemonSqueezy webhook, subscriptions / usage_events / referrals / user_sessions tables (dropped via
20260720180000_drop_premature_saas_scaffolding.sql); no viz-limit email, weekly digest, Pro nudge, or referral invite sends (Pro nudge + referral templates may exist in Resend as parked drafts for later) - Analytics:
src/services/analytics.js,src/services/analyticsEvents.js— PostHog SPA pageviews + growth eventswaitlist_joined,upgrade_limit_hit; surveys disabled in SDK - Context:
src/contexts/AuthProvider.jsx,src/hooks/useAuth.js - Avatar resolution:
src/utils/resolveUserAvatar.js(resolveUserAvatar,resolveDisplayName, DiceBear notionists style) - Components:
src/components/UserMenu.jsx,src/components/UserAvatar.jsx,src/components/RequireAuth.jsx - Page:
src/pages/ProfileSettingsPage.jsx
| Column | Client writable | Notes |
|---|---|---|
id |
no | PK, FK → auth.users |
email |
no | Set by handle_new_user trigger |
plan |
no | free | pro; service role / webhook only |
provider |
no | Set on signup |
created_at |
no | |
display_name |
yes | Editable on profile settings page |
avatar_url |
no | OAuth / trigger-populated HTTPS URL |
avatar_preference |
yes | google (default) | generated |
welcome_email_sent_at |
no | Set atomically by sync-contacts when claiming the one-time welcome send |
Future (post-0.5.0, not shipped): username (unique, set-once RLS), public /u/:username route; any referral/billing columns — new migrations then, not restore of dropped scaffolding. Through 0.5.0 Pro remains waitlist-only.
| Table | PK | Client access |
|---|---|---|
favorite_algorithms |
(user_id, category, algorithm_key) |
SELECT / INSERT / DELETE own rows |
algorithm_notes |
(user_id, category, algorithm_key) |
SELECT / INSERT / UPDATE own rows |
Migration: supabase/migrations/*_personal_learning_favorites_notes.sql. Free tier: 20 favorite slots (getFavoriteSlotLimit in entitlementService.js); notes unlimited per algorithm with HTML sanitization (noteHtmlSanitizer.js).
| Column | Client writable | Notes |
|---|---|---|
id |
no | PK |
user_id |
yes (on insert) | Nullable; FK → profiles when signed in |
email |
yes (on insert) | Unique, normalized lowercase in service layer |
source |
yes (on insert) | landing | app | direct |
created_at |
no |
Insert-only RLS for anon + authenticated; no client SELECT. Public count via waitlist_public_count() RPC. Welcome email via waitlist-welcome edge function (Resend).
Migrations: 20260710140000_pro_waitlist.sql, 20260710150000_pro_waitlist_attribution.sql (if base table applied without attribution columns), 20260710160000_drop_waitlist_pitch_variant.sql.
profiles_select_own—SELECTwhereauth.uid() = idprofiles_update_own—UPDATEwhereauth.uid() = idREVOKE UPDATEon table forauthenticated;GRANT UPDATE (display_name, avatar_preference)only
getProfile(userId)→{ display_name, avatar_url, avatar_preference, plan, email }or nullupdateProfile(userId, { displayName, avatarPreference })— trims display name; validatesavatarPreference; never touchesplan,avatar_url, etc.
pnpm vitest run src/services/profileService.test.jspnpm vitest run src/services/favoritesService.test.js src/services/notesService.test.jspnpm vitest run src/hooks/useFavorites.test.js src/hooks/useNoteAutosave.test.jspnpm vitest run src/components/FavoritesDropdown.test.jsx src/components/AlgorithmNotesTab.test.jsxpnpm vitest run src/pages/ProfileSettingsPage.test.jsxpnpm vitest run src/contexts/AuthProvider.test.jsx src/utils/resolveUserAvatar.test.js src/components/UserMenu.test.jsx
src/main.jsx— router,ThemeProvider, RTL initsrc/contexts/ThemeContext.jsx,src/contexts/ThemeContextDefinition.jssrc/i18n/index.js— three locales, browser language detection,localStoragecache
src/pages/LandingPage.jsxsrc/pages/VisualizerApp.jsx— main visualizer shell and top-level statesrc/pages/Roadmap.jsxsrc/pages/ProComingSoonPage.jsx— Pro waitlist teaser + email capture (/pro)src/pages/ProfileSettingsPage.jsx— signed-in display name + avatar preference
src/registry/categoryConfig.jssrc/config/algorithmConfig.jssrc/config/settingsConfig.jssrc/hooks/useCategoryVisualizations.jssrc/registry/visualizerRegistry.jssrc/registry/extraVisualizerProps.jssrc/registry/videoSceneRegistry.jsxsrc/registry/complexityDatasetRegistry.js
src/hooks/useSortingVisualization.jssrc/hooks/usePathfindingVisualization.jssrc/hooks/useSearchingVisualization.jssrc/hooks/useTreeTraversalVisualization.jssrc/hooks/useGraphAlgorithmVisualization.js
src/hooks/useVisualization.js— shared step playback, sound emission, completion timingsrc/hooks/usePythonExecution.js— Pyodide worker lifecyclesrc/hooks/useFullScreen.jssrc/hooks/useSwipe.js— touch swipe for manual steppingsrc/hooks/useTheme.js
src/components/Header.jsx,src/components/Footer.jsxsrc/components/SettingsPanel.jsx— category tabs, size controls, speed, export orientationsrc/components/ControlPanel.jsx— play/pause, step, reset, shuffle, sort order, sound togglesrc/components/AlgorithmDropdown.jsx,src/components/GraphScenarioDropdown.jsxsrc/components/ComplexityPanel.jsxsrc/components/FloatingActionButton.jsx,src/components/InsightFloatingActionButton.jsxsrc/components/PythonCodePanel.jsx(lazy),src/components/AlgorithmInsightPanel.jsx(lazy)src/components/ExportProgressModal.jsxsrc/components/OutputConsole.jsx,src/components/TestCasesPanel.jsxsrc/components/AutoHidingLegend.jsx,src/components/SwipeTutorial.jsxsrc/components/SignInPromptModal.jsxsrc/components/ProWaitlistBanner.jsx— dismissible Pro waitlist CTA (landing + app)src/components/LanguageSwitcher.jsx,src/components/ThemeToggle.jsx,src/components/DocumentTitle.jsxsrc/components/GitHubRepoBadge.jsx
src/components/landing/—Hero,HeroVisualizerDemo,AlgorithmTypes,Features,ProPreview,ClaritySection,FAQ,RoadmapCTA,TechPattern,SocialProofStrip(gated bySHOW_LANDING_SOCIAL_PROOF)src/components/roadmap/—RoadmapHero,Timeline,TimelineItemsrc/components/ui/— sharedButton,Container,Section
src/components/ArrayVisualizer.jsx,src/components/ArrayBar.jsxsrc/components/GridVisualizer.jsx,src/components/GridCell.jsxsrc/components/SearchingCategoryVisualizer.jsxsrc/components/GraphVisualizer.jsxsrc/components/TreeVisualizer.jsxsrc/components/GraphAlgorithmCategoryVisualizer.jsxsrc/components/GraphAlgorithmMatrixVisualizer.jsx
src/video/useVideoExporter.js,src/video/AlgorithmVideo.jsx- Scenes:
SortingScene,PathfindingScene,SearchingVideoScene,GraphSearchingScene,TreeTraversalScene,GraphAlgorithmVideoScene,GraphAlgorithmScene,GraphAlgorithmMatrixScene,ComplexityScene src/video/ExportAudioTracks.jsx,src/video/VideoWatermarkOverlay.jsxsrc/video/exportLanguage.js,src/video/videoExportTheme.js,src/video/constants.jssrc/video/audio/buildExportSoundCues.js,src/video/audio/exportAudioAssets.js- Static export SFX:
public/video-export/sfx/— 18 pre-rendered WAV files (regenerated viapnpm run generate:export-sfx)
src/hooks/usePythonExecution.jssrc/workers/pyodide.worker.jssrc/algorithms/python/**,src/algorithms/python/index.js,src/algorithms/python/testCases.jssrc/algorithms/pseudocode/**—strings.en.js,strings.fr.js,strings.ar.js,localize.js,index.js
src/utils/soundEvents.js— semantic event derivation (SOUND_EVENT_KINDS)src/utils/soundManager.js— Tone.js playback singletonsrc/utils/soundFrequencies.js,src/utils/toneInstrumentPresets.jssrc/utils/masterChain.js— shared effects bus (gain → filter → compressor → reverb)src/utils/categoryPalettes.js— per-category instrument and chord mappingssrc/utils/scaleQuantizer.js— pentatonic note selection for melodic cues
src/utils/arrayHelpers.js,src/utils/gridHelpers.js,src/utils/treeGenerators.jssrc/utils/graphSearchGenerators.js,src/utils/graphAlgorithmGenerators.js,src/utils/graphTestScenarios.jssrc/utils/graphMatrixLayout.js,src/utils/dStarLiteHelpers.js,src/utils/PriorityQueue.jssrc/utils/resolveStepDescription.js,src/utils/pseudocodeHighlight.jssrc/utils/rtlManager.js,src/utils/algorithmTranslations.jssrc/utils/deployContext.js—isProductionMainBranch()fromVITE_GIT_BRANCHsrc/utils/formatGitHubCount.js
src/data/roadmapData.js
src/test/setup.js— global Vitest setup (i18n init, constants/Tone/soundManager/framer-motion mocks)src/test/testUtils.jsx—renderWithI18n()helpersrc/test/framerMotionMock.jsx— shared Framer Motion test double
public/manifest.json,public/sitemap.xml,public/robots.txt,public/logo.svgpublic/_headers— security headers, cache rules, andworkers.devnoindex for Cloudflare Workers static assetspublic/ui/sfx/— interactive UI one-shot sounds (e.g. theme toggle); loaded via Web Audio insrc/utils/themeSwitchSound.jspublic/video-export/sfx/— 18 pre-rendered Remotion export WAV files (see Export sound contract)
vite.config.js,vitest.config.js(@/alias, jsdom, sequential forks for memory)eslint.config.js,wrangler.jsonc,codecov.ymlscripts/render-tone-export-sfx.mjs— Playwright + Tone.Offline WAV generation.github/workflows/ci.yml,deploy-cloudflare.yml,deploy-supabase-functions.yml,preview-cloudflare.yml,ensure-pr-source-develop.yml,release.yml,stale.yml,semgrep.yml,.github/labeler.yml
VisualizerAppowns top-level UI state:- active category (
algorithmType) - selected algorithm per category (
selectedAlgorithms) - size state:
arraySize,gridSize,searchGraphNodeCount,treeNodeCount,graphNodeCount - graph scenario selection for graph algorithms
- sorting order (
SORT_ORDERS) - speed, playback mode (
VISUALIZATION_MODES), sound preference, full-screen state - export flow, lazy panel visibility (
PythonCodePanel,AlgorithmInsightPanel) - gated feature state (
gatedFeature,pendingFeatureRef) for sign-in gating
- active category (
- All category hooks are called unconditionally in
VisualizerAppto preserve React Rules of Hooks. CATEGORY_CONFIGis the central registry for:- default algorithm
- translation prefix and tab label
- icon (Phosphor)
sizeBinding:array|grid|tree|graph- algorithm lookup and data generation
- feature flags (e.g.
hasDataRefresh) - size control metadata (slider vs preset buttons)
- grouped dropdown definitions (
groupDefs) - complexity dataset key
useAlgorithmConfig()derives translated dropdown data fromCATEGORY_CONFIG.- Each category hook computes steps and runtime state;
useCategoryVisualizations()exposes them as a map keyed byALGORITHM_TYPES. VISUALIZER_REGISTRYselects the interactive renderer.getExtraVisualizerProps()centralizes category-specific props for visualizer components.VIDEO_SCENE_RENDERERSselects the Remotion scene.COMPLEXITY_DATASETSmust stay aligned withCATEGORY_CONFIG[category].complexityDataset.- Visualization sound is emitted from the shared playback layer through
getSoundEventsForStep(), not from category-specific UI controls.
- Source of truth:
src/registry/searchingSubstrate.js - Array search algorithms use
ArrayVisualizerthroughSearchingCategoryVisualizer. - Node-link graph search algorithms use
GraphVisualizerthroughSearchingCategoryVisualizer. - Do not special-case searching substrate in unrelated components; branch through
getSearchingSubstrate()/isNodeLinkSearchingAlgorithm(). - Node-link searching uses
DEFAULT_SEARCH_GRAPH_NODE_COUNT(12) andSEARCH_GRAPH_NODE_COUNT(slider 5–24), separate from pathfinding grid size and graph-algorithm node count. - Searching video export routes array-shaped steps to
SortingSceneand node-link shaped steps toGraphSearchingSceneviaSearchingVideoScene.
- Registry:
src/registry/graphAlgorithmRegistry.js - Representations:
GRAPH_REPRESENTATIONS.NODE_LINKGRAPH_REPRESENTATIONS.MATRIX
- Profiles (
GRAPH_ALGORITHM_PROFILES): directed/weighted flags, representation, scenario support, deterministic input generation viacreateInput() - Groups (
GRAPH_ALGORITHM_GROUPS): topological ordering, MST, SCC, shortest paths - Input shape for node-link graph algorithms:
{ nodes, edges, adjacency, directed, weighted }
- Step shape for node-link graph algorithms:
{ nodes, edges, nodeStates, edgeStates, stackOrder, outputOrder, graphArtifacts, description, representation, directed, weighted }
- Step shape for matrix graph algorithms:
{ matrix, description, representation, directed, weighted, graphArtifacts }
matrixshape:{ rowLabels, columnLabels, cells, cellStates }
- Floyd-Warshall is the matrix-path exception and has a smaller max node-count range (
max: 6). - Preset scenarios are fixed datasets in
graphTestScenarios.js. When a scenario is selected, UI must not imply thatgraphNodeCountstill changes the active graph (GraphScenarioDropdown).
- Pathfinding algorithms operate on grid steps and are rendered by
GridVisualizer/PathfindingScene. CATEGORY_CONFIG[PATHFINDING].generateData()creates an empty grid template; randomized start/end and walls are owned byusePathfindingVisualization.gridSizeuses named presets fromGRID_SIZES, not the array-size slider.
- Tree traversal data comes from
generateTreeForTraversal(). sizeBinding: 'tree'withtreeNodeCount(default 15, slider 3–31).- Visual state includes nodes, edges, node states, visit order, optional queue order, and optional level scan direction.
- Keep tree generator and traversal tests aligned when changing node shape or traversal ordering.
- Locales:
src/i18n/locales/en/translation.jsonsrc/i18n/locales/fr/translation.jsonsrc/i18n/locales/ar/translation.json
- Pseudocode strings:
src/algorithms/pseudocode/strings.en.jssrc/algorithms/pseudocode/strings.fr.jssrc/algorithms/pseudocode/strings.ar.js
- Python snippets:
src/algorithms/python/*.pysrc/algorithms/python/index.jssrc/algorithms/python/testCases.js
featureGatei18n namespace: feature labels and sign-in prompt strings in all three locale files- Insight copy:
insight_panel.algorithms.<key>.*keys in all three locale files; metadata inalgorithmKnowledge.js - User-facing category labels are reused in multiple places. If you rename one, audit:
- all locale files
- pseudocode strings if algorithm names/descriptions change
src/registry/videoSceneRegistry.jsx- landing/roadmap/README/docs copy that mentions the category by name
- export title fallbacks and complexity labels
- Arabic is RTL. Check layout direction-sensitive changes in both app UI and Remotion export.
- Preserve the registry-driven architecture. Prefer extending config/registry files over adding special-case branches in
VisualizerApp. - Completion UX should preserve the final visualization state briefly before showing
ComplexityPanel. - Graph algorithm parity must cover both:
- interactive visualization
- Remotion export
- Floyd-Warshall must remain aligned across:
GraphAlgorithmCategoryVisualizerGraphAlgorithmVideoSceneGraphAlgorithmMatrixSceneGraphAlgorithmMatrixVisualizer
- The shared regenerate action is category-neutral and should stay described as input regeneration, not array regeneration.
- The shared control uses
Generate New Inputcopy and a refresh-style icon because the same action regenerates arrays, grids, trees, and graphs depending on the active category. - Sorting is the only category with sort-order controls.
- Full-screen mode uses the same
ControlPaneland visualizer registry as normal mode. - Lazy panels (
PythonCodePanel,AlgorithmInsightPanel) must remain optional overlays and should not block the main visualization path. - Swipe stepping applies only in manual playback mode on touch devices.
- The step progress bar is seekable: Free-tier users (non-gated) get an invisible full-width range input driving seeking, a circular grab handle (
seek-thumb) marking the fill edge, and thecontrols.dragToSeekmicrocopy under the bar. Anonymous/gated users see the same grab handle and a persistentcontrols.dragToSeekLockedmicrocopy ("Sign in to skip steps"), but no range input; the timeline wrapper is a focusable button (role="button") whose click or Enter/Space firesonGatedFeatureClick('timeline_scrub')→SignInPromptModal(featureGate.timeline_scrub).
- Sound enable/disable UI lives in
src/components/ControlPanel.jsx. - Persisted sound preference and shared sound toggle state live in
src/pages/VisualizerApp.jsx(bayan-flow:sound-enabled). - Semantic sound event derivation lives in
src/utils/soundEvents.js(SOUND_EVENT_KINDS: compare, swap, pivot, complete, visit, frontier, targetFound, pathFound, noResult, edgeConsider, edgeSelect, cycle, matrixConsider, matrixUpdate, componentComplete, passComplete). - Actual Tone.js playback state lives in the singleton
soundManager, routed throughcreateMasterChain()and category-specific palettes/chords fromcategoryPalettes.js. - Pentatonic note selection for melodic micro-events uses
scaleQuantizer.js. - If you touch sound UX, keep the enabled state synchronized with
soundManager.getIsEnabled()and local storage. - Sound is visualization-only: do not add click, settings, panel, export-button, fullscreen, or regeneration sounds.
- Do not infer sound from localized
descriptiontext. Use stable visual state or explicit semantic step metadata. useVisualizationis responsible for emitting sound during intentional forward playback/manual stepping. Initial load, reset, step-back, algorithm changes, and passive regeneration should stay silent.soundManagershould create Tone instruments lazily after sound is enabled, not at module import.- Interactive playback and export audio should consume the same sound events so they do not drift.
- Pre-rendered export WAV assets live under
public/video-export/sfx/; regenerate withpnpm run generate:export-sfxafter changing instrument presets or event kinds. - Graph algorithm and Floyd-Warshall matrix sound parity must cover both interactive visualization and Remotion export.
- Export uses
@remotion/web-renderer, supports horizontal and vertical orientations, and renders MP4/H.264 when the browser supports it. - Export audio playback in Remotion uses
@remotion/media(ExportAudioTracks.jsx). AlgorithmVideoadds title, step counter, localized description, watermark, optional export audio, and final complexity scene.buildExportSoundCues()should schedule cues fromgetSoundEventsForStep()and must not special-case translated copy.- Export descriptions use
resolveStepDescription()and normalized export language (exportLanguage.js). Keep description keys localizable.
- CI (
.github/workflows/ci.yml) on push/PR tomainanddevelop— Node 24.11.1, pnpm 9:- Quality —
pnpm lint,pnpm format:check - Test —
pnpm test:coverage(Codecov upload viacodecov.yml, PR lcov comment) - Build —
pnpm buildwithVITE_GIT_BRANCH,VITE_DEV_SITE_URL - Deploy — Cloudflare Workers (
main→ production,develop→ staging); PR previews viapreview-cloudflare.yml(separate workflow) - All-checks-pass — aggregate gate for branch protection
- Quality —
- Other workflows:
deploy-cloudflare.yml— production/staging deploy after CI succeeds onmain/developpreview-cloudflare.yml— PR preview URLs onbayan-flow-stagingensure-pr-source-develop.yml— blocks PRs tomainunless head isdevelopor author is inALLOWED_MERGERSsecretrelease.yml— GitHub release onv*tagsstale.yml,labeler.yml— repo hygiene
- Cloudflare SPA routing in
wrangler.jsonc(not_found_handling: single-page-application); branch context setsVITE_GIT_BRANCHat build time. - Optional
VITE_PYODIDE_CDN_BASEoverrides the default jsDelivr Pyodide CDN (src/constants/pyodideCdn.js). src/utils/deployContext.js—isProductionMainBranch()gates production-only UI (e.g. certain landing content).- GitHub repo constants:
src/constants/githubRepo.js.
- Add/update the category key in
src/constants/index.js(ALGORITHM_TYPES, complexity map if needed). - Add/update the
CATEGORY_CONFIGentry insrc/registry/categoryConfig.js. - Wire the hook unconditionally in
src/pages/VisualizerApp.jsx. - Add the hook result in
src/hooks/useCategoryVisualizations.js. - Register the visualizer in
src/registry/visualizerRegistry.js. - Register extra props in
src/registry/extraVisualizerProps.js. - Register the Remotion scene and title fallback in
src/registry/videoSceneRegistry.jsx. - Ensure
src/registry/complexityDatasetRegistry.jscontains the dataset key. - Add settings config/i18n entries where needed.
- Add or update tests for category config, runtime completeness, visualizer selection, export scene selection, and settings UI.
- Add the JS implementation under the relevant
src/algorithms/<category>/folder. - Export/register it from that category's
index.js. - Add constants/complexity metadata in
src/constants/index.js. - Add insight metadata in
src/constants/algorithmKnowledge.js(if insight panel coverage is desired). - Add i18n entries in all three locale files.
- Add pseudocode in all three pseudocode string files.
- Add Python code in
src/algorithms/python/and register it insrc/algorithms/python/index.js. - Add Python test cases in
src/algorithms/python/testCases.js. - Add/update semantic sound-event coverage in
src/utils/soundEvents.jswhen the algorithm introduces new visual action states. - Update
categoryConfig.jsalgorithmKeysandgroupDefs(and graph profile if applicable). - Add or extend tests for algorithm logic, registry wiring, hook behavior, visualizers, export scenes, Python index, complexity metadata, pseudocode, sound events, and insight metadata.
- Add the algorithm implementation in
src/algorithms/graphAlgorithm/. - Export it from
src/algorithms/graphAlgorithm/index.js. - Register its profile in
src/registry/graphAlgorithmRegistry.js(GRAPH_ALGORITHM_PROFILES, scenarios, groups). - Add its constant and complexity entry in
src/constants/index.js. - Add insight metadata in
src/constants/algorithmKnowledge.js. - Add i18n entries in all three locale files.
- Add pseudocode in all three pseudocode string files.
- Add Python code in
src/algorithms/python/and register it insrc/algorithms/python/index.js. - Add Python test cases in
src/algorithms/python/testCases.js. - Add/update graph or matrix sound-event coverage in
src/utils/soundEvents.js. - Add or extend tests for JS logic, graph profile/scenario wiring, hook behavior, visualizers, export scenes, Python index, complexity metadata, pseudocode, sound events, and insight metadata.
- Vitest runs in jsdom with
@/path alias; tests use sequential forks to reduce memory pressure (vitest.config.js). - Setup:
src/test/setup.js(global mocks for constants, Tone, soundManager, framer-motion, gridHelpers). - Helper:
renderWithI18n()fromsrc/test/testUtils.jsxfor component tests needing i18n. - Coverage config:
codecov.yml(patch target 70%; several presentational components excluded from coverage totals).
Registry and runtime (run first for wiring changes):
pnpm vitest run src/registry/categoryConfig.test.jspnpm vitest run src/registry/categoryRuntimeCompleteness.test.jspnpm vitest run src/registry/visualizerRegistry.test.jspnpm vitest run src/registry/extraVisualizerProps.test.jspnpm vitest run src/registry/videoSceneRegistry.test.jsxpnpm vitest run src/registry/complexityDatasetRegistry.test.jspnpm vitest run src/registry/graphAlgorithmRegistry.test.jspnpm vitest run src/registry/searchingSubstrate.test.js
Config and constants:
pnpm vitest run src/config/algorithmConfig.test.jsxpnpm vitest run src/config/settingsConfig.test.jsxpnpm vitest run src/constants/index.test.jspnpm vitest run src/constants/algorithmKnowledge.test.jspnpm vitest run src/constants/githubRepo.test.js
Hooks:
pnpm vitest run src/hooks/useCategoryVisualizations.test.jspnpm vitest run src/hooks/useVisualization.test.jspnpm vitest run src/hooks/useGraphAlgorithmVisualization.test.jspnpm vitest run src/hooks/useSortingVisualization.test.jspnpm vitest run src/hooks/usePathfindingVisualization.test.jspnpm vitest run src/hooks/useSearchingVisualization.test.jspnpm vitest run src/hooks/useTreeTraversalVisualization.test.jspnpm vitest run src/hooks/usePythonExecution.test.jspnpm vitest run src/hooks/useSwipe.test.jspnpm vitest run src/hooks/useTheme.test.js
Core visualizer shell:
pnpm vitest run src/pages/VisualizerApp.test.jsxpnpm vitest run src/components/SettingsPanel.test.jsxpnpm vitest run src/components/ControlPanel.test.jsxpnpm vitest run src/components/PythonCodePanel.test.jsxpnpm vitest run src/components/AlgorithmInsightPanel.test.jsxpnpm vitest run src/components/AlgorithmDropdown.test.jsxpnpm vitest run src/components/GraphScenarioDropdown.test.jsx
Visualizers and panels:
pnpm vitest run src/components/GraphVisualizer.test.jsxpnpm vitest run src/components/GraphAlgorithmCategoryVisualizer.test.jsxpnpm vitest run src/components/GraphAlgorithmMatrixVisualizer.test.jsxpnpm vitest run src/components/ComplexityPanel.test.jsxpnpm vitest run src/components/AutoHidingLegend.test.jsxpnpm vitest run src/components/TestCasesPanel.test.jsxpnpm vitest run src/components/ExportProgressModal.test.jsxpnpm vitest run src/components/SignInPromptModal.test.jsx
Video export:
pnpm vitest run src/video/AlgorithmVideo.test.jsxpnpm vitest run src/video/AlgorithmVideo.renderer.test.jsxpnpm vitest run src/video/useVideoExporter.test.jspnpm vitest run src/video/GraphAlgorithmVideoScene.test.jsxpnpm vitest run src/video/GraphAlgorithmMatrixScene.test.jsxpnpm vitest run src/video/GraphAlgorithmScene.test.jsxpnpm vitest run src/video/ComplexityScene.test.jsxpnpm vitest run src/video/audio/buildExportSoundCues.test.js
Sound:
pnpm vitest run src/utils/soundEvents.test.jspnpm vitest run src/utils/soundManager.test.jspnpm vitest run src/utils/masterChain.test.js
Algorithms and Python/pseudocode:
pnpm vitest run src/algorithms/graphAlgorithm/*.test.jspnpm vitest run src/algorithms/sorting/algorithms.test.jspnpm vitest run src/algorithms/pathfinding/pathfinding.test.jspnpm vitest run src/algorithms/searching/index.test.jspnpm vitest run src/algorithms/treeTraversal/*.test.jspnpm vitest run src/algorithms/python/index.test.jspnpm vitest run src/algorithms/pseudocode/index.test.js
Landing, roadmap, and i18n:
pnpm vitest run src/pages/LandingPage.test.jsxpnpm vitest run src/pages/Roadmap.test.jsxpnpm vitest run src/components/landing/*.test.jsxpnpm vitest run src/components/roadmap/*.test.jsxpnpm vitest run src/i18n/i18n.test.jspnpm vitest run src/data/roadmapData.test.js
pnpm test:runpnpm buildpnpm lintpnpm format:check
Use focused tests first for registry/category changes, then broaden to the full suite before handoff when the change touches shared runtime behavior.
- Do not rewrite user-authored changes.
- Keep shared registries synchronized; this codebase relies on configuration completeness more than ad hoc branching.
- When changing a user-facing label or category concept, audit all locales and export fallbacks, not just the visible screen you touched.
- When changing an algorithm, keep JS logic, UI, export, i18n, pseudocode, Python snippets, Python tests, complexity metadata, and insight metadata category-consistent.
- When changing visual step states, keep
soundEventsand export audio cue tests aligned with the new visual behavior. - Do not reintroduce controller/settings sounds; sound should come from visualization steps only.
- Treat silence as intentional: if a new step has no sound, make sure that is a deliberate choice rather than an omitted event mapping.
- For net-new graph algorithms, keep commits scoped to one completed algorithm at a time.
- If a shared helper is required, add it in the earliest commit that needs it.
- Prefer existing hooks, registries, helpers, and component patterns over one-off branches.
- Keep deterministic generators deterministic in tests by accepting/passing an
rngwhere existing utilities do.
| File | Content-Type | Purpose |
|---|---|---|
/.well-known/api-catalog |
application/linkset+json |
RFC 9727 API catalog with linkset array |
/.well-known/mcp/server-card.json |
application/json |
MCP Server Card (SEP-1649) with serverInfo, endpoint, capabilities |
/.well-known/oauth-authorization-server |
application/json |
OAuth discovery (Supabase issuer) with agent_auth block |
/.well-known/oauth-protected-resource |
application/json |
RFC 9728 Protected Resource Metadata |
/.well-known/agent-card.json |
application/json |
Agent card with capabilities and features |
/.well-known/agent-skills/index.json |
application/json |
Agent skills catalog |
/auth.md |
text/markdown |
Agent registration / authentication guide |
/llms.txt |
text/plain |
Machine-readable site description for AI agents |
The /* section includes Link headers pointing to:
</.well-known/api-catalog>; rel="api-catalog"</.well-known/oauth-protected-resource>; rel="oauth-protected-resource"</.well-known/mcp/server-card.json>; rel="mcp-server-card"</auth.md>; rel="auth-md"</llms.txt>; rel="llms-txt"
All /.well-known/* paths include Access-Control-Allow-Origin: * for cross-origin agent discovery.