{
  "slug": "comment-notification-batching",
  "title": "Comment notification batching: template and code",
  "url": "https://www.courier.com/recipes/comment-notification-batching",
  "markdown": "https://www.courier.com/recipes/comment-notification-batching.md",
  "stage": "Engagement",
  "purpose": "Turn a burst of comments into one notification instead of one per comment.",
  "summary": "Comment notification batching turns a burst of comments into one notification instead of one per comment. When the comments stop for 10 minutes, or an hour after the first one, or at 100 comments, it sends one Inbox message and one email with the count and the latest five. Reading the comments first cancels it.",
  "channels": [
    "inbox",
    "email"
  ],
  "shape": "journey",
  "shows": [
    "A batch node that rolls a burst into one send",
    "The count and the latest comments in one message",
    "Dropping the notification once they've read it"
  ],
  "data": [
    {
      "name": "author_name",
      "type": "string",
      "example": "Sam"
    },
    {
      "name": "comment_text",
      "type": "string",
      "example": "Can we ship Friday?"
    },
    {
      "name": "thread_title",
      "type": "string",
      "example": "Q4 launch plan"
    },
    {
      "name": "profile.first_name",
      "type": "string",
      "example": "Dana",
      "note": "From the profile. Write it when the user signs up. The emails say \"there\" when it's missing"
    },
    {
      "name": "batch.count",
      "type": "number",
      "example": "3",
      "note": "Set by the batch node, not your data"
    }
  ],
  "steps": [
    {
      "step": "1",
      "when": "10 quiet minutes after the last comment, 1 hour after the first, or at 100 comments",
      "channels": "Inbox, Email",
      "templates": [
        "templates/comment-batch-inbox.json",
        "templates/comment-batch-email.json"
      ]
    }
  ],
  "files": {
    "journey": "journey.json",
    "templates": [
      "templates/comment-batch-inbox.json",
      "templates/comment-batch-email.json"
    ],
    "setup": [
      "setup.ts"
    ],
    "start": [
      "start.ts",
      "start.py"
    ],
    "stop": [
      "stop.ts",
      "stop.py"
    ]
  },
  "docs": [
    "https://www.courier.com/docs/journeys/nodes/batch",
    "https://www.courier.com/docs/guides/notify-everyone-watching",
    "https://www.courier.com/docs/in-app/send-to-the-inbox",
    "https://www.courier.com/docs/journeys/nodes/cancel",
    "https://www.courier.com/docs/journeys/invoke"
  ],
  "related_recipes": [
    "https://www.courier.com/recipes/weekly-digest-email",
    "https://www.courier.com/recipes/team-invite-reminder-email",
    "https://www.courier.com/recipes/feature-adoption-email-sequence"
  ],
  "agent_prompt": "Batch comment notifications in this app, sent through Courier: when comments arrive in a burst, send each person one in-app and email notification with the count and the latest comments, not one per comment. Follow the steps at https://www.courier.com/recipes/comment-notification-batching.md and use the Courier skill for SDK details.\n\n1. Create the journey and its templates in my Courier workspace by replacing the comments link in the template files with our own, then running setup.ts from that page with COURIER_API_KEY from our environment. Save the journey ID it prints as COURIER_COMMENTS_JOURNEY_ID.\n2. Find where this codebase saves a new comment and start the journey there, once for each person who should hear about it (everyone following the thread except the author). Pass the fields in the Data fields table from our own data, and make sure first_name is written to each person's Courier profile at signup.\n3. Find where a user opens the comments and cancel the journey with the token comments-<user_id>.\n4. Match this codebase's language, file layout, and error handling. Never hardcode the API key.\n5. When you're done, add three comments for a test user a few seconds apart, and once the batch releases 10 minutes later, show me the steps of the run that sent.",
  "status": {
    "state": "passing",
    "last_tested": "2026-10-19"
  }
}
