# Novu Manage Preferences

> Configure notification preferences in Novu at the workflow and subscriber level. Set default channel preferences (email, SMS, push, chat, in-app), mark preferences as read-only or subscriber-editable, and manage subscriber-specific overrides. Use when setting up notification opt-in/opt-out, configuring per-channel delivery preferences, or building a preferences management UI.

- **Type:** Skill
- **Install:** `agentstack add skill-novuhq-skills-manage-preferences`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [novuhq](https://agentstack.voostack.com/s/novuhq)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [novuhq](https://github.com/novuhq)
- **Source:** https://github.com/novuhq/skills/tree/main/skills/manage-preferences
- **Website:** https://novu.co

## Install

```sh
agentstack add skill-novuhq-skills-manage-preferences
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Manage Preferences

Novu has a two-level preference system:
1. **Workflow defaults** — configured in the dashboard for UI based workflows or via code in framework based workflows, apply to all subscribers.
2. **Subscriber overrides** — set by end users, override workflow defaults

## Workflow-Level Preferences

Set default preferences when defining a workflow with `@novu/framework`:

```typescript
import { workflow } from "@novu/framework";

const alertWorkflow = workflow("system-alert", execute, {
  preferences: {
    all: { enabled: true, readOnly: false },
    channels: {
      email: { enabled: true },
      sms: { enabled: false },
      push: { enabled: true },
      chat: { enabled: false },
      inApp: { enabled: true },
    },
  },
});
```

> Authoring workflows in code? See [`framework-integration`](../framework-integration) for the full Framework setup, Bridge Endpoint, step controls, and deployment.

### Channel Types

| Channel | Description |
| --- | --- |
| `email` | Email notifications |
| `sms` | SMS text messages |
| `push` | Mobile/web push notifications |
| `chat` | Slack, Discord, Teams, etc. |
| `inApp` | In-app Inbox notifications |

### Read-Only Preferences

Set `readOnly: true` to **hide a workflow's channels from the Preferences UI** — subscribers can't toggle them on or off:

```typescript
const criticalAlertWorkflow = workflow("critical-alert", execute, {
  preferences: {
    all: { enabled: true, readOnly: true },  // subscriber CANNOT disable
  },
});
```

### `readOnly` vs `critical` — pick the right one

These are different mechanisms with different guarantees. See [`design-workflow/references/severity-and-critical.md`](../design-workflow/references/severity-and-critical.md) for the full matrix.

| Flag                                 | What it does                                                                                |
| ------------------------------------ | ------------------------------------------------------------------------------------------- |
| `preferences.all.readOnly: true`     | **UI only.** Hides the workflow from the Preferences UI so subscribers can't toggle it.     |
| `critical: true` (workflow-level)    | **Runtime.** Bypasses subscriber preferences, skips digest, runs without delays.            |

If you need the notification to **always be delivered** (account suspended, security alert, password reset), set `critical: true` — `readOnly: true` alone won't override existing subscriber overrides at runtime.

### Optional (Subscriber-Editable) Preferences

```typescript
const marketingWorkflow = workflow("weekly-newsletter", execute, {
  preferences: {
    all: { enabled: true, readOnly: false },  // subscriber CAN disable
    channels: {
      email: { enabled: true },
      sms: { enabled: false },  // off by default, subscriber can enable
    },
  },
});
```

## Subscriber-Level Preferences

Subscribers can override workflow defaults (unless `readOnly: true`).

### Get Subscriber Preferences

```typescript
import { Novu } from "@novu/api";

const novu = new Novu({
  secretKey: process.env.NOVU_SECRET_KEY,
});

const preferences = await novu.subscribers.preferences.list({
  subscriberId: "subscriber-123",
});
```

### Update Subscriber Preferences

```typescript
await novu.subscribers.preferences.update(
  {
    workflowId: "weekly-newsletter",
    channels: {
      email: false,   // opt out of email
      inApp: true,    // keep in-app
    },
  },
  "subscriber-123"
);
```

### Global Preferences

Update preferences across all workflows by omitting `workflowId`:

```typescript
await novu.subscribers.preferences.update(
  {
    channels: {
      sms: false,  // disable SMS for all workflows
    },
  },
  "subscriber-123"
);
```

## Preference Resolution Order

When Novu determines whether to deliver a notification:

1. **Subscriber workflow preference** (most specific) — subscriber's override for this specific workflow
2. **Subscriber global preference** — subscriber's default across all workflows
3. **Workflow default** — developer-defined default in code
4. **System default** — all channels enabled

The most specific preference wins. If a subscriber disables email for a specific workflow, that takes precedence even if their global email preference is enabled.

## Preferences UI Component

### React

```tsx
import { Inbox } from "@novu/react";

function App() {
  return (
    
      {/* The Preferences panel is built into the Inbox */}
    
  );
}
```

The `` component includes a built-in Preferences panel accessible via the settings icon.

### Standalone Preferences

Use the `` component independently:

```tsx
import { Inbox, Preferences } from "@novu/react";

function PreferencesPage() {
  return (
    
      
    
  );
}
```

## Common Patterns

### Critical Alerts (Always On)

```typescript
preferences: {
  all: { enabled: true, readOnly: true },
}
```

Subscribers cannot opt out. Use for security alerts, payment notifications, legal notices.

### Marketing (Opt-Out Friendly)

```typescript
preferences: {
  all: { enabled: true, readOnly: false },
  channels: {
    email: { enabled: true },
    sms: { enabled: false },
  },
}
```

Subscribers can toggle channels. SMS is off by default.

### In-App Only by Default

```typescript
preferences: {
  all: { enabled: false },
  channels: {
    inApp: { enabled: true },
  },
}
```

Only in-app is on. Subscribers can enable other channels if desired.

## Common Pitfalls

1. **`readOnly: true` is per-workflow, not per-channel** — you set `readOnly` on the `all` level. Individual channels inherit it.
2. **Subscriber overrides don't apply to `readOnly` workflows** — if the workflow is read-only, subscriber preferences are ignored.
3. **`enabled: false` in the workflow default means the channel is off** — subscribers can still enable it (unless `readOnly: true`).
4. **The Preferences UI only shows non-readOnly workflows** — read-only workflows are hidden from the subscriber's preference panel.
5. **Global preferences apply across all non-readOnly workflows** — they're a convenient "disable all email" setting, but workflow-specific preferences take precedence.

## References

- [Workflow Preferences Examples](./references/workflow-preferences-examples.md)
- [Subscriber Preferences Examples](./references/subscriber-preferences-examples.md)
- [Preferences UI Examples](./references/preferences-ui-examples.md)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [novuhq](https://github.com/novuhq)
- **Source:** [novuhq/skills](https://github.com/novuhq/skills)
- **License:** MIT
- **Homepage:** https://novu.co

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-novuhq-skills-manage-preferences
- Seller: https://agentstack.voostack.com/s/novuhq
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
