Welcome to Chapter 2! In the previous chapter, we explored the “why” behind Trigger.dev, understanding its role in building robust, fault-tolerant AI agents and automated workflows. Now, it’s time to roll up our sleeves and dive into the “how.”
This chapter will guide you through setting up your local development environment for Trigger.dev v4-beta and creating your very first job. By the end, you’ll have a running Trigger.dev project, a basic understanding of its core components, and the satisfaction of seeing your first durable workflow execute. This hands-on experience is crucial for building confidence and understanding how Trigger.dev fits into your development stack.
Preparing Your Development Environment
Before we jump into Trigger.dev, let’s ensure your local machine has the necessary tools. Think of this as preparing your workshop before starting a new project.
Prerequisites: Node.js and npm
Trigger.dev projects typically run on Node.js and leverage npm (Node Package Manager) or Yarn for dependency management.
Node.js (LTS Version): Trigger.dev requires Node.js version 18 or higher. The current Long Term Support (LTS) release is always recommended for stability and ongoing support.
- Why it matters: Newer Node.js versions bring performance improvements, security fixes, and modern JavaScript features that Trigger.dev utilizes. Using an older version might lead to compatibility issues or missing features.
- Check your version: Open your terminal or command prompt and run:
node -v - If your version is older than 18, you’ll need to upgrade. We recommend using a Node Version Manager like
nvmfor easy switching between Node.js versions.- Official Node.js Downloads: https://nodejs.org/en/download
- nvm (Node Version Manager): https://github.com/nvm-sh/nvm
npm (or Yarn):
npmis usually installed automatically when you install Node.js.- Check your version:
npm -v - If you prefer Yarn, ensure it’s installed globally:
yarn -v - ⚡ Quick Note: While
npmis the default, Trigger.dev supportsyarnas well. The initialization process will adapt to your preference if you have Yarn installed.
- Check your version:
Core Concepts: Building Blocks of a Trigger.dev Workflow
Before we write any code, let’s establish a mental model for what we’re about to build. Understanding these core concepts will make the implementation steps much clearer.
What is a Trigger.dev Job?
At its heart, a Trigger.dev job is a durable, fault-tolerant function that executes in response to an event.
- What it is: A unit of work defined in your code that Trigger.dev manages. Think of it as a specific task, like “send a welcome email” or “process a payment.”
- Why it exists: To perform tasks reliably, even if your server crashes, the network goes down, or an external API is temporarily unavailable. Trigger.dev ensures the job either completes successfully or is retried until it does, providing robust operations in unpredictable environments.
- How it works: You define a job, specifying what event triggers it and what code it should run. Trigger.dev then orchestrates its execution, including retries, delays, and state management, ensuring its eventual completion.
Triggers and Events
Every Trigger.dev job starts with a trigger. This is how your job knows when to spring into action.
- Trigger: The condition that causes a job to start. This could be a scheduled interval (e.g., “every hour”), an incoming HTTP webhook event (e.g., “when a user signs up”), or a custom event you send programmatically.
- Event: The actual data payload that initiates a job. When a trigger fires, it often carries an event with relevant data for the job to process. For example, a
user.signed.upevent might carry the user’s ID and email address, which the job then uses to personalize a welcome message.
The Trigger.dev CLI
The Trigger.dev Command Line Interface (CLI) is your primary tool for initializing projects and interacting with the Trigger.dev platform.
- What it is: A command-line utility that helps you set up and manage your Trigger.dev projects.
- Why it exists: To streamline the initial setup, ensuring you have the correct project structure and dependencies, and to connect your local development environment to the Trigger.dev cloud service. It automates much of the boilerplate.
- How it works: We’ll use
npx trigger.dev@v4-beta initto scaffold a new project, which handles installing the necessary SDKs and creating boilerplate configuration files. This command allows you to use the CLI without a global installation.
Step-by-Step Implementation: Your First Workflow
Let’s get hands-on and create a simple “Hello World” job. This will demonstrate the full lifecycle from setup to execution.
Step 1: Create Your Project Directory
First, create a new directory for your Trigger.dev project and navigate into it. This keeps your project organized and separate from other codebases.
mkdir my-first-trigger-project
cd my-first-trigger-project
Step 2: Initialize Trigger.dev v4-beta
Now, we’ll use the Trigger.dev CLI to set up our project. We’ll specifically target the v4-beta version, as it’s the latest cutting-edge release, with General Availability (GA) expected around May/June 2026. This ensures you’re working with the most modern features.
npx trigger.dev@v4-beta init
- What’s happening here?
npx: This command executes a Node.js package without requiring you to globally install it first. It’s great for one-off commands or trying out new tools.trigger.dev@v4-beta: Specifies the Trigger.dev package and explicitly requests itsv4-betaversion.init: This is the command to initialize a new Trigger.dev project, setting up all the necessary files and configurations.
- Interactive Setup: The CLI will ask you a few questions to configure your project:
What framework are you using?: For this example, chooseNext.js. Even if you’re not building a full Next.js application, it provides a well-structured starting point for a Node.js project that integrates well with Trigger.dev.What is your project's root directory?: Press Enter to accept the default (.), meaning the current directory will be your project root.What is your API Key?: You’ll need to create an account on https://trigger.dev. Once logged in, navigate to Environments -> Development and copy your Secret Key. Paste it into the terminal.- 🧠 Important: Your API Key is sensitive. It’s typically stored in an environment variable (like in your
.envfile) and should never be committed directly to source control. Theinitcommand automatically adds it to your.envfile for local development.
- 🧠 Important: Your API Key is sensitive. It’s typically stored in an environment variable (like in your
- Output: After answering, the CLI will install dependencies and create several files and folders. You should see output similar to:
✔ What framework are you using? › Next.js ✔ What is your project's root directory? › . ✔ What is your API Key? › sk_... Installing dependencies... ... (npm/yarn install output) ... 🎉 Trigger.dev project initialized! Next steps: 1. Start your dev server: npm run dev 2. Go to your Trigger.dev dashboard to see your project: https://app.trigger.dev/orgs/...
Step 3: Understanding the Generated Project Structure
Let’s quickly look at the key files and folders the init command created. This gives you a map of your new Trigger.dev project.
package.json: Your project’s manifest file, listing scripts (likedev) and dependencies (e.g.,@trigger.dev/sdk,@trigger.dev/nextjs)..env: Contains yourTRIGGER_SECRET_KEYenvironment variable. This file is excluded from version control by default.trigger.config.ts: The main configuration file for your Trigger.dev project. This is where you configure things like your API key, base URL, and integrations.src/trigger/client.ts: Exports your initialized Trigger.dev client instance. This client is the bridge between your code and the Trigger.dev platform, used to define and register your jobs.src/trigger/index.ts: This is where you’ll define your Trigger.dev jobs. Theinitcommand might have added a sample job here, which we will modify or replace.
Step 4: Creating Your First “Hello World” Job
Now, let’s open src/trigger/index.ts in your code editor and add a very simple job. If there’s already a sample job, you can either modify it or add a new one alongside it.
Open src/trigger/index.ts:
// src/trigger/index.ts
import { trigger } from "./client";
import { eventTrigger } from "@trigger.dev/sdk";
// Define your first Trigger.dev job
trigger.defineJob({
// A unique identifier for your job.
// This is how Trigger.dev tracks and manages it across runs.
id: "hello-world",
// A human-readable name for your job, visible in the Trigger.dev dashboard.
name: "Hello World Job",
// Versioning helps manage changes to your job definitions over time.
// It allows for graceful updates without breaking in-flight jobs.
version: "1.0.0",
// The 'on' property defines what event will trigger this job.
// Here, we're using eventTrigger to listen for a custom named event.
on: eventTrigger({
// The name of the event this job listens for.
// Events are typically namespaced for clarity (e.g., "user.created", "order.processed").
name: "hello.world",
}),
// The 'run' function contains the actual logic of your job.
// It's an async function because jobs often involve asynchronous operations
// like API calls, database interactions, or delays.
run: async (payload, io, ctx) => {
// 'io.logger' is a special logger provided by Trigger.dev.
// Messages logged here will appear in your Trigger.dev dashboard for this specific job run,
// making debugging distributed workflows much easier than standard console.log.
io.logger.info("Hello, Trigger.dev!");
io.logger.info("Received payload:", payload);
// You can return any data from your job. This data will be stored as the job's output
// and is visible in the Trigger.dev dashboard.
return { message: "Success! Hello from your first Trigger.dev job!" };
},
});
// You can define more jobs here by calling trigger.defineJob again...
// For example:
// trigger.defineJob({
// id: "another-job",
// name: "Another Example Job",
// version: "1.0.0",
// on: eventTrigger({ name: "another.event" }),
// run: async (payload, io, ctx) => {
// io.logger.info("Another job ran!");
// return { status: "completed" };
// },
// });
import { trigger } from "./client";: This line imports thetriggerclient instance that was initialized insrc/trigger/client.ts. This client is your gateway to defining and interacting with the Trigger.dev platform.import { eventTrigger } from "@trigger.dev/sdk";: This imports theeventTriggerhelper. It’s a convenient way to specify that your job should activate when a particular named event is received.trigger.defineJob({...}): This is the core function for defining any Trigger.dev job. It takes a configuration object:id: A unique string identifier. This is crucial for Trigger.dev to track, manage, and display your job in the dashboard.name: A human-readable name for the job, which helps you identify it easily in the Trigger.dev dashboard.version: A semantic version string (e.g., “1.0.0”) for your job’s logic. This is important for durable execution, allowing Trigger.dev to manage different versions of your job gracefully.on: eventTrigger({ name: "hello.world" }): This tells Trigger.dev to run this job whenever an event with the namehello.worldis received.run: async (payload, io, ctx) => {...}: This is the heart of your job – the function containing the actual business logic.payload: An object containing the data sent with the incoming event.io: An object providing I/O operations managed by Trigger.dev, such as durable logging (io.logger), performing retriable API calls (io.runTask), and interacting with integrations. This is key for fault tolerance.ctx: Provides contextual information about the current job run, such asctx.id(the unique ID for this specific run).
io.logger.info(...): Unlikeconsole.log,io.logger.infois Trigger.dev’s durable logger. Logs here are captured, associated with the specific job run, and displayed in your Trigger.dev dashboard, making debugging distributed and long-running workflows significantly easier.
Step 5: Running Your Development Server
Now that we’ve defined our job, let’s start the development server. This will register your hello-world job with the Trigger.dev platform and allow it to listen for incoming events.
In your terminal, from your project’s root directory:
npm run dev
- What’s happening? This script (defined in your
package.json) typically starts your Node.js application. The Trigger.dev SDK within your application will connect to the Trigger.dev cloud service using yourTRIGGER_SECRET_KEY(from the.envfile) and register all the jobs you’ve defined. This connection ensures that Trigger.dev knows about your jobs and can orchestrate their execution. - Output: You should see output indicating that your server is running and that Trigger.dev has connected and registered your jobs. Look for messages like “Trigger.dev client connected” and “Registered job: hello-world”. Keep this terminal window open; it’s your local job worker.
Step 6: Triggering Your Job
With your development server running, your hello-world job is now active and waiting for a hello.world event. Let’s trigger it from the Trigger.dev dashboard!
- Open the Trigger.dev Dashboard: Go to https://app.trigger.dev and log in.
- Navigate to your Project: You should see your project listed on the dashboard. Click on it to enter your project’s overview.
- Go to the “Events” Tab: In the left sidebar of your project dashboard, find and click on “Events”.
- Send an Event: Click the “Send Event” button (or similar) to manually send an event.
Event Name: Typehello.world. This must exactly match thenameproperty you defined in youreventTriggerinsrc/trigger/index.ts.Payload: You can send some JSON data. For now, let’s keep it simple:{ "greeting": "world" }- Click “Send Event”.
- Observation:
- Immediately, your running
npm run devterminal should show yourio.logger.infomessages: “Hello, Trigger.dev!” and “Received payload: { greeting: ‘world’ }”. - In the Trigger.dev dashboard, go to the “Runs” tab. You should see a new entry for your “Hello World Job” with a “Succeeded” status. Click on this run to see the detailed logs, including your
io.logger.infomessages and the job’s final output.
- Immediately, your running
Congratulations! You’ve successfully set up your Trigger.dev environment, defined a durable job, and seen it execute. This is the foundation for all the powerful workflows you’ll build.
Mini-Challenge: Personalizing Your Greeting
Let’s make our “Hello World” job a little more interactive by using the data from the event payload.
Challenge: Modify the
hello-worldjob to accept anameproperty in its event payload. Instead of just logging “Hello, Trigger.dev!”, it should log a personalized greeting like “Hello, [name] from Trigger.dev!”.- Steps:
- Open and edit
src/trigger/index.ts. - Access the
nameproperty from thepayloadobject within therunfunction. - Update the
io.logger.infomessage to include the personalized name. - Restart your
npm run devserver (Ctrl+C to stop, thennpm run devagain) to register the updated job definition with Trigger.dev. This step is crucial for changes to take effect. - Trigger the job again from the Trigger.dev dashboard’s “Events” tab, but this time, send a payload like:
{ "name": "Alice" }
- Open and edit
- Steps:
Hint: The
payloadobject is just a standard JavaScript object. You can access its properties using dot notation (e.g.,payload.name). Remember to handle cases wherepayload.namemight not be provided (e.g., use a default greeting).What to observe/learn: This challenge reinforces how to pass dynamic data to your jobs and access it within the
runfunction, which is fundamental for building useful and context-aware workflows. Observe the new personalized greeting in both your terminal and the Trigger.dev dashboard logs for the specific job run.
Common Pitfalls & Troubleshooting
Even simple setups can hit snags. Here are a few common issues you might encounter during initial setup and how to resolve them.
npm run devNot Connecting to Trigger.dev:- Symptom: Your terminal shows “Trigger.dev client not connected”, “Failed to connect to Trigger.dev”, or similar errors, and your jobs don’t appear in the dashboard.
- Cause: The
TRIGGER_SECRET_KEYin your.envfile is incorrect, has leading/trailing spaces, or is missing. There might also be network issues preventing your local machine from reachingapi.trigger.dev, or a firewall blocking outbound connections. - Solution: Double-check your
TRIGGER_SECRET_KEYagainst the key displayed in your Trigger.dev dashboard (under Environments -> Development). Ensure there are no extra characters. Verify your internet connection. If on a corporate network, check for proxy settings or firewall rules that might restrict outbound traffic.
- Job Not Showing in Dashboard / Not Triggering:
- Symptom: You’ve run
npm run dev, and your terminal shows the client connected, but your job doesn’t appear in the dashboard’s “Jobs” list, or sending an event doesn’t cause it to run. - Cause: The
npm run devprocess isn’t actively running, or you haven’t restarted it after making changes to your job definition. Theidof your job intrigger.defineJobmight not match what you expect, or, most commonly, theeventTriggername (hello.world) doesn’t exactly match the event name you’re sending from the dashboard (it’s case-sensitive!). - Solution: Ensure your
npm run devterminal is active and shows “Registered job: [your-job-id]”. Always restart your dev server (Ctrl+Cthennpm run dev) after modifying job definitions. Carefully compare theidandeventTrigger.namein your code with how you’re interacting with the dashboard.
- Symptom: You’ve run
- Node.js Version Errors:
- Symptom:
npm installornpm run devfails with errors related to Node.js version, such as “Engine ’node’ is incompatible with this module.” - Cause: Your installed Node.js version is older than the minimum required (Node.js 18+).
- Solution: Upgrade Node.js to version 18 or higher using
nvm(recommended for managing multiple Node.js versions) or the official installer from nodejs.org.
- Symptom:
Summary
In this chapter, you’ve taken the crucial first steps in your Trigger.dev journey! You’ve moved from understanding the concepts to hands-on implementation, laying a solid foundation for more complex workflows.
Here’s a quick recap of what we covered:
- Environment Setup: We ensured your local development environment was ready, verifying Node.js (v18+) and npm/Yarn installations.
- Project Initialization: You used the powerful
npx trigger.dev@v4-beta initcommand to scaffold a new Trigger.dev project, setting up essential configuration and client files. - Core Concepts: We built a mental model for Trigger.dev by understanding what a job is, how triggers and events work, and the role of the CLI.
- First Job Creation: You defined a simple “Hello World” job in
src/trigger/index.ts, learning aboutdefineJob,eventTrigger,payload, and the durableio.logger. - Execution & Observation: You learned how to start your development server with
npm run devand trigger your job manually from the Trigger.dev dashboard, carefully observing its execution and logs. - Practical Application: You successfully completed a mini-challenge to personalize your job’s output, reinforcing how to pass and utilize dynamic data.
- Troubleshooting: We addressed common setup pitfalls like connection issues, job registration problems, and Node.js version mismatches.
You now have a foundational understanding of how to get a Trigger.dev project up and running, and how to define and execute your first durable background job. In the next chapter, we’ll dive deeper into the io object, exploring how to perform external API calls reliably and handle retries, which is essential for building robust AI agents and complex, fault-tolerant workflows.
References
- Trigger.dev GitHub Repository: https://github.com/triggerdotdev/trigger.dev
- Trigger.dev Documentation: https://trigger.dev
- Node.js Official Website: https://nodejs.org
- nvm (Node Version Manager): https://github.com/nvm-sh/nvm
This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.