Skip to content

[FEATURE] Migrating ui to react#1147

Open
nicolastakashi wants to merge 61 commits intoopen-telemetry:mainfrom
nicolastakashi:react/ui
Open

[FEATURE] Migrating ui to react#1147
nicolastakashi wants to merge 61 commits intoopen-telemetry:mainfrom
nicolastakashi:react/ui

Conversation

@nicolastakashi
Copy link

This pull request introduces a new React-based UI for the Weaver project, establishing a parallel implementation alongside the existing Svelte UI. It includes extensive documentation, configuration, and planning materials to support the migration, as well as initial scaffolding and setup for the React app. The changes ensure strict parity between the two UIs, clarify the project's structure and conventions, and improve developer experience with updated documentation and tooling.

UI Migration and Documentation:

  • Added a comprehensive migration plan (plan.md) detailing the step-by-step process for creating a React app (ui-react/) to match the current Svelte UI, including route mapping, component parity, API usage, theming, and deployment strategy.
  • Introduced a new UI documentation file (docs/ui.md) describing the React UI's tech stack, development workflow, API integration, and deployment requirements.
  • Added a project knowledge base (AGENTS.md) summarizing the overall architecture, conventions, anti-patterns, and unique styles of the Weaver project, as well as guidance for navigating the codebase and building the UI.

React UI Scaffolding and Configuration:

  • Added React app scaffolding in ui/, including a Vite-based setup, ESLint configuration (eslint.config.js), and a new .gitignore tailored for Node/React development. [1] [2]
  • Updated ui/index.html and ui/package.json for React, including new mount point, entry script, and app naming. [1] [2]
  • Added a README for the React UI with setup instructions and guidance on expanding ESLint rules for production readiness.

Build and Integration Adjustments:

  • Clarified in build.rs that the build step now targets the React UI, ensuring the correct assets are built and embedded in the Rust server.

These changes lay the groundwork for a smooth migration from Svelte to React, provide clear guidance for developers, and establish best practices for UI development and integration within the Weaver project.

@nicolastakashi nicolastakashi requested a review from a team as a code owner January 20, 2026 21:07
@codecov
Copy link

codecov bot commented Jan 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.0%. Comparing base (6e5c98c) to head (1e6e718).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##            main   #1147     +/-   ##
=======================================
- Coverage   80.1%   80.0%   -0.1%     
=======================================
  Files        108     108             
  Lines       8440    8440             
=======================================
- Hits        6763    6760      -3     
- Misses      1677    1680      +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jerbly
Copy link
Contributor

jerbly commented Jan 26, 2026

I checked out and ran your branch... it looks good. The Schema pages need more work though:
Current:
image
Yours:
image

Copy link
Contributor

@jsuereth jsuereth left a comment

Choose a reason for hiding this comment

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

Not sure how exactly to review this, but lots of meta comments about architectural decisions here.

From my perspective, I don't care if we use svelte or react. I do care if the code is maintainable and extendable. I think, architecturally, we should clean up some of the decisions in typescript vs. react here, so we have clean logic in typescript, and save REACT for layout and simple callbacks.

I think this means more code moving out of .tsx into .ts file, e.g. making sure api.ts returns typed responses, and adding helper methods to those types.

return response.json() as Promise<T>;
}

