Arbiter Dashboard
React dashboard for exploring code reviews and monitoring Arbiter metrics.
Features
- Review List — Browse all reviews with filtering and pagination
- Review Detail — View findings grouped by severity with expandable cards
- Deliberation Timeline — Step-by-step visualization of agent decision process
- Metrics Dashboard — Charts showing verdicts, severities, and review trends
Quick Start
# Install dependencies
npm install
# Start development server
npm run dev
The dashboard runs at http://localhost:5173 by default.
Configuration
Set the API URL via environment variable:
# Development
VITE_API_URL=http://localhost:8000 npm run dev
# Or create a .env.local file
echo "VITE_API_URL=http://localhost:8000" > .env.local
npm run dev
If VITE_API_URL is not set, the dashboard assumes the API is served from the same
origin (useful when proxying through nginx in production).
Build for Production
# Type check and build
npm run build
# Preview production build
npm run preview
The build output is in the dist/ directory. Serve with any static file server or
use the included Docker configuration.
Docker
Build and run with Docker:
# Build image
docker build -t arbiter-dashboard .
# Run container
docker run -p 8080:80 arbiter-dashboard
The Docker image uses nginx to serve the static files and proxy API requests.
Project Structure
dashboard/
├── src/
│ ├── api/ # API client and query functions
│ │ ├── client.ts # Base fetch wrapper with error handling
│ │ └── reviews.ts # Review-specific API calls
│ ├── components/
│ │ ├── common/ # Shared UI components
│ │ │ ├── LoadingSpinner.tsx
│ │ │ ├── Pagination.tsx
│ │ │ └── SeverityBadge.tsx
│ │ ├── deliberation/ # Deliberation visualization
│ │ │ ├── ConflictCard.tsx
│ │ │ ├── DeliberationTimeline.tsx
│ │ │ └── VerdictBadge.tsx
│ │ ├── layout/ # App layout components
│ │ │ ├── Header.tsx
│ │ │ ├── Layout.tsx
│ │ │ └── Sidebar.tsx
│ │ └── reviews/ # Review-related components
│ │ ├── FindingCard.tsx
│ │ ├── ReviewCard.tsx
│ │ ├── ReviewFilters.tsx
│ │ └── ReviewList.tsx
│ ├── pages/ # Route pages
│ │ ├── MetricsPage.tsx
│ │ ├── ReviewDetailPage.tsx
│ │ └── ReviewsPage.tsx
│ ├── types/ # TypeScript type definitions
│ │ └── api.ts
│ ├── App.tsx # Root component with routing
│ └── main.tsx # Application entry point
├── public/ # Static assets
├── package.json
├── tsconfig.json
├── vite.config.ts
└── Dockerfile
Routes
| Path | Page | Description |
|---|---|---|
/ |
ReviewsPage | List of all reviews with filters |
/reviews/:id |
ReviewDetailPage | Single review with findings and deliberation |
/metrics |
MetricsPage | Aggregate statistics and charts |
Component Overview
Layout Components
- Layout — Main app layout with header, sidebar, and content area
- Header — Top navigation bar
- Sidebar — Navigation menu with links to reviews and metrics
Review Components
- ReviewList — Paginated list of review cards with filtering
- ReviewCard — Summary card showing review metadata and verdict
- ReviewFilters — Filter controls for repository, status, verdict, author
- FindingCard — Expandable card showing individual agent findings
Deliberation Components
- DeliberationTimeline — Vertical timeline showing deliberation steps
- ConflictCard — Displays detected conflicts between agents
- VerdictBadge — Color-coded badge for review verdicts (approve/changes/comment)
Common Components
- SeverityBadge — Color-coded badge for finding severities
- LoadingSpinner — Loading indicator
- Pagination — Page navigation controls
Tech Stack
| Technology | Purpose |
|---|---|
| React 19 | UI framework |
| React Router 7 | Client-side routing |
| TanStack Query | Data fetching and caching |
| Tailwind CSS 4 | Styling |
| Recharts | Charts and visualizations |
| Vite | Build tool and dev server |
| TypeScript | Type safety |
Development
Linting
npm run lint
Type Checking
npm run typecheck
Adding New Pages
- Create component in
src/pages/ - Add route in
src/App.tsx - Add navigation link in
src/components/layout/Sidebar.tsx
Adding API Endpoints
- Add types in
src/types/api.ts - Add query function in
src/api/reviews.ts - Use with
useQueryhook in component