Skip to content
Development
Skill

/trigger-convex

Integrates Trigger.dev background tasks with Convex using @trigger.dev/convex. Use when triggering work transactionally from a Convex mutation, showing reactive run state, handling completion callbacks, combining Trigger Realtime with Convex, restoring jobs after reload, or

From plugin
triggerdev
17k11 skills3 agents

Claude Code

$ npx -y skills add triggerdotdev/trigger.dev --skill trigger-convex --agent claude-code

SKILL.md

trigger-convex.SKILL.md
name: trigger-convex
description: >
  Integrates Trigger.dev background tasks with Convex using @trigger.dev/convex.
  Use when triggering work transactionally from a Convex mutation, showing reactive
  run state, handling completion callbacks, combining Trigger Realtime with Convex,
  restoring jobs after reload, or repairing paused synchronization. Covers ownership,
  idempotency, scoped browser tokens, and credential-safe task payloads. Not for
  Convex-only applications or Trigger.dev applications without Convex.
license: Apache-2.0

Trigger.dev with Convex

Check the installed contract first

Locate `@trigger.dev/convex/package.json`, then read the adjacent `README.md` and `dist/client/index.d.ts`. In a non-hoisted installation, resolve the package with:

node -p "require.resolve('@trigger.dev/convex/package.json')"

Use the installed declarations as authority. Older releases do not expose `refresh()`. If it is absent, use durable polling or upgrade to a compatible release; do not invent a replacement method or accept browser-supplied run state. Keep the application's Convex version compatible with the package's peer dependency. Do not pin an arbitrary preview URL unless the user explicitly needs that preview.

Choose the relevant flow:

| Request | Approach | | --- | --- | | Enqueue a report, render, import, or AI task | Call `trigger.trigger` inside the application's authenticated mutation. | | Display durable status/results | Authorize the application's job, then call `trigger.getRun` from a query. | | Update application records on completion | Register a short internal mutation using `vRun`. | | Display responsive browser progress | Subscribe to Trigger Realtime; request an authorized Convex refresh on terminal events. | | Restore an edit after reload or leaving the page | Persist the selected application job/request ID and inputs; recover owned work from Convex. | | Recover paused status synchronization | Repair credentials/callback failures, then call authorized `resume`; do not enqueue another task. |

Install and configure

Install `@trigger.dev/convex` and `convex`. Deploy the actual task separately with Trigger.dev; the component does not deploy task code. Keep `TRIGGER_SECRET_KEY` only in the Convex server environment, for the intended Trigger environment.

// convex/convex.config.ts
import { defineApp } from "convex/server";
import triggerComponent from "@trigger.dev/convex/convex.config.js";

const app = defineApp();
app.use(triggerComponent);
export default app;

Run `npx convex dev` to generate the application's component references.

// convex/trigger.ts
import { Trigger } from "@trigger.dev/convex";
import { components } from "./_generated/api";

export const trigger: Trigger = new Trigger(components.trigger);

Constructor options are `secretKey`, `baseUrl`, and `onComplete`. The default API is `https://api.trigger.dev`; `TRIGGER_API_URL` is not automatically read by the component. Set `baseUrl` explicitly for a different API host. HTTP is allowed only for localhost development. Keep server keys out of `VITE_`/`NEXT_PUBLIC_` variables.

Enqueue atomically and authorize reads

Maintain an application-owned job table. The component has no user/tenant model. This example assumes an existing deployed `process-text` task that accepts `{ text }`. Validate business limits and authorize any referenced documents/files before enqueueing.

// convex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  jobs: defineTable({
    owner: v.string(),
    requestId: v.string(),
    text: v.string(),
    componentRunId: v.optional(v.string()),
  }).index("by_owner_request", ["owner", "requestId"])
    .index("by_componentRunId", ["componentRunId"]),
});
// convex/jobs.ts
import { vRun } from "@trigger.dev/convex";
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { trigger } from "./trigger";

export const request = mutation({
  args: { text: v.string(), requestId: v.string() },
  returns: v.id("jobs"),
  handler: async (ctx, args) => {
    const user = await ctx.auth.getUserIdentity();
    if (!user) throw new Error("Unauthorized");
    const owner = user.tokenIdentifier;
    const existing = await ctx.db.query("jobs")
      .withIndex("by_owner_request", q => q.eq("owner", owner).eq("requestId", args.requestId))
      .unique();
    if (existing) {
      if (existing.text !== args.text) throw new Error("Request ID reused for different input");
      return existing._id;
    }
    const jobId = await ctx.db.insert("jobs", { owner, ...args });
    const componentRunId = await trigger.trigger(ctx, "process-text", { text: args.text }, {
      idempotencyKey: `process-text:${owner}:${args.requestId}`,
    });
    await ctx.db.patch(jobId, { componentRunId });
    return jobId;
  },
});

export const status = query({
  args: { jobId: v.id("jobs") },
  returns: v.union(vRun, v.null()),
  handler: async (ctx, { jobId }) => {
    const user = await ctx.auth.getUserIdentity();
    const job = await ctx.db.get(jobId);
    if (!user || !job || job.owner !== user.tokenIdentifier) return null;
    return job.componentRunId ? trigger.getRun(ctx, job.componentRunId) : null;
  },
});

Preserve the same request ID when retrying an unconfirmed submission. Namespace component idempotency keys by tenant/owner, task, and logical request. They dedupe across the entire component instance, not just a task, and do not compare payloads. An application mutation rollback also rolls back the component enqueue/scheduling. Do not replace this with a direct SDK trigger from an action if atomicity is required. Use type-only task imports when adding task payload inference; do not bundle task implementations, Sharp, or provider clients into the Convex mutation runtime.

There are three di

Read more
@triggerdotdev
Ships withtriggerdev

The quickest way to get started is to create an account and project in our web app, and follow the instructions in the onboarding. Build and deploy your first task in minutes.

17k11 skills3 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
16.7k
Star history of triggerdotdev/trigger.dev on GitHub, a chart by star-history.com

Other skills on triggerdev.

drizzle

drizzle

Use this skill when writing or modifying Drizzle ORM schemas, queries, or migrations in this repo — specifically the…

errors-api-e2e

errors-api-e2e

End-to-end smoke test for the public Errors HTTP API (error groups). Seeds failed runs into ClickHouse so the error materialized…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about trigger-convex.

Which coding agents can use trigger-convex?
trigger-convex installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.