Dashboard
Use @sentry/junior-dashboard when you want browser access to Junior runtime diagnostics without exposing plugin, skill, or filesystem discovery publicly. The dashboard mounts into the same Nitro deployment as Junior, but its Better Auth session only protects dashboard routes.
Install
Section titled “Install”Install the dashboard package next to @sentry/junior:
pnpm add @sentry/junior-dashboardRegister the plugin
Section titled “Register the plugin”Register juniorDashboardPlugin() in the runtime-safe plugin set. Configure the
Google Workspace domain that should be allowed to view the dashboard:
import { defineJuniorPlugins } from "@sentry/junior";import { juniorDashboardPlugin } from "@sentry/junior-dashboard";
export const plugins = defineJuniorPlugins([ juniorDashboardPlugin({ allowedGoogleDomains: ["sentry.io"], trustedOrigins: ["https://<your-domain>"], }),]);createApp() reads that plugin set from Nitro’s virtual config:
import { createApp } from "@sentry/junior";
export default await createApp();Point the Junior Nitro module at the same plugin module:
import { defineConfig } from "nitro";import { juniorNitro } from "@sentry/junior/nitro";
export default defineConfig({ preset: "vercel", modules: [ juniorNitro({ plugins: "./plugins", }), ], routes: { "/**": { handler: "./server.ts" }, },});You can also provide the same authorization policy through deployment environment variables:
| Variable | Purpose |
|---|---|
JUNIOR_DASHBOARD_GOOGLE_DOMAINS | Comma-separated or JSON array of allowed Google domains. |
JUNIOR_DASHBOARD_ALLOWED_EMAILS | Comma-separated or JSON array of explicit email allowlist. |
JUNIOR_DASHBOARD_TRUSTED_ORIGINS | Comma-separated or JSON array of Better Auth trusted origins. |
JUNIOR_DASHBOARD_AUTH_REQUIRED | Set to false only for explicit local dashboard auth bypass. |
The dashboard package owns these routes:
| Route | Purpose |
|---|---|
/ | Authenticated command-center UI. |
/conversations | Authenticated conversation-history UI. |
/plugins | Authenticated plugin reporting UI. |
/api/dashboard/* | Authenticated dashboard JSON APIs. |
/api/auth/* | Better Auth Google login and callbacks. |
/health remains the public minimal Junior runtime health response.
The current dashboard API slices are:
| Endpoint | Purpose |
|---|---|
/api/dashboard/health | Health status for the command center pulse. |
/api/dashboard/runtime | Runtime paths, providers, skills, and packages. |
/api/dashboard/plugins | Loaded plugin list. |
/api/dashboard/skills | Discovered skill list. |
/api/dashboard/sessions | Recent conversation feed from turn-session checkpoints. |
/api/dashboard/conversation-stats | Aggregate conversation stats, people/place leaderboards, and sampling metadata. |
/api/dashboard/plugin-reports | Sanitized trusted-plugin operational summaries. |
/api/dashboard/conversations/:conversation | Expiring conversation transcript; private conversations return redacted metadata only. |
/api/dashboard/config | Safe dashboard config signals and feature readiness. |
/api/dashboard/me | Signed-in dashboard identity. |
The dashboard UI is a React client using React Router for browser views and TanStack Query to poll dashboard APIs. / shows command-center health, aggregate conversation stats, and recent turn durations; /conversations shows conversation history; /conversations/:conversation shows the transcript and turn/tool-call detail for one conversation; /plugins shows loaded plugin inventory and trusted plugin operational summaries. The dashboard does not wrap Slack webhooks, provider OAuth callbacks, sandbox egress, or /api/internal/*.
The conversation feed is a bounded metadata index with the same expiration policy as turn-session checkpoints. Conversation detail reads transcript data from the expiring checkpoint message store, so old transcripts disappear when checkpoint state expires. When SENTRY_DSN initializes the runtime and SENTRY_ORG_SLUG is set, conversation rows include a Sentry conversation link; when the runtime captures a trace ID, conversation detail shows it with the turn metadata.
The conversation stats endpoint is separate from the recent feed and includes sampleLimit, sampleSize, and truncated fields so the UI can mark bounded aggregates.
Dashboard dates use JUNIOR_TIMEZONE, defaulting to America/Los_Angeles.
For local dashboard visual QA, pass mockConversations: true to juniorDashboardPlugin() or set JUNIOR_DASHBOARD_MOCK_CONVERSATIONS=true for the env-configured path. The sample conversations are read-only reporting fixtures and appear before real session records.
Configure Google auth
Section titled “Configure Google auth”Create a Google OAuth client for the deployment origin. Add this redirect URI:
https://<your-domain>/api/auth/callback/googleSet the required environment variables:
| Variable | Purpose |
|---|---|
GOOGLE_CLIENT_ID | Google OAuth client ID. |
GOOGLE_CLIENT_SECRET | Google OAuth client secret. |
Dashboard cookies are signed with JUNIOR_SECRET by default. Set BETTER_AUTH_SECRET only when you need a separate rotation boundary for browser sessions.
Dashboard callbacks use JUNIOR_BASE_URL, Vercel URL envs, or local dev by default. Set BETTER_AUTH_URL only when dashboard auth needs a different public origin.
Verify
Section titled “Verify”After deployment:
GET https://<your-domain>/healthreturns a minimal health JSON response.GET https://<your-domain>/api/inforeturns404.- Opening
https://<your-domain>/starts Google login. - A user from the configured Google Workspace domain reaches the dashboard.
- A user outside the configured domain receives
403.
Next step
Section titled “Next step”Use Security Hardening to review production auth boundaries, then use Verify & Troubleshoot for deployment smoke checks.