DEV Community

Cover image for I Built an Open-Source Social Media Scheduler for 33 Platforms — Here's How It Works
Lukasz
Lukasz

Posted on

I Built an Open-Source Social Media Scheduler for 33 Platforms — Here's How It Works

I Built an Open-Source Social Media Scheduler for 33 Platforms — Here's How It Works

Over the last few months, I've been building PostSider, an open-source social media scheduling platform.

The idea started pretty simply: I wanted one place to manage publishing across different platforms without maintaining a completely separate workflow for every network.

But the project gradually became more than a scheduling UI.

Today PostSider has 33 built-in connectors, can be fully self-hosted with Docker, exposes a public REST API and Node.js SDK, and includes an MCP server that allows AI agents to interact with the same publishing infrastructure.

GitHub:

https://github.com/lumizone/postsider

Website:

https://postsider.com

In this post, I want to explain how the project is structured and some of the architectural decisions behind it.


The problem with supporting many platforms

Publishing to one social network is fairly straightforward.

Supporting 30+ is not.

Every platform has slightly different concepts:

  • authentication
  • OAuth flows
  • media limits
  • text limits
  • publishing APIs
  • analytics
  • refresh tokens
  • post formats
  • videos
  • images
  • first comments
  • validation rules

If every integration is implemented independently throughout the application, the codebase becomes difficult to maintain very quickly.

So one of the most important decisions in PostSider was to isolate each platform behind a common provider interface.

The integrations live under:

libraries/nestjs-libraries/src/integrations/social/
Enter fullscreen mode Exit fullscreen mode

Each provider implements the same general contract.

Conceptually, the structure looks like this:

PostSider
   |
   +-- Integration Manager
          |
          +-- X Provider
          +-- LinkedIn Provider
          +-- Instagram Provider
          +-- YouTube Provider
          +-- TikTok Provider
          +-- Bluesky Provider
          +-- Mastodon Provider
          +-- ...
Enter fullscreen mode Exit fullscreen mode

The application doesn't need to understand every platform individually.

Instead, it asks the provider what it supports and how a particular action should be executed.

That makes adding another integration much more manageable.


33 connectors behind one system

At the moment, PostSider registers 33 active connectors.

They include social networks such as:

  • X
  • LinkedIn
  • Facebook
  • Instagram
  • Threads
  • YouTube
  • TikTok
  • Pinterest
  • Bluesky
  • Mastodon
  • Farcaster
  • Nostr

It also supports communication platforms such as:

  • Discord
  • Slack
  • Telegram

And publishing platforms including:

  • WordPress
  • Medium
  • Dev.to
  • Hashnode
  • Ghost
  • Blogger
  • Notion
  • Write.as
  • Mataroa
  • Listmonk

You don't need credentials for all of them.

A self-hosted installation only needs the OAuth/API credentials for the platforms that will actually be used.


The scheduler needs to survive restarts

Another interesting problem is scheduled publishing.

A naive implementation could look like this:

setTimeout(() => {
  publishPost();
}, timeUntilPost);
Enter fullscreen mode Exit fullscreen mode

That works until the server restarts.

Or crashes.

Or gets redeployed.

Or you have thousands of scheduled jobs.

For PostSider I use Temporal for durable background workflows.

The architecture is roughly:

Frontend
   |
   v
NestJS API
   |
   v
PostgreSQL
   |
   +------> Temporal
               |
               v
          Orchestrator
               |
               v
        Platform Provider
Enter fullscreen mode Exit fullscreen mode

When a post is scheduled, the background workflow isn't tied to the lifecycle of a single web process.

Temporal handles the durable workflow and workers execute the publishing operation when required.

I also use it for things like token refresh workflows.

This introduces more infrastructure, but for a scheduler I think the tradeoff is worth it.


The stack

PostSider is a TypeScript monorepo using pnpm.

The main stack currently looks like this:

Frontend       Next.js 15 + React 19
Backend        NestJS
Database       PostgreSQL + Prisma
Cache          Redis
Workflows      Temporal
Storage        Local / Cloudflare R2 / MinIO
AI             OpenAI (optional)
Billing        Polar.sh (optional)
Monitoring     Sentry
Enter fullscreen mode Exit fullscreen mode

The repository is structured roughly like this:

postsider/
├── apps/
│   ├── backend/
│   ├── orchestrator/
│   ├── frontend/
│   ├── commands/
│   ├── sdk/
│   └── mcp/
│
├── libraries/
│   ├── nestjs-libraries/
│   └── helpers/
│
├── docker-compose.yaml
├── docker-compose.production.yaml
└── .env.example
Enter fullscreen mode Exit fullscreen mode

