I was searching for a WhatsApp message scheduler (without using WhatsApp Business API), but couldn’t find anything suitable—so I decided to build one myself.


🔧 What I Wanted to Build

  • Create, edit, and delete scheduled messages
  • Set a "Send After (in days)" timer
  • Reschedule the timer with one click

It seemed like a simple project, but turned out to be pretty tricky. Here's how I tackled it.


❌ Why Not node-schedule or setInterval?

Basic solutions like node-schedule or setInterval don’t offer the reliability I wanted. So I turned to bullmq, which uses Redis for job management.

I'm using:

  • Prisma + SQLite for tracking messages & schedules
  • whatsapp-web.js as an unofficial WhatsApp client
  • Backend: Bun + Hono

🗂️ Backend Structure

Backend Structure


Backend Breakdown

📦 Dependencies

{
  "dependencies": {
    "bullmq": "^5.45.0",
    "hono": "^4.7.5",
    "prisma": "^6.5.0",
    "ioredis": "^5.6.0",
    "whatsapp-web.js": "^1.27.0",
    "qrcode-terminal": "^0.12.0",
    "@prisma/client": "^6.5.0"
  }
}

🧠 Prisma Schema

I have three models: AdminProfile, People, and Message. Here's the Message Model.

model Message {
  id          String   @id @default(cuid())
  content     String
  sendTo      People   @relation(fields: [sendToPhone], references: [phone])
  sendToPhone String
  sendAfter   Float    @default(0)
  createdAt   DateTime @default(now())
}

🔐 Basic Auth

Used Hono's built-in basic-auth with minimal setup:

new Hono().use(
  basicAuth({
    username: Bun.env.USERNAME || "user",
    password: Bun.env.PASSWORD || "pass",
  })
);

📨 Message Queue with BullMQ

import { Queue } from "bullmq";

export const messageQueue = new Queue("messageQueue", {
  connection: {
    url: process.env.REDIS_REST_URL,
    maxRetriesPerRequest: null,
  },
});

🗓 Scheduling Messages

This runs after every create/edit/delete operation.

await messageQueue.add(
  jobId,
  { content: message.content, sendToPhone: message.sendToPhone },
  { jobId, delay: sendAfterMs }
);

Also added a reminder message if messages aren't rescheduled in time 👇

messageQueue.add("message-reschedule", {
  content: "You have 3.5 hours left to reschedule messages or I think you are dead",
  sendToPhone: "8801884510919",
}, { delay: timeLeft - 3.5 * 3600 * 1000 });

📲 WhatsApp Client (wweb.js)

import { Client, LocalAuth } from "whatsapp-web.js";

const client = new Client({ authStrategy: new LocalAuth() });

const sendMessage = async (phone: string, message: string) => {
  client.sendMessage(`${phone}@c.us`, message);
};

👷 Worker: Auto Sync with Schedule

const worker = new Worker(
  "messageQueue",
  async (job) => {
    await sendMessage(job.data.sendToPhone, job.data.content);
  },
  { connection: redisConfig, concurrency: 1 }
);

🖼️ Frontend (Minimal but Functional)

The frontend is just a simple interface built using:

  • Next.js
  • Shadcn UI
  • Server Actions to talk to the backend

Frontend
🔗 View Frontend Code


✨ TL;DR

I built a WhatsApp scheduler using:

  • Bun + Hono for the backend
  • BullMQ for reliable message queuing
  • Prisma + SQLite for storing schedules
  • wweb.js for sending WhatsApp messages
  • Next.js frontend (barebones, but it works)

💬 Final Words

Still a work in progress, but it’s functional and fun to build.

Would love to hear thoughts, improvements, or just a “cool project” 😄