Nasaq

CampaignComposer

Compose an email or WhatsApp broadcast with a live audience count, a rich or plain editor, a preview, a test send, pre-send checks, a confirmation and a send progress bar.

PreviewOpen ↗

Code

<CampaignComposer  audiences={[{ id: "all", label: "Everyone", counts: { email: 1240, whatsapp: 610 } }]}  variables={[{ key: "name", label: "Name", sample: "Sara" }]}  onSendTest={async (draft, to) => sendTest(draft, to)}  onSend={async (draft) => startSend(draft)}  progress={progress}/>

Marketing · beta

Live examples and controls: CampaignComposer in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/campaign-composer.json

One screen to send a message to many people. Choose the channel and the audience, watch how many people it will reach, write the message, see it as the reader will, send yourself a test, fix what the checks list, confirm, and follow the send.

When to use

  • Newsletters and one-off broadcasts by email or WhatsApp.

When not to use

  • Automated sequences: use a rule builder.
  • Reusable email layouts: use EmailTemplates.

Import

import { CampaignComposer } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"

Quick start

<CampaignComposer
  audiences={[{ id: "all", label: "Everyone", counts: { email: 1240, whatsapp: 610 } }]}
  variables={[{ key: "name", label: "Name", sample: "Sara" }]}
  onSendTest={async (draft, to) => sendTest(draft, to)}
  onSend={async (draft) => startSend(draft)}
  progress={progress}
/>

Anatomy

  • Left: channel toggle, audience select, live count, subject (email), editor, variable chips.
  • Right: preview (email frame at desktop or phone width, or a WhatsApp bubble), the checks list, send progress, "Send a test" and "Send campaign".
  • Dialogs: test send, and an alert dialog "Send to N people?".

Every email preview and WhatsApp bubble carries the unsubscribe footer, so the reader can always opt out.

API

PropTypeDescription
audiencesCampaignAudience[]{ id, label, description?, counts? }.
variablesEmailVariable[]{ key, label, sample }, filled per person.
defaultValue / onChangePartial<CampaignDraft> / (draft) => void{ channel, audienceId, subject, body }.
onCountAudience(audienceId, channel) => Promise<number>Live count, else audience.counts.
onSendTest(draft, to) => Promise<...>WhatsApp tests go to the workspace number only.
onSend(draft) => Promise<...>After confirmation.
progress{ sent, failed, total } or nullControlled. While set, the form locks.
onStopSending() => voidShows a stop button while sending.
sender, testRecipientShown in the email preview and test dialog.
labelsPartial<CampaignComposerLabels>Override any string.

Pure helpers: validateCampaign, campaignProgress, campaignPlainText, campaignUnknownVariables.

Examples

Drive progress from your queue: { sent: 480, failed: 3, total: 1240 }.

Accessibility

The count is a live status. Checks are a list with text. Progress is a named progressbar. The confirm step is an alert dialog.

RTL & i18n

English and Arabic ship. The email body direction follows the locale, addresses and numbers stay left-to-right.

Styling & tokens

Semantic tokens only. Channels are text, no brand mark is drawn.

Do / Don't

  • Do send a test first.
  • Don't send WhatsApp broadcasts to people who have not agreed to WhatsApp.

Lab

https://docs.nasaqui.com/?path=/docs/components-marketing-campaign-composer--docs

On this page