RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/CLAUDE.md/triggerdotdev/trigger.dev

CLAUDE.md

apps/webapp/CLAUDE.md
CLAUDE.md

Quality

88/100

Scores the file, not the repository.

Length

1,119 words

19 headings · 3 code blocks

Repository

16k

— · pushed 0 days ago

Last changed

3 days ago

First indexed 3 days ago.
triggerdotdev/trigger.dev/apps/webapp/CLAUDE.mdRawGitHub
1# Webapp
2 
3Remix 2.17.4 app serving as the main API, dashboard, and orchestration engine. Uses an Express server (`server.ts`).
4 
5## Verifying Changes
6 
7**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:
8 
9```bash
10pnpm run typecheck --filter webapp # ~1-2 minutes
11```
12 
13Only run typecheck after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
14 
15Note: Public packages (`packages/*`) use `build` instead. See the root CLAUDE.md for details.
16 
17## Testing Dashboard Changes with Chrome DevTools MCP
18 
19Use the `chrome-devtools` MCP server to visually verify local dashboard changes. The webapp must be running (`pnpm run dev --filter webapp` from repo root).
20 
21### Login
22 
23```
241. mcp__chrome-devtools__new_page(url: "http://localhost:3030")
25 → Redirects to /login
262. mcp__chrome-devtools__click the "Continue with Email" link
273. mcp__chrome-devtools__fill the email field with "local@trigger.dev"
284. mcp__chrome-devtools__click "Send a magic link"
29 → Auto-logs in and redirects to the dashboard (no email verification needed locally)
30```
31 
32### Navigating and Verifying
33 
34- **take_snapshot**: Get an a11y tree of the page (text content, element UIDs for interaction). Prefer this over screenshots for understanding page structure.
35- **take_screenshot**: Capture what the page looks like visually. Use to verify styling, layout, and visual changes.
36- **navigate_page**: Go to specific URLs, e.g. `http://localhost:3030/orgs/references-bc08/projects/hello-world-SiWs/env/dev/runs`
37- **click / fill**: Interact with elements using UIDs from `take_snapshot`.
38- **evaluate_script**: Run JS in the browser console for debugging.
39- **list_console_messages**: Check for console errors after navigating.
40 
41### Tips
42 
43- Snapshots can be very large on complex pages (200K+ chars). Use `take_screenshot` first to orient, then `take_snapshot` only when you need element UIDs to interact.
44- The local seeded user email is `local@trigger.dev`.
45- Dashboard URL pattern: `http://localhost:3030/orgs/{orgSlug}/projects/{projectSlug}/env/{envSlug}/{section}`
46 
47## Key File Locations
48 
49- **Trigger API**: `app/routes/api.v1.tasks.$taskId.trigger.ts`
50- **Batch trigger**: `app/routes/api.v1.tasks.batch.ts`
51- **OTEL endpoints**: `app/routes/otel.v1.logs.ts`, `app/routes/otel.v1.traces.ts`
52- **Prisma setup**: `app/db.server.ts`
53- **Run engine config**: `app/v3/runEngine.server.ts`
54- **Services**: `app/v3/services/**/*.server.ts`
55- **Presenters**: `app/v3/presenters/**/*.server.ts`
56 
57## Route Convention
58 
59Routes use Remix flat-file convention with dot-separated segments:
60`api.v1.tasks.$taskId.trigger.ts` -> `/api/v1/tasks/:taskId/trigger`
61 
62## Abort Signals
63 
64**Never use `request.signal`** for detecting client disconnects. It is broken due to a Node.js bug ([nodejs/node#55428](https://github.com/nodejs/node/issues/55428)) where the AbortSignal chain is severed when Remix internally clones the Request object. Instead, use `getRequestAbortSignal()` from `app/services/httpAsyncStorage.server.ts`, which is wired directly to Express `res.on("close")` and fires reliably.
65 
66```typescript
67import { getRequestAbortSignal } from "~/services/httpAsyncStorage.server";
68 
69// In route handlers, SSE streams, or any server-side code:
70const signal = getRequestAbortSignal();
71```
72 
73## Environment Variables
74 
75Access via `env` export from `app/env.server.ts`. **Never use `process.env` directly.**
76 
77For testable code, **never import env.server.ts** in test files. Pass configuration as options instead:
78- `realtime/nativeRealtimeClient.server.ts` (testable service, takes config as constructor arg)
79- `realtime/nativeRealtimeClientInstance.server.ts` (creates singleton with env config)
80 
81## Run Engine 2.0
82 
83The 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.).
84 
85The `engineVersion.server.ts` file determines V1 vs V2 for a given environment. New code should always target V2.
86 
87## Background Workers
88 
89Background job workers use `@trigger.dev/redis-worker`:
90- `app/v3/commonWorker.server.ts`
91- `app/v3/alertsWorker.server.ts`
92- `app/v3/batchTriggerWorker.server.ts`
93 
94## Real-time
95 
96- Socket.io: `app/v3/handleSocketIo.server.ts`, `app/v3/handleWebsockets.server.ts`
97- Electric SQL: Powers real-time data sync for the dashboard
98 
99## v3 (engine V1) removed
100 
101v3 (engine V1: MarQS + Graphile worker) is end-of-life and its execution code is gone. The `app/v3/` directory name is historical; everything under it now serves V2. There is no V1 execution path: a `RunEngineVersion` `V1` branch (e.g. in `triggerTask.server.ts`, `cancelTaskRun.server.ts`) only rejects/finalizes gracefully so v3 clients get a clean 4xx, never a 5xx. Do not reintroduce V1. See `.claude/rules/legacy-v3-code.md` for the deprecation boundary.
102 
103## Performance: Trigger Hot Path
104 
105The `triggerTask.server.ts` service is the **highest-throughput code path** in the system. Every API trigger call goes through it. Keep it fast:
106 
107- **Do NOT add database queries** to `triggerTask.server.ts` or `batchTriggerV3.server.ts`. Task defaults (TTL, etc.) are resolved via `backgroundWorkerTask.findFirst()` in the queue concern (`queues.server.ts`) - one query per request, in mutually exclusive branches depending on locked/non-locked path. Piggyback on the existing query instead of adding new ones.
108- **Two-stage resolution pattern**: Task metadata is resolved in two stages by design:
109 1. **Trigger time** (`triggerTask.server.ts`): Only TTL is resolved from task defaults. Everything else uses whatever the caller provides.
110 2. **Dequeue time** (`dequeueSystem.ts`): Full `BackgroundWorkerTask` is loaded and retry config, machine config, maxDuration, etc. are resolved against task defaults.
111- If you need to add a new task-level default, **add it to the existing `select` clause** in the `backgroundWorkerTask.findFirst()` query — do NOT add a second query. If the default doesn't need to be known at trigger time, resolve it at dequeue time instead.
112- Batch triggers (`batchTriggerV3.server.ts`) follow the same pattern — keep batch paths equally fast.
113 
114## Prisma Query Patterns
115 
116- **Always use `findFirst` instead of `findUnique`.** Prisma's `findUnique` has an implicit DataLoader that batches concurrent calls into a single `IN` query. This batching cannot be disabled and has active bugs even in Prisma 6.x: uppercase UUIDs returning null (#25484, confirmed 6.4.1), composite key SQL correctness issues (#22202), and 5-10x worse performance than manual DataLoader (#6573, open since 2021). `findFirst` is never batched and avoids this entire class of issues.
117 
118## Transactions
119 
120- **Always use the `$transaction` helper from `~/db.server`, never `prisma.$transaction` (or `$replica.$transaction`) directly.** The helper wraps the raw call with tracing (an OTEL span + an `isolation_level` attribute) and boundary logging for infrastructure errors (e.g. `PrismaClientInitializationError`) that the raw client swallows. Signature: `$transaction(prisma, name?, async (tx) => { ... }, options?)`.
121- Pass the isolation level via options as a string: `{ isolationLevel: "Serializable" }`. Reach for `Serializable` when a read-then-write must be atomic against concurrent transactions (e.g. a count-then-delete invariant); the loser of a race fails and can retry, which is the right trade for rare, correctness-critical paths.
122- The helper returns `R | undefined` — guard the result (`if (!result) throw ...`) when callers need a definite value.
123 
124## PAT-authenticated API routes
125 
126- **A PAT route must resolve its target org/project scoped to the caller's membership** (`members: { some: { userId } }`, or a helper like `findProjectByRef` / `resolveOrganizationForApiUser`). A PAT is user-scoped and can name any org/project by id/slug, and the OSS RBAC fallback ability is permissive — so `ability.can(...)` alone does NOT reject a non-member on self-hosted. The RBAC `authorization` gate enforces the *role*; the membership-scoped query is the *tenant* floor. Skipping it opens cross-org access on OSS.
127 
128## React Patterns
129 
130- Only use `useCallback`/`useMemo` for context provider values, expensive derived data that is a dependency elsewhere, or stable refs required by a dependency array. Don't wrap ordinary event handlers or trivial computations.
131- Use named constants for sentinel/placeholder values (e.g. `const UNSET_VALUE = "__unset__"`) instead of raw string literals scattered across comparisons.
132 

Commands it names

  • pnpm run typecheck --filter webapp
  • pnpm run build --filter webapp
  • pnpm run dev --filter webapp

Sections

  • Webapp
  • Verifying Changes
  • Testing Dashboard Changes with Chrome DevTools MCP
  • Login
  • Navigating and Verifying
  • Tips
  • Key File Locations
  • Route Convention
  • Abort Signals
  • Environment Variables
  • Run Engine 2.0
  • Background Workers
  • Real-time
  • v3 (engine V1) removed
  • Performance: Trigger Hot Path
  • Prisma Query Patterns
  • Transactions
  • PAT-authenticated API routes
  • React Patterns

What it covers

setupbuildtestcode-stylesecuritydatabaseapiperformancedo-not

Stack — with the evidence

typescript

(1.00)

prisma

(1.00)

vite

(1.00)

vitest

(1.00)

playwright

(1.00)

node

(0.85)

pnpm

(0.85)

react

(0.70)

remix

(0.70)

express

(0.70)

drizzle

(0.70)

postgres

(0.70)

redis

(0.70)

tailwind

(0.70)

vercel

(0.70)

aws

(0.70)

javascript

(0.60)

turborepo

(0.60)

monorepo

(0.60)

github-actions

(0.60)

Format

CLAUDE.md

Claude Code's memory file. Shaped like AGENTS.md but with two things it lacks: @path imports, so shared rules live in one place, and a user-scope layer that follows the developer across repos rather than shipping with the code.

What the corpus says about it

Repository

Owner
triggerdotdev
Language
—
License
—
Archived
no

All configs in this repo

Also in triggerdotdev/trigger.dev

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
triggerdotdev/trigger.devpackages/cli-v3/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18deploymentdo-notdocs51/1003 days ago
triggerdotdev/trigger.dev.cursor/rules/executing-commands.mdc · 16kCursor rulestypescriptprisma+18test49/1003 days ago
triggerdotdev/trigger.dev.cursor/rules/otel-metrics.mdc · 16kCursor rulestypescriptprisma+18styledo-not61/1003 days ago
triggerdotdev/trigger.dev.cursor/rules/webapp.mdc · 16kCursor rulestypescriptprisma+18setuptestsecurity55/1003 days ago
triggerdotdev/trigger.dev.cursor/rules/writing-tasks.mdc · 16kCursor rulestypescriptprisma+18setupbuildarchtypes+564/1003 days ago
triggerdotdev/trigger.dev.github/copilot-instructions.md · 16kCopilot instructionstypescriptprisma+18teststyletypes32/1003 days ago
triggerdotdev/trigger.devAGENTS.md · 16kAGENTS.mdtypescriptprisma+18setupbuildtestlint-format+888/1003 days ago
triggerdotdev/trigger.devapps/supervisor/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18no sections25/1003 days ago
triggerdotdev/trigger.devinternal-packages/clickhouse/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+19styletypesdo-not61/1003 days ago
triggerdotdev/trigger.devinternal-packages/database/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18typesdatabasedo-not65/1003 days ago
triggerdotdev/trigger.devinternal-packages/run-engine/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18buildteststyle70/1003 days ago
triggerdotdev/trigger.devpackages/core/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18no sections31/1003 days ago
triggerdotdev/trigger.devpackages/redis-worker/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18test29/1003 days ago
triggerdotdev/trigger.devpackages/trigger-sdk/CLAUDE.md · 16kCLAUDE.mdtypescriptprisma+18do-not54/1003 days ago
Diff against packages/cli-v3/CLAUDE.md Diff against .cursor/rules/executing-commands.mdc Diff against .cursor/rules/otel-metrics.mdc Diff against .cursor/rules/webapp.mdc Diff against .cursor/rules/writing-tasks.mdc Diff against .github/copilot-instructions.md Diff against AGENTS.md Diff against apps/supervisor/CLAUDE.md Diff against internal-packages/clickhouse/CLAUDE.md Diff against internal-packages/database/CLAUDE.md Diff against internal-packages/run-engine/CLAUDE.md Diff against packages/core/CLAUDE.md Diff against packages/redis-worker/CLAUDE.md Diff against packages/trigger-sdk/CLAUDE.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
Adit-Jain-srm/NightmareNetCLAUDE.md · 45CLAUDE.mdtypescriptpython+18buildtestlint-formatstyle+6100/1003 days ago
nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4kCLAUDE.mdtypescriptnode+16setupbuildstylearch+2100/1003 days ago
dotCMS/corecore-web/CLAUDE.md · 949CLAUDE.mdjavanode+13teststylearchtesting-strategy+3100/1003 days ago
microsoft/playwrightCLAUDE.md · 94kCLAUDE.mdtypescriptjavascript+10buildtestlint-formatstyle+7100/1003 days ago
filamentphp/filamentCLAUDE.md · 32kCLAUDE.mdphplaravel+5buildtestlint-formatstyle+7100/1003 days ago
bagisto/bagistoCLAUDE.md · 28kCLAUDE.mdphplaravel+8setupbuildteststyle+5100/1003 days ago
dotCMS/coreCLAUDE.md · 949CLAUDE.mdjavanode+9setupbuildteststyle+799/100today
lollipopkit/flutter_server_boxCLAUDE.md · 8.3kCLAUDE.mddartflutter+8buildteststylearch+298/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack