Email Notification Expert logo

Email Notification Expert

Community
roedyrustam
email-notification-expert

Transactional email (Resend), React Email, and notification pipelines / Email transaksional (Resend), React Email, dan pipeline notifikasi.

Overview

Publisherroedyrustam
Repositoryvibes-plug
Skill nameemail-notification-expert
Stars
117
Forks
27
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by roedyrustam on GitHub. Read the source before you install it.

Installation

Install the Email Notification Expert AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/roedyrustam/vibes-plug/tree/main/skills/email-notification-expert
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/roedyrustam/vibes-plug.git /tmp/vibes-plug
mkdir -p .claude/skills
cp -r /tmp/vibes-plug/skills/email-notification-expert .claude/skills/email-notification-expert
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Email Notification Expert in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Email Notification Expert on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Email Notification Expert is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Email & Notification Expert (2026 Edition)

English | Bahasa Indonesia


English

Orchestration & Integration

  • Upstream Orchestrators: Works under brainstorming and zero-to-prod-orchestrator (Phase 4 - Backend, Messaging & Notification Pipelines) to deliver transactional and notification services.
  • Downstream Cooperating Skills:
    • saas-billing — Payment receipt emails, invoice PDFs, and failed payment dunning sequences.
    • saas-architect — Workspace team member invitations and tenant alert notifications.
    • authentication-identity-expert — Magic links, password resets, verification emails, and MFA codes.
    • mobile-expo-expert — Unified multi-channel notifications (email, APNs/FCM push, iOS Live Activities).
    • async-queue-temporal-expert — Durable background queue execution via BullMQ and Inngest.
    • production-ready-hardener — Pre-launch deliverability verification (SPF, DKIM, DMARC, and DNS records).
    • session-memory-manager — Store email template catalogs, notification providers, and delivery settings.

Description

Production-grade guide for building reliable email delivery systems and unified notification pipelines. Covers Resend, Postmark, AWS SES, React Email / MJML template engines, email deliverability (SPF, DKIM, DMARC), in-app notification systems (bell icon, toast, notification center), webhook-triggered email flows, email queuing with BullMQ/Inngest, and CAN-SPAM/GDPR compliance.

Trigger Conditions

Activate this skill when:

  • Setting up transactional email (welcome, password reset, invoices, team invites).
  • Building email templates with React Email or MJML.
  • Integrating Resend, Postmark, SendGrid, or AWS SES.
  • Implementing in-app notification systems (real-time bell, toast, notification center).
  • Configuring email deliverability (SPF, DKIM, DMARC records).
  • Building email queue systems for high-volume sends.
  • Implementing unsubscribe management and compliance.

Email Provider Selection Guide

ProviderBest ForKey StrengthPricing Model
ResendModern apps, React EmailDeveloper DX, React components as emailPer email (free tier: 3k/mo)
PostmarkTransactional-onlyIndustry-best deliverability, dedicated IPPer email (free tier: 100/mo)
AWS SESHigh volume, cost-sensitiveCheapest at scale ($0.10/1000 emails)Per email
SendGridMarketing + TransactionalFull marketing suite, analyticsTiered plans
PlunkSelf-hostable, open-sourceFull control, no vendor lock-inFree (self-hosted)

Recommendation: Use Resend for most new projects (best DX with React Email). Use Postmark for mission-critical transactional emails. Use AWS SES for high-volume (10k+/day) cost optimization.


1. React Email Templates

tsx
// emails/welcome.tsx
import {
  Body, Button, Container, Head, Heading,
  Html, Img, Link, Preview, Section, Text,
} from '@react-email/components';

interface WelcomeEmailProps {
  username: string;
  loginUrl: string;
}

