Social Command Center — Multi-platform social media management SaaS

May 1, 2026

The problem

Creators and small teams post the same content to X, Reddit, Bluesky, and LinkedIn by hand — rewriting for each platform's limits and tone, juggling time zones for scheduling, and losing track of what performed. Existing tools are expensive and skip newer platforms like Bluesky.

What I built

A full-stack SaaS where a user writes a post once, enhances it with AI, translates it, schedules it, and publishes it to multiple platforms from one dashboard — then watches engagement roll in automatically.

Modular monolith backend

14 services (auth, post-composer, scheduler, platform connectors, ai-enhancer, translator, extractor, analytics, listener, trend-scout, billing…) live in one Fastify process behind a single gateway with JWT auth, rate limiting, and Zod validation on every route. One folder = one responsibility; services call each other as plain functions, never HTTP.

Queue-driven publishing pipeline

Scheduling is built on BullMQ + Redis with 5 dedicated queues. Scheduling a post enqueues a delayed job; the worker fires at publish time and runs the pipeline:

publish job fires → AI enhance (optional) → translate (optional) → post to each connected platform → record published_posts → log usage

Failed platforms don't block the others — each connector returns a typed Result, and partial failures are recorded per platform.

Platform connectors

Adapter-style connectors for Bluesky (AT Protocol), X (twitter-api-v2), and Reddit (snoowrap) behind a common interface. OAuth/app-password tokens are encrypted at rest with AES-256-GCM before touching the database.

Time-decay analytics

Publishing a post schedules four analytics fetch jobs at t+5min, t+1h, t+24h, and t+7d — capturing the engagement curve (likes, reposts, replies, impressions) without polling every post forever. The dashboard aggregates across 24h/7d/30d/90d ranges.

AI layer

Text enhancement (rewrite, tone shift, hashtags, platform-length fitting) via an LLM provider abstraction, and translation through DeepL with automatic LLM fallback when DeepL doesn't support a language pair.

Architecture decisions

  • Modular monolith over microservices — every "service" is a folder with routes/handlers/schema sharing one process, one Postgres, one deploy. All the separation-of-concerns benefits with none of the distributed-systems tax at MVP scale; any service can be split out later since they already communicate through queues or typed function calls.
  • Typed Result objects over thrown exceptions — every operation that can fail returns { success, data | error } end-to-end, from Drizzle queries up through the API envelope. Platform APIs fail constantly (rate limits, expired tokens, moderation blocks); making failure a first-class return type forced every call site to handle it.
  • BullMQ delayed jobs over cron scanning — instead of a cron sweeping a table for due posts every minute, each scheduled post is a delayed Redis job with retry/backoff built in. Editing or cancelling a scheduled post just updates or removes its job by id.
  • Tokens encrypted at rest — social account credentials are the most sensitive thing the app holds; AES-256-GCM with a dedicated key means a database leak alone doesn't expose users' accounts.

What I'd do differently

  • Verify platform API access before writing connectors — the X connector is code-complete but the pay-per-use API pricing and Reddit's manual app approval made Bluesky the primary demo platform. I'd validate API economics first and order the roadmap around them.
  • Ship email verification and password reset with auth v1 instead of deferring them — retrofitting table-stakes auth flows is more awkward than building them alongside registration.

Tech stack

TypeScript · Fastify · Drizzle ORM · PostgreSQL · BullMQ · Redis · Next.js 15 · Tailwind + shadcn/ui · TanStack Query · Zustand · Zod · Stripe · Docker · Turborepo

GitHub
LinkedIn