export interface RegistryStats {
Copy link
Contributor

Choose a reason for hiding this comment

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

For @jerbly too - Do you think we can auto-generate these from the rust code in some way?

Or at least detect when they fall out of date with each other.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes! It's a little bit circular but you could generate the openapi doc from utoipa (like we do to use it in rapidocs). Then use this doc to generate the typescript.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should this file name change now they're we're not vite?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry @jsuereth, I'm afraid I didn't understand your question.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need a vite.config.js file if we're not using vite?

oneOf?: SchemaProperty[];
anyOf?: SchemaProperty[];
definitions?: Record<string, SchemaDefinition>;
$defs?: Record<string, SchemaDefinition>;
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems like an inconsistency we could fix on the Rust side - why do we have both defs and definitions?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I don't think we need definitions any more. It changed to $defs when we moved to the new JSON schema which happened when we updated schemars recently.

- Create ui-react/ directory with Vite React+TypeScript template
- Configure package.json with name weaver-ui-react and scripts (dev, build, preview)
- Configure build output to ui-react/dist directory
- Add index.html with React root mount point (#root)
- Add main.tsx importing global CSS (index.css)

This establishes the foundation for the UI migration from Svelte to React.
Add comprehensive plan for migrating UI from Svelte (ui/) to React (ui-react/)
using Vite + React + TypeScript with TanStack Router and Tailwind + DaisyUI.
- Install Tailwind 3.4.19, PostCSS 8.5.6, Autoprefixer 10.4.23, DaisyUI 4.12.24
- Create postcss.config.js with Tailwind + Autoprefixer plugins
- Create tailwind.config.js with React content globs and light/dark themes
- Port global CSS stability badges from ui/src/app.css

Build verified: daisyUI 4.12.24 with 2 themes (light, dark)
- Switch from PostCSS approach to @tailwindcss/vite plugin per official docs
- Use @import "tailwindcss" and @plugin "daisyui" in CSS instead of @tailwind directives
- Remove postcss.config.js and tailwind.config.js (not needed with v4)
- Upgrade DaisyUI to 5.5.14 with @plugin directive

Official Vite installation: https://tailwindcss.com/docs/installation/using-vite
- Install @tanstack/react-router and @tanstack/react-router-devtools
- Set up route tree structure with all required routes
- Create placeholder route components for all pages
- Update main.tsx to use RouterProvider
- Remove unused App.tsx and App.css files

Routes added:
- / (index)
- /search
- /stats
- /schema
- /api-docs
- /attribute/:key
- /metric/:name
- /span/:type
- /event/:name
- /entity/:type
Mirror Svelte proxy configuration from ui/vite.config.js
- Create AppLayout component mirroring Svelte drawer layout
- Implement responsive drawer with mobile toggle and desktop sidebar
- Add navbar with Weaver title and theme toggle (sun/moon icons)
- Implement sidebar with Registry, Schema, Developer sections
- Theme persistence via localStorage with data-theme attribute
- Create ui-react/src/lib/api.ts with BASE_URL = '/api/v1'
- Implement fetchJSON() with same error semantics as Svelte (throw on !ok)
- Add TypeScript types: RegistryStats, SearchResult, SearchResponse
- Implement all API functions: getRegistryStats, getAttribute, getMetric, getSpan, getEvent, getEntity
- Implement unified search() with URLSearchParams for query/type/stability/limit/offset
nicolastakashi and others added 28 commits February 6, 2026 15:06
- Create SpanDetail component with full feature parity
- Fetch span data via getSpan API
- Implement copy-to-clipboard with 2s feedback
- Render kind badge with 'internal' default
- Show attributes table with sampling relevant indicator
- Add loading/error/deprecation states matching Svelte
- Update plan.md to mark Span task complete
- Add Event detail route component at /event/:name
- Fetch event by name using getEvent API
- Implement loading and error states
- Add copy-to-clipboard with 2s indicator
- Render name, stability, and deprecated badges
- Show deprecated warning with renamed_to link
- Display description and note using Markdown component
- Render event attributes table with requirement level badges
- Match Svelte EventDetail.svelte parity exactly
- Add getSchema API function to fetch schema JSON
- Create full Schema route component with TypeScript types
- Implement schema query param parsing (default ForgeRegistryV2)
- Fetch schema from /api/v1/schema/:name on mount/param change
- Render left sidebar with definition list + root card
- Parse type query param (root or definition name)
- Implement selectDefinition/selectRoot URL updates via history.pushState
- Port type formatting logic (array/map/union/allOf/oneOf/anyOf)
- Implement clickable type references navigation
- Verify browser back/forward behavior via popstate listener
- Update plan.md to mark task 12 complete
Verified strict parity between Svelte and React implementations:
- Search filters: Same type and stability options in both apps
- Pagination: Same itemsPerPage=50, offset calc, display
- Link targets: Same route paths for detail pages
- URL handling: Hash vs history routing (acceptable per requirements)
- Search triggering: Both trigger on keystroke and Enter key
- Verified ui/ build continues unchanged (outputs to ui/dist/)
- Verified ui-react/ build output stays at ui-react/dist/
- Confirmed docs/ui.md documents how to run/build each app separately
- Both apps remain independent with separate build directories
…dist)

- Update src/serve/ui.rs to embed ui-react/dist instead of ui/dist
- Update comment to reflect new build source directory
- Update docs/ui.md Production Deployment section
- Mark task as complete in plan.md
- Cargo check passes
- Update build_ui() function to use ui-react directory
- Update comment to clarify React UI build
- Update plan.md to mark task as complete
- Update AGENTS.md with build process documentation
- All section 17 notes are documented in docs/ui.md and AGENTS.md
TanStack Router uses HTML5 History API by default (createRouter with default options).
The server's serve_ui function correctly implements SPA fallback:
- Serves exact files when they exist
- Falls back to index.html for any non-file paths
This enables History API routing to work correctly.
Deleted ui/ directory as all UI functionality has been migrated to ui-react/:
- Rust embed (src/serve/ui.rs) now uses ui-react/dist
- Build script (build.rs) builds from ui-react/
- No remaining ui/ references in codebase
- React UI builds and works correctly

This completes the UI migration from Svelte to React.
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Move duplicated TypeScript interfaces (MetricResponse, SpanResponse, EventResponse, EntityAttribute, AttributeResponse) from individual route components to api.ts for better type sharing and maintainability. All route files now import from the centralized location.

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Signed-off-by: Nicolas Takashi <nicolas.takashi@coralogix.com>
Copy link
Contributor

@jerbly jerbly left a comment

Choose a reason for hiding this comment

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

I didn't really know how to review this. I checked out your branch and ran it and everything seems to function well.

So I asked Claude with its new Opus 4.6 model to provide a thorough review. Take this with a pinch of salt and don't necessarily implement it all but I do think there are some important fixes we should get in:

Full code review:
https://gist.github.com/jerbly/4c82f5887339eaf8fc9eede73e532eb0

TL;DR: 3 critical security issues (XSS in markdown rendering, no error
boundaries, unsanitized CDN script), significant code duplication across
5 detail routes, and accessibility gaps. See gist for full details and
prioritized recommendations.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants