- Full prompt management UI: list, detail, override, and version
management for AI prompts defined with `prompts.define()`
- Rich AI span inspectors for all AI SDK operations with token usage,
messages, and prompt context
- Real-time generation tracking with live polling and filtering
## Prompt management
Define prompts in your code with `prompts.define()`, then manage
versions and overrides from the dashboard without redeploying:
```typescript
import { task, prompts } from "@trigger.dev/sdk";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const supportPrompt = prompts.define({
id: "customer-support",
model: "gpt-4o",
variables: z.object({
customerName: z.string(),
plan: z.string(),
issue: z.string(),
}),
content: `You are a support agent for Acme SaaS.
Customer: {{customerName}} ({{plan}} plan)
Issue: {{issue}}
Respond with empathy and precision.`,
});
export const supportTask = task({
id: "handle-support",
run: async (payload) => {
const resolved = await supportPrompt.resolve({
customerName: payload.name,
plan: payload.plan,
issue: payload.issue,
});
const result = await generateText({
model: openai(resolved.model ?? "gpt-4o"),
system: resolved.text,
prompt: payload.issue,
...resolved.toAISDKTelemetry(),
});
return { response: result.text };
},
});
```
The prompts list page shows each prompt with its current version, model,
override status, and a usage sparkline over the last 24 hours.
From the prompt detail page you can:
- **Create overrides** to change the prompt template or model without
redeploying. Overrides take priority over the deployed version when
`prompt.resolve()` is called.
- **Promote** any code-deployed version to be the current version
- **Browse generations** across all versions with infinite scroll and
live polling for new results
- **Filter** by version, model, operation type, and provider
- **View metrics** (total generations, avg tokens, avg cost, latency)
broken down by version
## AI span inspectors
Every AI SDK operation now gets a custom inspector in the run trace
view:
- **`ai.generateText` / `ai.streamText`** — Shows model, token usage,
cost, the full message thread (system prompt, user message, assistant
response), and linked prompt details
- **`ai.generateObject` / `ai.streamObject`** — Same as above plus the
JSON schema and structured output
- **`ai.toolCall`** — Shows tool name, call ID, and input arguments
- **`ai.embed`** — Shows model and the text being embedded
For generation spans linked to a prompt, a "Prompt" tab shows the prompt
metadata, the input variables passed to `resolve()`, and the template
content from the prompt version.
All AI span inspectors include a compact timestamp and duration header.
## Other improvements
- Resizable panel sizes now persist across page refreshes (patched
`@window-splitter/state` to fix snapshot restoration)
- Run page panels also persist their sizes
- Fixed `<div>` inside `<p>` DOM nesting warnings in span titles and
chat messages
- Added Operations and Providers filters to the AI metrics dashboard
## Screenshots
<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 14
17@2x"
src="https://github.com/user-attachments/assets/f3e59989-a2fa-4990-a9d0-3cacda431868"
/>
<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 15
37@2x"
src="https://github.com/user-attachments/assets/2f2d02df-2d2b-44fb-ac6f-9153f6a6c387"
/>
<img width="3680" height="2392" alt="CleanShot 2026-03-21 at 10 15
54@2x"
src="https://github.com/user-attachments/assets/baa161e0-ef91-4fa4-a55f-986b71cccdf0"
/>
4.5 KiB
Webapp
Remix 2.1.0 app serving as the main API, dashboard, and orchestration engine. Uses an Express server (server.ts).
Verifying Changes
Never run pnpm run build --filter webapp to verify changes. Building proves almost nothing about correctness. The webapp is an app, not a public package — use typecheck from the repo root:
pnpm run typecheck --filter webapp # ~1-2 minutes
Only run typecheck after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
Note: Public packages (packages/*) use build instead. See the root CLAUDE.md for details.
Testing Dashboard Changes with Chrome DevTools MCP
Use the chrome-devtools MCP server to visually verify local dashboard changes. The webapp must be running (pnpm run dev --filter webapp from repo root).
Login
1. mcp__chrome-devtools__new_page(url: "http://localhost:3030")
→ Redirects to /login
2. mcp__chrome-devtools__click the "Continue with Email" link
3. mcp__chrome-devtools__fill the email field with "local@trigger.dev"
4. mcp__chrome-devtools__click "Send a magic link"
→ Auto-logs in and redirects to the dashboard (no email verification needed locally)
Navigating and Verifying
- take_snapshot: Get an a11y tree of the page (text content, element UIDs for interaction). Prefer this over screenshots for understanding page structure.
- take_screenshot: Capture what the page looks like visually. Use to verify styling, layout, and visual changes.
- navigate_page: Go to specific URLs, e.g.
http://localhost:3030/orgs/references-bc08/projects/hello-world-SiWs/env/dev/runs - click / fill: Interact with elements using UIDs from
take_snapshot. - evaluate_script: Run JS in the browser console for debugging.
- list_console_messages: Check for console errors after navigating.
Tips
- Snapshots can be very large on complex pages (200K+ chars). Use
take_screenshotfirst to orient, thentake_snapshotonly when you need element UIDs to interact. - The local seeded user email is
local@trigger.dev. - Dashboard URL pattern:
http://localhost:3030/orgs/{orgSlug}/projects/{projectSlug}/env/{envSlug}/{section}
Key File Locations
- Trigger API:
app/routes/api.v1.tasks.$taskId.trigger.ts - Batch trigger:
app/routes/api.v1.tasks.batch.ts - OTEL endpoints:
app/routes/otel.v1.logs.ts,app/routes/otel.v1.traces.ts - Prisma setup:
app/db.server.ts - Run engine config:
app/v3/runEngine.server.ts - Services:
app/v3/services/**/*.server.ts - Presenters:
app/v3/presenters/**/*.server.ts
Route Convention
Routes use Remix flat-file convention with dot-separated segments:
api.v1.tasks.$taskId.trigger.ts -> /api/v1/tasks/:taskId/trigger
Environment Variables
Access via env export from app/env.server.ts. Never use process.env directly.
For testable code, never import env.server.ts in test files. Pass configuration as options instead:
realtimeClient.server.ts(testable service, takes config as constructor arg)realtimeClientGlobal.server.ts(creates singleton with env config)
Run Engine 2.0
The webapp integrates @internal/run-engine via app/v3/runEngine.server.ts. This is the singleton engine instance. Services in app/v3/services/ call engine methods for all run lifecycle operations (triggering, completing, cancelling, etc.).
The engineVersion.server.ts file determines V1 vs V2 for a given environment. New code should always target V2.
Background Workers
Background job workers use @trigger.dev/redis-worker:
app/v3/commonWorker.server.tsapp/v3/alertsWorker.server.tsapp/v3/batchTriggerWorker.server.ts
Do NOT add new jobs using zodworker/graphile-worker (legacy).
Real-time
- Socket.io:
app/v3/handleSocketIo.server.ts,app/v3/handleWebsockets.server.ts - Electric SQL: Powers real-time data sync for the dashboard
Legacy V1 Code
The app/v3/ directory name is misleading - most code is actively used by V2. Only these specific files are V1-only legacy:
app/v3/marqs/(old MarQS queue system)app/v3/legacyRunEngineWorker.server.tsapp/v3/services/triggerTaskV1.server.tsapp/v3/services/cancelTaskRunV1.server.tsapp/v3/authenticatedSocketConnection.server.tsapp/v3/sharedSocketConnection.ts
Some services (e.g., cancelTaskRun.server.ts, batchTriggerV3.server.ts) branch on RunEngineVersion to support both V1 and V2. When editing these, only modify V2 code paths.