novu-design-workflow✓ Pass
Design notification workflows the Novu way — choose channels, set severity, decide when a workflow is critical, configure digests, and route based on subscriber state. Applies to BOTH dashboard-authored and code-first (`@novu/framework`) workflows. Use when planning a new workflow, deciding which channels to include, picking severity, configuring digest behavior, or matching a use case (order confirmation, payment failed, account suspended, comment, trial expiring, password reset, webhook fan-out, fetch-then-notify) to a proven template.
// Install Skill
Install Skill
Skills are third-party code from public GitHub repositories. SkillHub scans for known malicious patterns but cannot guarantee safety. Review the source code before installing.
Install globally (user-level):
npx skillhub install novuhq/novu/novu-design-workflowInstall in current project:
npx skillhub install novuhq/novu/novu-design-workflow --projectskill.install.customTargetHelp
npx skillhub install novuhq/novu/novu-design-workflow --target-dir /path/to/skillsSuggested path: ~/.claude/skills/novu-design-workflow/
SKILL.md Content
---
name: novu-design-workflow
description: Design notification workflows the Novu way — choose channels, set severity, decide when a workflow is critical, configure digests, and route based on subscriber state. Applies to BOTH dashboard-authored and code-first (`@novu/framework`) workflows. Use when planning a new workflow, deciding which channels to include, picking severity, configuring digest behavior, or matching a use case (order confirmation, payment failed, account suspended, comment, trial expiring, password reset, webhook fan-out, fetch-then-notify) to a proven template.
---
# Design Workflow
Design rules for any Novu workflow — independent of whether you author it in the **Dashboard** (no-code) or in **code** with [`@novu/framework`](../framework-integration). The decisions here (channels, severity, critical, digest, conditions) are the same on both surfaces; only the syntax differs.
> Authoring **in code**? Pair this skill with [`framework-integration/`](../framework-integration) for `workflow(...)`, `step.*`, `controlSchema`, and Bridge Endpoint setup.
> Authoring **in the Dashboard or via the Novu MCP**? After designing here, fill in step content (subject, body, `editorType`, headers, conditions) using [`dashboard-workflows/`](../dashboard-workflows).
## When to use this skill
Use it whenever you need to **decide what a workflow should look like**:
- "Design an order-confirmation workflow"
- "Which channels should I send for a payment failure?"
- "Make this notification critical"
- "Should this be digested?"
- "Add a fallback for offline subscribers"
- "What's the right template for X?"
Do **not** use it for: triggering an existing workflow ([`trigger-notification/`](../trigger-notification)), authoring code wrappers ([`framework-integration/`](../framework-integration)), or rendering severity in the UI ([`inbox-integration/`](../inbox-integration)).
## Severity & Critical
Two independent dials. Most workflows set **neither**.
| Dial | Values | Default | Effect |
| ---------- | ------------------------------- | ------------ | ------------------------------------------------------------------------------- |
| `severity` | `LOW` / `MEDIUM` / `HIGH` | unset | Visual prioritization in the Inbox (color, glow); informs digest skip rules. |
| `critical` | `true` / `false` | `false` | Bypass subscriber preferences, skip digest, no delays, all available channels. |
Rules of thumb:
- Leave `severity` unset for most workflows. Only set it when visual prioritization is needed.
- `HIGH` = "deal with this today" (payment failed, trial expiring tomorrow).
- `critical: true` = "deliver regardless of preferences" (account suspended, security alert, password reset).
- `critical: true` ⇒ digest is automatically skipped and channels deliver immediately.
See [`references/severity-and-critical.md`](./references/severity-and-critical.md) for the full behavior matrix and the `readOnly` vs `critical` distinction.
## Channel Selection
### If the user specified channels
Use **only** those channels. Do not add fallbacks. Do not add extras. If the requested channel isn't configured in the organization, add it anyway because the user explicitly asked for it.
> "Send a push notification when the order ships" → one `push` step. Nothing else.
### If the user did NOT specify channels
Pick from channels **configured in the organization**, in this priority order, up to **3 channels**:
```
In-App > Email > Chat > Push > SMS
```
| Channel | Use it for | Skip it when |
| ------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| In-App | Default for in-product content. Always include if the user is in your product. | The recipient can't see it (password reset, OTP, pre-signup) |
| Email | Receipts, documentation, async communication. Default fallback after In-App. | Pure conversational pings inside the product |
| Chat | If configured AND `severity >= MEDIUM`. Slack/Teams for ops & internal flows. | Marketing or low-severity nudges |
| Push | Fallback when subscriber is **offline** but needs immediate awareness. | Subscriber is online (use In-App instead) |
| SMS | Last resort. Only when no other channel works (true emergencies, OTP, regulatory). | Anything that fits in Email or Push |
See [`references/channel-selection.md`](./references/channel-selection.md) for the full decision tree.
## Digest Defaults
When you add a digest step, default to:
- `type: "regular"`
- look-back window: **5 minutes**
- digest time: **1 hour**
- key: `subscriberId` (and `+threadId` for conversational flows)
**Skip the digest** when:
- `severity: HIGH`, or
- `critical: true`
See [`references/digest-defaults.md`](./references/digest-defaults.md) for digest key composition and conversational examples.
## User-State Logic
Adapt routing based on whether the subscriber is online:
| State | Behavior |
| -------- | ------------------------------------------------------------------------------------------------------- |
| Online | Send In-App immediately. Skip Push. Delay Email/Chat based on severity. |
| Offline | Use Push or Chat to get attention. |
Default delays:
- **B2B** apps → next work hour
- **B2C** apps → ~30 minutes
The condition for "subscriber offline" is the same on both surfaces — see [`references/step-conditions.md`](./references/step-conditions.md).
## Workflow Templates
Match the use case to a template and copy its shape. Each template specifies severity, critical, actionable, and interaction type, plus the step ordering.
| # | Use case | Severity | Critical | Notes |
| - | ------------------------------ | -------- | -------- | ------------------------------------------------ |
| 1 | Order Confirmation | none | false | Digested, In-App + Email + Push (offline only) |
| 2 | Comment on Your Post | none | false | Digested by `subscriberId + threadId` |
| 3 | Payment Failed | HIGH | false | In-App + Chat + Email + Push (offline) |
| 4 | Account Suspended | HIGH | true | All channels, no preferences, no digest |
| 5 | Forgot Password | none | true | Email + SMS only, no In-App |
| 6 | Trial Expiring Tomorrow | HIGH | false | In-App + Chat + Email + Push (offline) |
| 7 | Explicit Channel Request | n/a | n/a | Use only the channels the user specified |
| 8 | Webhook / External API Call | varies | varies | Add `step.http` after channel steps |
| 9 | Fetch Data then Notify | varies | varies | `step.http` first; declare `responseBodySchema` |
Full ASCII flows + per-template metadata in [`references/workflow-templates.md`](./references/workflow-templates.md).
## Step Conditions
Conditions decide whether a step runs. Use them for "send only if subscriber is offline", "send email only if In-App wasn't seen", and similar fallbacks.
- **Dashboard** authors write [JSON-Logic](https://jsonlogic.com): `{ "==": [{ "var": "subscriber.isOnline" }, "false"] }`
- **Framework** authors pass a `skip: () => boolean` callback to the step.
The semantics are identical. See [`references/step-conditions.md`](./references/step-conditions.md) for the canonical snippets and the variables available in each scope.
## Common Pitfalls
1. **Don't set severity by default** — leave it unset unless you actually need visual prioritization.
2. **`critical: true` is not the same as `readOnly: true`** — `readOnly` only hides the workflow from the Preferences UI; `critical` bypasses preferences and digests at runtime. See [`references/severity-and-critical.md`](./references/severity-and-critical.md).
3. **Don't add fallbacks when the user named the channels** — explicit channel requests are exact.
4. **Cap the channel count at 3** when the user didn't specify channels. More channels = more annoyance, not more reach.
5. **Don't combine digest with `critical: true`** — critical workflows must deliver immediately. The digest step is auto-skipped.
6. **Digest key matters for conversational flows** — without `+threadId`, a comment on Post A and a comment on Post B end up in the same digest.
7. **Push only when offline** — sending push to an online user duplicates the In-App alert.
8. **HTTP step needs `responseBodySchema`** — without it, downstream steps can't read response properties via `{{ steps.<id>.<prop> }}`.
## References
- [Channel Selection](./references/channel-selection.md) — full decision tree and per-channel guidance
- [Severity & Critical](./references/severity-and-critical.md) — behavior matrix, preference & digest interactions, `readOnly` vs `critical`
- [Digest Defaults](./references/digest-defaults.md) — windows, keys, conversational digest patterns
- [Step Conditions](./references/step-conditions.md) — JSON-Logic snippets and Framework `skip` equivalents
- [Workflow Templates](./references/workflow-templates.md) — the 9 reference flows with severity/critical/interaction tables
## See Also
- [`dashboard-workflows/`](../dashboard-workflows) — author step content (subject, body, `editorType`, headers, conditions) for Dashboard or Novu MCP workflows
- [`framework-integration/`](../framework-integration) — implement these designs in code (`workflow()`, `step.*`, `controlSchema`, Bridge)
- [`manage-preferences/`](../manage-preferences) — how `critical` interacts with subscriber-level preferences
- [`inbox-integration/`](../inbox-integration) — how severity surfaces visually in the Inbox
- [`trigger-notification/`](../trigger-notification) — invoking a workflow once it's designed
License
No license was declared in this skill's source.
The full license text is available in the source repository.
View the license in the source repository — the version published there is authoritative.
// Install Skill
Install Skill
Skills are third-party code from public GitHub repositories. SkillHub scans for known malicious patterns but cannot guarantee safety. Review the source code before installing.
Install globally (user-level):
npx skillhub install novuhq/novu/novu-design-workflowInstall in current project:
npx skillhub install novuhq/novu/novu-design-workflow --projectskill.install.customTargetHelp
npx skillhub install novuhq/novu/novu-design-workflow --target-dir /path/to/skillsSuggested path: ~/.claude/skills/novu-design-workflow/