April 4, 2026 · 9 min read

I Built a Slack Bot That Writes Social Posts for 3 Platforms

A community manager needed to post across LinkedIn, Twitter, and Facebook — plus send DMs to 400+ Slack community members. Manually. Every week. I built a dashboard that generates AI content, schedules posts, automates DM sequences, and broadcasts to the entire community in one click. Here's how.

The Problem

Community management is secretly one of the most tedious jobs in tech. The community manager I built this for had a weekly routine:

  1. Write a LinkedIn post about this week's content
  2. Adapt it for Twitter (shorter, different tone)
  3. Adapt it again for Facebook (different formatting)
  4. Open Slack, find the community channel
  5. Manually DM 20-30 members about upcoming events
  6. Track who opened, who replied, who showed up

This took 4-6 hours per week. Not because any individual task was hard, but because switching between platforms, adapting tone, and manually messaging hundreds of people is death by a thousand cuts.

What I Built

A React dashboard with 5 core features:

1. AI Content Generation

Feed the tool a topic, a link, or a raw draft. Gemini generates platform-specific versions:

Each version is editable before posting. The AI gets you 80% there; you fine-tune the last 20%. Total time: 2 minutes instead of 30.

2. Scheduled Posting

Queue posts for specific dates and times. The dashboard shows a content calendar with what's scheduled for each platform. Posts can be reordered, edited, or deleted from the queue.

3. DM Automation (Sequences)

This is the feature that saved the most time. Instead of manually DMing members one by one:

  1. Write a DM template with personalization tokens ({first_name}, {company})
  2. Select a member segment (new members, active members, event attendees)
  3. Schedule the sequence (send immediately, or drip over 3 days)
  4. Track delivery, opens, and replies

The Slack API has strict rate limits (1 message per second for DMs), so the system auto-batches and spaces messages to avoid hitting limits. A dry run mode lets you preview who gets what before sending.

4. Broadcast Messaging

One-click broadcast to all 400+ community members. Write the message, preview the formatting (Slack's mrkdwn is different from Markdown — a trap I fell into multiple times), and send. The system batches automatically and shows delivery progress in real time.

5. Community Analytics

Who's active, who's lurking, who joined recently, who hasn't posted in 30 days. Member growth over time, message frequency, top contributors. All pulled from Slack's API and stored in Supabase for historical tracking.

The Architecture

Stack

Frontend: React + Vite + Tailwind
Backend: Supabase Edge Functions + Postgres (16 tables)
AI: Gemini (content generation, tone adaptation)
APIs: Slack (DMs, channels, member data), social platform APIs
Hosting: Vercel (custom domain)
Scheduling: pg_cron for automated sends + data refreshes

The Slack API Lessons

Rate limits are aggressive

Slack allows ~1 message per second for DMs. If you're messaging 400 people, that's 7 minutes of pure API time. You need a queue, batching, and progress tracking. I send in batches of 50 with a 1-second delay between messages and a 5-second pause between batches.

mrkdwn is not Markdown

Slack uses its own formatting called mrkdwn. Bold is *text* (not **text**). Links are <url|label> (not [label](url)). Italic is _text_. I built a preview component that renders mrkdwn exactly as Slack would, so the community manager sees the real formatting before sending.

User lookup is fragile

The Slack API gives you user IDs, not names. To display friendly names and match members to your database, you need to call users.info for each member. I cache this in Supabase and refresh weekly — calling it per-request would eat your rate limit instantly.

DMs require a conversation open first

You can't just POST a message to a user ID. You need to call conversations.open first to get a DM channel ID, then post to that channel. For 400 members, that's 800 API calls (open + send). Batch accordingly.

Where This Pattern Applies

This isn't just for social media managers. The "AI generates content + API distributes it" pattern works for:

What I'd Do Differently

1. Build the mrkdwn preview first

I spent an embarrassing amount of time sending test DMs to myself because I couldn't preview Slack formatting in the dashboard. The preview component should be the first thing you build, not the last.

2. Template system from day one

The community manager ended up reusing the same 5-6 message types (event invite, content share, welcome DM, check-in, feedback request). I should have built a template system with saved messages and one-click reuse from the start.

3. Friendly name fallback

When the Slack API doesn't return a display name (it happens), the DM says "Hi !" with a blank. I added a fallback to real_name then first_name then just "there." Always build the fallback chain before the first broadcast.

"Monday used to be my worst day. Now I open the dashboard, review the AI drafts, hit send on DMs, and I'm done by 10 AM."

— the community manager, 3 weeks after launch

The whole system cost $0 to run (Supabase free tier, Vercel free tier, Gemini free API tier). The community manager saves 4 hours per week. That's 200+ hours per year returned to actual community building instead of copy-pasting messages.

From the shop

PWA Notifications Kit ($14)

The 5-layer notification system that actually works on iOS. Native push, in-app banners, Shortcuts automation, and offline queue with retry.

Get PWA Notifications Kit — $14

Like what I build? Check out the shop — deploy-ready kits starting at $14.


More from the build log

AI automations, serverless architecture, and tools that save people hours.

Read more posts