Context
Phase 3 of the PRD describes a developer dashboard — a UI for browsing events, viewing indexer status, and managing API keys. This is the operational interface that differentiates Trident from a raw API: it gives both operators and dApp developers a visual way to verify the indexer is working and to explore what events their contracts are generating.
Without a dashboard, debugging a silent indexer issue requires reading JSON from curl, which is inaccessible to non-technical stakeholders and slow even for engineers.
What needs to be built
Tech stack
Next.js 15 App Router + Tailwind CSS + shadcn/ui
Rationale:
- Next.js App Router gives us server components for the initial data load (fast first paint, SEO for the public explorer)
- Tailwind + shadcn/ui provides a professional design system with minimal setup
- Can be deployed to Vercel (free tier) or served as a static export from the Go API's
embed.FS
Location: dashboard/ at the monorepo root, with its own package.json.
Authentication
On first visit, the dashboard shows a login screen prompting for the API URL and an API key. These are stored in localStorage (appropriate for a developer tool — not a consumer app). Once entered, they persist across browser sessions.
A Disconnect button clears the stored credentials and returns to the login screen.
Pages
1. Events Browser (/)
The primary view. A filterable, paginated table of soroban_events:
| Column |
Notes |
| Ledger |
Monospace, links to Stellar Expert ledger page |
| Timestamp |
Relative ("2 minutes ago") with absolute on hover |
| Contract |
Truncated strkey with copy button |
| Topic 0 |
The primary event type (transfer, mint, etc.) |
| Tx Hash |
Truncated, links to Stellar Expert transaction |
| Type |
CONTRACT / SYSTEM / DIAGNOSTIC badge |
Filter bar (above the table): contract ID input, topic_0 dropdown (populated from recent values), ledger range inputs, network selector.
Live mode toggle: when enabled, the table polls the WebSocket and prepends new events without a page refresh. A "N new events" banner appears at the top, and clicking it scrolls to the new rows.
Event detail drawer: clicking a row opens a right-side drawer showing the full event JSON, decoded data field, all four topics, and a link to the Stellar Expert transaction.
2. Indexer Status (/status)
Data from GET /v1/stats/indexer:
- Lag gauge: a half-donut chart showing current lag vs threshold. Green < 50 ledgers, yellow 50-200, red > 200.
- Events/min chart: a sparkline of events indexed per minute over the last hour (requires polling
system_state or adding a time-series table — document the dependency)
- Last poll time: relative timestamp with status indicator (green dot = healthy, red = stalled)
- Total events indexed: large number with thousands separator
- Uptime: time since last restart (requires a
started_at field in system_state)
3. Contract Leaderboard (/contracts)
Data from GET /v1/stats/contracts:
A ranked list of contracts by event volume. Columns: rank, contract ID (truncated + copy), event count, last seen ledger, last seen time. Clicking a contract ID pre-fills the Events Browser filter and navigates to /.
Include a ledger range picker at the top (defaults to "last 10,000 ledgers").
4. API Keys (/keys) — Admin only
Only accessible if the admin key was used to log in (check by calling GET /v1/admin/keys — returns 403 if not admin):
- Table of all API keys (label, tier, created at, status)
- "Create Key" button: opens a modal, prompts for label and tier, shows the raw key once after creation with a copy button and a "This key will not be shown again" warning
- "Revoke" button on each row (with confirmation dialog)
Acceptance criteria
Dependencies
Context
Phase 3 of the PRD describes a developer dashboard — a UI for browsing events, viewing indexer status, and managing API keys. This is the operational interface that differentiates Trident from a raw API: it gives both operators and dApp developers a visual way to verify the indexer is working and to explore what events their contracts are generating.
Without a dashboard, debugging a silent indexer issue requires reading JSON from curl, which is inaccessible to non-technical stakeholders and slow even for engineers.
What needs to be built
Tech stack
Next.js 15 App Router + Tailwind CSS + shadcn/ui
Rationale:
embed.FSLocation:
dashboard/at the monorepo root, with its ownpackage.json.Authentication
On first visit, the dashboard shows a login screen prompting for the API URL and an API key. These are stored in
localStorage(appropriate for a developer tool — not a consumer app). Once entered, they persist across browser sessions.A
Disconnectbutton clears the stored credentials and returns to the login screen.Pages
1. Events Browser (
/)The primary view. A filterable, paginated table of
soroban_events:Filter bar (above the table): contract ID input, topic_0 dropdown (populated from recent values), ledger range inputs, network selector.
Live mode toggle: when enabled, the table polls the WebSocket and prepends new events without a page refresh. A "N new events" banner appears at the top, and clicking it scrolls to the new rows.
Event detail drawer: clicking a row opens a right-side drawer showing the full event JSON, decoded
datafield, all four topics, and a link to the Stellar Expert transaction.2. Indexer Status (
/status)Data from
GET /v1/stats/indexer:system_stateor adding a time-series table — document the dependency)started_atfield insystem_state)3. Contract Leaderboard (
/contracts)Data from
GET /v1/stats/contracts:A ranked list of contracts by event volume. Columns: rank, contract ID (truncated + copy), event count, last seen ledger, last seen time. Clicking a contract ID pre-fills the Events Browser filter and navigates to
/.Include a ledger range picker at the top (defaults to "last 10,000 ledgers").
4. API Keys (
/keys) — Admin onlyOnly accessible if the admin key was used to log in (check by calling
GET /v1/admin/keys— returns 403 if not admin):Acceptance criteria
npm run buildproduces a valid Next.js build with zero type errorsreact-json-viewor similar)Dependencies