Skip to main content
Novu allows you to write step handlers as TypeScript code in your project and publish them to Novu as serverless functions. Instead of configuring notification content in a visual editor, you define a handler file that returns the output for your step. Novu calls it at send time with the subscriber data, trigger payload, and any dashboard-defined controls. You can create both UI-managed steps and code-managed steps within the same workflow.
Code steps are only supported in the US region. We are working on supporting this in EU region.

Supported channels

Quick Start

1

Create workflow and step in the UI

Create a workflow and add any channel step in the workflow from UI. Once the step is added. Go to the step editor and Toggle the switch to Custom Code from Editor option to enable custom code for this step.
2

Get the CLI command from the dashboard

The Novu dashboard shows a prefilled publish command in the step editor screen, click on the Copy button to copy the command. It includes your secret key, workflow ID, step ID, and API URL.
3

Run the CLI command in your project

The CLI supports the following flags and options:The CLI will perform the following:
  1. Look up the step type from the Novu API.
  2. Auto-scaffold a placeholder handler at novu/<workflowId>/<stepId>.step.tsx.
  3. Bundle all handlers in the novu/ directory.
  4. Deploy to Novu.
For email steps, you can optionally link a React Email template directly:
If you dont want to pass secret key to CLI, it will try to read NOVU_SECRET_KEY variable from .env file if present.Also similarly for apiUrl, by default it uses US, but you can specify EU or other regions either in novu.config.ts or directly in CLI command.
4

Edit the handler

The generated file will be located at novu/<workflowId>/<stepId>.step.tsx. The folder name is the workflowId. The CLI reads it from the path at publish time. You should commit this file to your repository.Open the generated file and replace the placeholder content with your real logic. Each handler receives the full context:
novu/workflow-id/step-id.step.tsx
5

Republish when you make changes

If the bundle content changed, Novu deploys a new version. This publish command by default will publish all step handler in novu folder, if you want to publish just one workflow or one step you can specify --workflow and --step flags

Defining Controls (Optional)

Controls allow dashboard users to override specific values without changing code. You can define a controlSchema using Zod or plain JSON Schema:
After publishing, the dashboard renders form fields for each control property.

Controls vs Payload

Skipping a Step Conditionally

Use skip to prevent a step from executing at runtime based on your logic. The function receives (controls, ctx) where ctx contains payload, subscriber, context, and steps.
skip is not called during preview. You will always see the step output in the dashboard preview regardless of the skip condition.

Provider Overrides

Provider overrides let you customize the raw request sent to the underlying notification provider for a step. This is useful for setting provider-specific options not exposed by Novu standard output schema.
The _passthrough field merges directly into the API body sent to the provider. You can also set headers and query for header and query string overrides.

Disabling Output Sanitization

Novu sanitizes HTML in email and in_app outputs by default to prevent XSS vulnerabilities. To opt out, you can set disableOutputSanitization:

Configuration File (Optional)

You can create a novu.config.ts file for advanced use cases:

TypeScript Support

You can install @novu/framework as a dev dependency to get full TypeScript types for controls, payload, subscriber, context, and steps:
The CLI publishes to non production environments only. Publishing directly to Production is blocked. To promote changes to Production, use the Publish changes button in the Novu dashboard.

Frequently Asked Questions

Frequently asked questions related to code steps:

What is the attachment limit for email type code step

If email step is created using custom code, then maximum attachment size limit is 7MB. Checkout the ending email attachments documentation to learn on how to send the email attachments while triggering the workflow.

Troubleshooting