The same codebase can run as a hosted service or as a self-hosted deployment.

Optional functionality is controlled through environment configuration.

For example, PostSider works perfectly fine without an OpenAI API key.

AI features simply remain disabled.


Self-hosting with Docker

One requirement I wanted from the beginning was to make PostSider something people could actually run themselves.

For a local installation, the basic setup is:

git clone https://github.com/lumizone/postsider.git
cd postsider
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Then open:

http://localhost:4007
Enter fullscreen mode Exit fullscreen mode

The Compose stack starts the application together with PostgreSQL, Redis and Temporal.

The repository also contains a separate production-oriented Docker Compose configuration for more serious deployments.

I don't want self-hosting to be an afterthought.

It's one of the main reasons the project is open source.


Making the application useful without the UI

Another decision was to avoid making all functionality dependent on the dashboard.

PostSider exposes a public REST API under:

/public/v1
Enter fullscreen mode Exit fullscreen mode

There is also a Node.js SDK:

npm install @postsider/node
Enter fullscreen mode Exit fullscreen mode

A simplified example:

import Postsider from '@postsider/node';

const client = new Postsider(
  'your-api-key',
  'https://your-instance.com'
);

await client.post({
  type: 'schedule',
  date: '2026-10-01T10:00:00',
  posts: [
    {
      integration: {
        id: 'channel-id'
      },
      value: [
        {
          content: 'Hello from PostSider'
        }
      ]
    }
  ]
});
Enter fullscreen mode Exit fullscreen mode

This means PostSider can also work as infrastructure underneath another application.

You don't necessarily need to use the dashboard for every workflow.


Then I added MCP

This became one of the more interesting parts of the project.

PostSider now includes an MCP server through the @postsider/mcp package.

The idea is simple.

Instead of giving an AI agent direct access to dozens of social media APIs, the agent communicates with PostSider.

Claude / Codex / MCP client
          |
          v
      PostSider MCP
          |
          v
     PostSider API
          |
          v
 Integration Providers
          |
          v
 X / LinkedIn / TikTok / etc.
Enter fullscreen mode Exit fullscreen mode

The MCP server currently exposes 19 tools.

An agent can perform workflows such as:

  • list connected channels
  • review the publishing calendar
  • create drafts
  • upload media
  • request approval
  • inspect scheduled content
  • read analytics

I intentionally designed this around a read-first and draft-first workflow.

Giving an autonomous agent immediate publishing access to every connected social account isn't necessarily what you want.

Instead, an agent can prepare the work inside the same workflow humans already use.

A human can still remain in control of the final publishing decision.


Why not just integrate every API directly into an AI agent?

You can.

But then your agent needs to understand:

X API
LinkedIn API
Instagram API
TikTok API
YouTube API
Pinterest API
...
Enter fullscreen mode Exit fullscreen mode

including authentication, token refresh, provider-specific validation and different publishing models.

With PostSider sitting in the middle, the architecture becomes:

Agent
   |
   v
PostSider
   |
   +-- X
   +-- LinkedIn
   +-- Instagram
   +-- TikTok
   +-- YouTube
   +-- ...
Enter fullscreen mode Exit fullscreen mode

The agent works with one consistent interface.

PostSider handles the provider-specific complexity.

I think this is one of the more interesting directions for the project.


What I learned building it

Supporting many APIs makes abstraction difficult.

If the abstraction is too generic, you lose platform-specific functionality.

If every provider is completely independent, the rest of the application becomes full of special cases.

The balance I've been trying to find is:

Shared interface
+
Provider-specific capabilities
Enter fullscreen mode Exit fullscreen mode

Another lesson is that social media scheduling is surprisingly infrastructure-heavy.

A reliable scheduler needs to think about:

  • durable jobs
  • retries
  • rate limits
  • OAuth token refresh
  • media storage
  • background workers
  • provider outages
  • validation before publishing
  • security of credentials

The calendar UI is actually one of the easier parts.


What's next

There are still plenty of things I want to improve.

Some of the current roadmap includes:

  • broader automated test coverage
  • stronger TypeScript null safety
  • more integrations
  • advanced analytics
  • a plugin system for custom integrations
  • mobile support
  • expanding the MCP capabilities

I'm also interested in making self-hosting easier.

A project can technically be self-hostable while still being painful to operate, and I'd like PostSider to move further away from that.


Try it

PostSider is available under the AGPL-3.0 license.

GitHub:

https://github.com/lumizone/postsider

Documentation:

https://docs.postsider.com

Website:

https://postsider.com

If you're interested in self-hosting, social media APIs, workflow infrastructure or MCP, I'd be interested in feedback — especially around the provider architecture and deployment experience.

Top comments (0)