export default function WelcomeEmail({ username, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Welcome to our platform, {username}!</Preview>
      <Body style={main}>
        <Container style={container}>
          <Img src="https://yourdomain.com/logo.png" width={48} height={48} alt="Logo" />
          <Heading style={heading}>Welcome, {username}! 🎉</Heading>
          <Text style={text}>
            We're thrilled to have you on board. Your account is ready.
          </Text>
          <Section style={buttonContainer}>
            <Button style={button} href={loginUrl}>
              Get Started
            </Button>
          </Section>
          <Text style={footer}>
            If you didn't create this account, you can safely ignore this email.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

const main = { backgroundColor: '#f6f9fc', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' };
const container = { backgroundColor: '#ffffff', margin: '0 auto', padding: '40px 20px', borderRadius: '8px', maxWidth: '560px' };
const heading = { fontSize: '24px', fontWeight: '600' as const, color: '#1a1a1a', margin: '24px 0 16px' };
const text = { fontSize: '16px', lineHeight: '26px', color: '#484848' };
const buttonContainer = { textAlign: 'center' as const, margin: '32px 0' };
const button = { backgroundColor: '#5046e5', borderRadius: '6px', color: '#fff', fontSize: '16px', padding: '12px 24px', textDecoration: 'none' };
const footer = { fontSize: '13px', color: '#999', marginTop: '32px' };

2. Sending Emails with Resend

typescript
// lib/email.ts
import { Resend } from 'resend';
import WelcomeEmail from '@/emails/welcome';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendWelcomeEmail(to: string, username: string) {
  const { data, error } = await resend.emails.send({
    from: 'Your App <noreply@yourdomain.com>',
    to,
    subject: `Welcome to Our Platform, ${username}!`,
    react: WelcomeEmail({ username, loginUrl: 'https://app.yourdomain.com/login' }),
    // Optional: plain text fallback
    text: `Welcome ${username}! Get started at https://app.yourdomain.com/login`,
    // Optional: tags for analytics
    tags: [
      { name: 'category', value: 'onboarding' },
    ],
  });

  if (error) {
    throw new Error(`Failed to send welcome email: ${error.message}`);
  }

  return data;
}

3. Email Queue for High-Volume

typescript
// queues/email-queue.ts
import { Queue, Worker } from 'bullmq';
import { sendEmail } from '@/lib/email';

// Queue definition
export const emailQueue = new Queue('emails', {
  connection: { host: process.env.REDIS_HOST, port: 6379 },
  defaultJobOptions: {
    attempts: 3,
    backoff: { type: 'exponential', delay: 2000 },
    removeOnComplete: { age: 86400 }, // Keep for 24h
    removeOnFail: { age: 604800 },    // Keep failed for 7 days
  },
});

// Worker (separate process)
const emailWorker = new Worker('emails', async (job) => {
  const { type, to, data } = job.data;

  switch (type) {
    case 'welcome':
      await sendWelcomeEmail(to, data.username);
      break;
    case 'password-reset':
      await sendPasswordResetEmail(to, data.resetToken);
      break;
    case 'invoice':
      await sendInvoiceEmail(to, data.invoiceId);
      break;
    default:
      throw new Error(`Unknown email type: ${type}`);
  }
}, {
  connection: { host: process.env.REDIS_HOST, port: 6379 },
  concurrency: 5,  // Process 5 emails at a time
  limiter: { max: 50, duration: 1000 }, // Max 50 emails/second (respect provider limits)
});

// Enqueue email from API route
export async function queueEmail(type: string, to: string, data: Record<string, unknown>) {
  await emailQueue.add(type, { type, to, data });
}

4. Email Deliverability Setup

DNS Records Required
# SPF — Authorize sending servers
TXT  @  "v=spf1 include:_spf.resend.com ~all"

# DKIM — Cryptographic signature
CNAME  resend._domainkey  resend._domainkey.yourdomain.com

# DMARC — Policy for failed authentication
TXT  _dmarc  "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; pct=100"

# Return-Path (custom bounce domain)
CNAME  bounce  feedback-smtp.us-east-1.amazonses.com
Deliverability Checklist
  • SPF record configured and verified
  • DKIM signing enabled and verified
  • DMARC policy set to at least p=quarantine
  • Custom From domain (not @gmail.com or @resend.dev)
  • List-Unsubscribe header present in all marketing emails
  • Bounce handling configured (remove invalid addresses)
  • Complaint feedback loop registered with major ISPs
  • Email content passes spam filter checks (no ALL CAPS, excessive links)

5. In-App Notification System

typescript
// db/schema — Notification table (Drizzle ORM)
import { pgTable, text, timestamp, boolean, uuid } from 'drizzle-orm/pg-core';

export const notifications = pgTable('notifications', {
  id: uuid('id').primaryKey().defaultRandom(),
  userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
  type: text('type').notNull(), // 'info' | 'warning' | 'success' | 'error'
  title: text('title').notNull(),
  message: text('message').notNull(),
  actionUrl: text('action_url'),
  isRead: boolean('is_read').default(false).notNull(),
  createdAt: timestamp('created_at').defaultNow().notNull(),
});

// API: Mark notification as read
export async function markAsRead(notificationId: string, userId: string) {
  await db.update(notifications)
    .set({ isRead: true })
    .where(and(
      eq(notifications.id, notificationId),
      eq(notifications.userId, userId),
    ));
}

// API: Get unread count
export async function getUnreadCount(userId: string): Promise<number> {
  const [result] = await db.select({ count: count() })
    .from(notifications)
    .where(and(
      eq(notifications.userId, userId),
      eq(notifications.isRead, false),
    ));
  return result.count;
}
tsx
// components/notification-bell.tsx
'use client';

import { useQuery } from '@tanstack/react-query';
import { Bell } from 'lucide-react';

export function NotificationBell() {
  const { data: unreadCount } = useQuery({
    queryKey: ['notifications', 'unread-count'],
    queryFn: () => fetch('/api/notifications/unread-count').then(r => r.json()),
    refetchInterval: 30_000, // Poll every 30 seconds
  });

  return (
    <button className="notification-bell" aria-label={`${unreadCount ?? 0} unread notifications`}>
      <Bell size={20} />
      {unreadCount > 0 && (
        <span className="notification-badge">{unreadCount > 99 ? '99+' : unreadCount}</span>
      )}
    </button>
  );
}

6. Unsubscribe & Compliance

typescript
// Mandatory headers for CAN-SPAM/GDPR compliance
const emailHeaders = {
  'List-Unsubscribe': '<https://app.yourdomain.com/unsubscribe?token=xxx>',
  'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
};

// One-click unsubscribe endpoint
export async function POST(request: Request) {
  const { token } = await request.json();
  const decoded = verifyUnsubscribeToken(token);
  await db.update(emailPreferences)
    .set({ unsubscribed: true, unsubscribedAt: new Date() })
    .where(eq(emailPreferences.userId, decoded.userId));
  return new Response('Unsubscribed', { status: 200 });
}

7. Mobile Push Notifications & iOS Live Activities

typescript
import * as Notifications from 'expo-notifications';

// Register for push tokens (Expo Push / FCM / APNs)
export async function registerForPushNotificationsAsync() {
  const { status: existingStatus } = await Notifications.getPermissionsAsync();
  let finalStatus = existingStatus;
  if (existingStatus !== 'granted') {
    const { status } = await Notifications.requestPermissionsAsync();
    finalStatus = status;
  }
  if (finalStatus !== 'granted') return null;
  return (await Notifications.getExpoPushTokenAsync()).data;
}
  • Expo Push & FCM: Send batched push notifications with deep links, actions, and custom data payloads.
  • iOS Live Activities / Dynamic Island: Update real-time status (orders, deliveries, live events) using ActivityKit.
  • Push Token Lifecycle: Save push tokens to database associated with userId; handle token rotation and app reinstall events.

Common Pitfalls to Avoid

Anti-PatternProblemCorrect Approach
Sending email synchronously in API routesSlow response times, timeout riskQueue emails with BullMQ/Inngest
Using @gmail.com as senderPoor deliverability, spam filtersUse custom domain with SPF/DKIM
No plain-text fallbackEmails may display incorrectlyAlways include text alongside HTML
Hardcoded email contentCan't update without deploysUse templates with dynamic variables
No unsubscribe linkCAN-SPAM violation, ISP blockingAlways include List-Unsubscribe header
Sending passwords in emailSecurity vulnerabilitySend one-time reset links with expiry

Sovereign Execution, Token Efficiency & Invariants

DimensionSovereign Mandate & Deterministic Contract
Frontier Model CascadeMedium / High (GPT-5.6 Sol Medium, Gemini 4 Argon, Claude Sonnet 5.5 High, Grok 4.7 High Fast)
Availability FallbackGemini 4 Argon/Pro -> Gemini 3.8 Flash; Claude Opus 5.5 -> Claude Opus 4.6 (Zero unhandled missing-model errors)
KV-Cache & Token ProtocolPin static instructions & schemas at prompt prefix (kv-cache-prefix-optimizer); pass surgical CONTEXT_MAP.md slices (<250 tokens/call) during Swarm Fan-Out
SaaT CLI & MCP DispatchCLI: vibes skill exec email-notification-expert <audit|eval|verify|generate|blueprint> / MCP: vibes_skill_dispatch, vibes_ast_query, vibes_compile_cache, vibes_optimize_budget, vibes_verify_gate
NFR & Anti-Slop InvariantsP99 API Gateway Latency < 85ms, OpenAPI 3.1 / TypeSpec strict schema parity, RFC 9457 Problem Details error contracts, Idempotency-Key enforcement; 100% complete zero-placeholder output verified via node scripts/check-anti-slop.js --strict


Bahasa Indonesia

Integrasi Orkestrasi

  • Orkestrator Hulu: Beroperasi di bawah arahan brainstorming dan zero-to-prod-orchestrator (Fase 4 - Backend, Pengiriman Pesan & Pipeline Notifikasi) untuk menyediakan layanan email transaksional dan notifikasi.
  • Skill Hilir & Kerja Sama:
    • saas-billing — Email kuitansi pembayaran, invoice PDF, dan sekuens dunning penagihan gagal.
    • saas-architect — Undangan anggota tim workspace dan notifikasi tenant.
    • authentication-identity-expert — Magic link, reset password, verifikasi email, dan kode MFA.
    • mobile-expo-expert — Notifikasi multi-saluran terpadu (email, push APNs/FCM, iOS Live Activities).
    • async-queue-temporal-expert — Eksekusi antrean background job tahan banting via BullMQ dan Inngest.
    • production-ready-hardener — Verifikasi deliverabilitas pra-peluncuran (rekod DNS SPF, DKIM, DMARC).
    • session-memory-manager — Menyimpan katalog template email, provider notifikasi, dan pengaturan pengiriman.

Deskripsi

Panduan tingkat produksi untuk membangun sistem pengiriman email yang andal dan pipeline notifikasi terpadu. Mencakup Resend, Postmark, AWS SES, mesin template React Email / MJML, deliverabilitas email (SPF, DKIM, DMARC), sistem notifikasi in-app (bell icon, toast, pusat notifikasi), alur email berbasis webhook, antrean email dengan BullMQ/Inngest, dan kepatuhan CAN-SPAM/GDPR.

Kondisi Pemicu

Aktifkan skill ini ketika:

  • Menyiapkan email transaksional (selamat datang, reset password, invoice, undangan tim).
  • Membangun template email dengan React Email atau MJML.
  • Mengintegrasikan Resend, Postmark, SendGrid, atau AWS SES.
  • Mengimplementasikan sistem notifikasi in-app (bell real-time, toast, pusat notifikasi).
  • Mengonfigurasi deliverabilitas email (SPF, DKIM, DMARC).
  • Membangun sistem antrean email untuk pengiriman volume tinggi.
  • Mengimplementasikan manajemen unsubscribe dan kepatuhan regulasi.

Panduan Pemilihan Provider Email

ProviderTerbaik UntukKekuatan UtamaModel Harga
ResendAplikasi modern, React EmailDX developer terbaik, komponen React sebagai emailPer email (gratis: 3k/bulan)
PostmarkHanya transaksionalDeliverabilitas terbaik di industri, IP dedicatedPer email (gratis: 100/bulan)
AWS SESVolume tinggi, hemat biayaTermurah di skala besar ($0.10/1000 email)Per email
SendGridMarketing + TransaksionalSuite marketing lengkap, analitikPaket bertingkat

Rekomendasi: Gunakan Resend untuk kebanyakan proyek baru (DX terbaik dengan React Email). Gunakan Postmark untuk email transaksional misi-kritis. Gunakan AWS SES untuk optimasi biaya volume tinggi (10k+/hari).

Notifikasi Push Mobile & iOS Live Activities

  • Expo Push & FCM: Kirim notifikasi push masal dengan payload kustom, aksi tombol, dan deep linking ke rute aplikasi (Expo Router).
  • iOS Live Activities: Tampilkan status dinamis secara real-time pada Dynamic Island dan Lock Screen iOS menggunakan ActivityKit.
  • Siklus Hidup Push Token: Simpan token push ke database per userId dan tangani event rotasi token saat instal ulang aplikasi.

Kesalahan Umum yang Harus Dihindari

Anti-PolaMasalahPendekatan yang Benar
Mengirim email secara sinkron di API routeWaktu respons lambat, risiko timeoutAntrean email dengan BullMQ/Inngest
Menggunakan @gmail.com sebagai pengirimDeliverabilitas buruk, filter spamGunakan domain kustom dengan SPF/DKIM
Tidak ada fallback teks biasaEmail mungkin tampil tidak benarSelalu sertakan text di samping HTML
Tidak ada link unsubscribePelanggaran CAN-SPAM, pemblokiran ISPSelalu sertakan header List-Unsubscribe

Matriks Eksekusi Berdaulat, Efisiensi Token & Invarian

DimensiMandat Berdaulat & Kontrak Deterministik
Kaskade Model FrontierMedium / High (GPT-5.6 Sol Medium, Gemini 4 Argon, Claude Sonnet 5.5 High, Grok 4.7 High Fast)
Invarian Fallback KetersediaanGemini 4 Argon/Pro -> Gemini 3.8 Flash; Claude Opus 5.5 -> Claude Opus 4.6 (Bebas gagal saat model belum tersedia/kuota penuh)
Protokol Hemat Token & KV-CacheKunci instruksi & skema statis di prefix awal (kv-cache-prefix-optimizer); kirim potongan CONTEXT_MAP.md (<250 token/panggilan) saat Fan-Out
Eksekusi SaaT CLI & MCPCLI: vibes skill exec email-notification-expert <audit|eval|verify|generate|blueprint> / MCP: vibes_skill_dispatch, vibes_ast_query, vibes_compile_cache, vibes_optimize_budget, vibes_verify_gate
Invarian NFR & Anti-SlopLatensi P99 API < 85ms, paritas skema ketat OpenAPI 3.1 / TypeSpec, kontrak error RFC 9457 Problem Details, penegakan Idempotency-Key; kode 100% tuntas tanpa placeholder diverifikasi melalui node scripts/check-anti-slop.js --strict

Frequently asked questions

What does the Email Notification Expert AI skill do?

Transactional email (Resend), React Email, and notification pipelines / Email transaksional (Resend), React Email, dan pipeline notifikasi.

Why use Email Notification Expert on TypingMind?

Because you install it once and use it with any model. Email Notification Expert is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Email Notification Expert in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/roedyrustam/vibes-plug/tree/main/skills/email-notification-expert. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Email Notification Expert?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Email Notification Expert?

As many as you like. As long as a model supports skills, you can use Email Notification Expert with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Email Notification Expert AI skill free?

Yes. It is published on GitHub by roedyrustam under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