Open-source social media scheduling for 40+ platforms.
Plan, compose, and publish from one calendar, with a public API and SDK for automation
and an optional AI assist for checking and rewriting captions.
Quick Start · Features · Architecture · Self-Hosting · Contributing · License
Scheduling and publishing
- Visual calendar with drag and drop scheduling and time slot management
- Posting queue with day-aware find-free-slot, plus Smart Slots suggestions
- Evergreen recycling for content you want to repost on a cadence
- Per-platform preview and per-platform validation before you publish
- First comment posted automatically for platforms that support it
- 40+ connectors: X, LinkedIn, Facebook, Instagram, YouTube, TikTok, Threads, Bluesky, Mastodon, Reddit, Discord, Slack, Telegram, Pinterest, and many more
Composer
- Hashtag groups, caption templates, UTM builder, and reusable snippets
- Bulk CSV import to schedule many posts at once
- Approval workflow so posts can be reviewed before they go out
Optional AI (off unless you provide a key)
- Post Checker flags issues before publishing
- Caption rewrite improves a draft on request
- Uses the platform
OPENAI_API_KEY, or a per-org key you bring yourself (BYO)
Collaboration and automation
- Team collaboration with role-based access (Admin / User)
- Multi-organization workspaces, one per brand or client
- Media library to upload, manage, and attach images and videos
- Analytics with per-post performance tracking where the provider supports it
- Public REST API + SDK (
/public/v1and the@postsider/nodepackage) for programmatic use - MCP server so AI agents (Claude, Codex) can drive the platform natively, via
@postsider/mcp - Webhooks to notify external systems when posts are published
- Self-hostable on your own infrastructure with Docker
- Node.js >= 20.17 (recommended: use Volta, it auto-picks the right version)
- pnpm >= 10.6
- PostgreSQL >= 15
- Redis >= 7
- Docker (optional, for the all-in-one setup)
git clone https://github.com/your-org/postsider.git
cd postsider
docker compose up -dOpen the app in your browser. On first launch, create your admin account through the bootstrap flow.
# 1. Clone and install
git clone https://github.com/your-org/postsider.git
cd postsider
pnpm install
# 2. Set up environment
cp .env.example .env
# Edit .env, at minimum set DATABASE_URL, REDIS_URL, JWT_SECRET
# 3. Apply the database schema
pnpm prisma-migrate-deploy
# 4. Create your first admin user
pnpm bootstrap
# 5. Start development servers (backend + orchestrator)
pnpm dev
# 6. In another terminal, start the frontend
pnpm dev:frontendThe backend runs on http://localhost:3000, the frontend on http://localhost:4200.
After running pnpm bootstrap, you receive a one-time password in the terminal. Sign in with admin@setup.local and that password, then you are prompted to set your real email and password.
PostSider is a pnpm monorepo with the following structure:
postsider/
├── apps/
│ ├── backend/ # NestJS REST API (auth, posts, integrations, billing)
│ ├── orchestrator/ # Temporal worker (scheduled publishing, token refresh)
│ ├── frontend/ # Next.js 15 dashboard (React 19, App Router)
│ ├── commands/ # CLI utilities (bootstrap, config)
│ └── sdk/ # Published npm package for the public API
├── libraries/
│ ├── nestjs-libraries/ # Shared backend logic (Prisma, integrations, uploads)
│ └── helpers/ # Lightweight utilities (auth, crypto, validation)
├── docker-compose.yaml # Production-ready stack
└── .env.example # Configuration reference
| Layer | Technology |
|---|---|
| Backend API | NestJS 11, TypeScript 5.5 |
| Frontend | Next.js 15, React 19, CSS Modules |
| Database | PostgreSQL + Prisma 6.5 |
| Cache / Queue | Redis 7 |
| Workflow Engine | Temporal (durable post scheduling, token refresh) |
| AI (optional) | OpenAI (Post Checker and caption rewrite) |
| Billing (optional) | Polar.sh (Merchant of Record) |
| Storage | Local filesystem or Cloudflare R2 |
| Auth | JWT + bcrypt, OAuth (GitHub, Google, Generic OIDC) |
| Monitoring | Sentry |
- Temporal for scheduling: posts are scheduled as durable workflows, surviving restarts and crashes. Token refresh runs on a cron workflow.
- Per-provider integration classes: each social platform is a self-contained class implementing
SocialProvider. Adding a new platform means adding one file. - CASL-based permissions: subscription tier determines what actions are allowed. Guards check abilities on every request.
- Env-gated single build: the same codebase runs as managed hosting or fully self-hosted. Billing is enabled only when
POLAR_ACCESS_TOKENis set; AI features are enabled only when an OpenAI key is present (platform or BYO). With neither, every org is unlimited and AI is simply hidden. - Public API with SDK: the
@postsider/sdkpackage wraps the public v1 endpoints for external consumers.
All configuration lives in environment variables. See .env.example for the full reference.
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
REDIS_URL |
Redis connection string |
JWT_SECRET |
Random string for signing tokens (make it long and unique) |
FRONTEND_URL |
Public URL where the dashboard is accessible |
NEXT_PUBLIC_BACKEND_URL |
Public URL of the backend API |
By default, files are stored locally in ./uploads/. For cloud storage, set:
STORAGE_PROVIDER=cloudflare
CLOUDFLARE_ACCOUNT_ID=...
CLOUDFLARE_ACCESS_KEY=...
CLOUDFLARE_SECRET_ACCESS_KEY=...
CLOUDFLARE_BUCKETNAME=...
CLOUDFLARE_BUCKET_URL=...Each platform requires its own OAuth credentials. Refer to .env.example for the full list. You only need to configure the platforms you plan to use.
docker-compose.production.yaml runs the full stack in a single command:
- PostSider app (backend + frontend in one container, port 5000)
- PostgreSQL (app database)
- Redis (caching + rate limiting)
- MinIO (S3-compatible object storage, port 9000)
- Temporal (workflow engine + its own Postgres + Elasticsearch)
- Temporal UI (workflow monitoring, port 8080)
- DbGate (database admin UI, port 8082, optional)
Migrations run automatically at startup via prisma migrate deploy before the app starts.
Steps:
# 1. Copy the env template
cp .env.example .env.production
# 2. Fill in required values: DATABASE_URL, REDIS_URL, JWT_SECRET,
# FRONTEND_URL, NEXT_PUBLIC_BACKEND_URL, BACKEND_INTERNAL_URL,
# MINIO_ACCESS_KEY, MINIO_SECRET_KEY, POSTGRES_PASSWORD.
# Leave POLAR_ACCESS_TOKEN and OPENAI_API_KEY blank for self-host
# (billing becomes unlimited; AI features use user-supplied BYO keys).
# For each social platform you want, register an OAuth app on the
# provider's developer portal and fill in the matching CLIENT_ID /
# CLIENT_SECRET vars (see the "Social platform OAuth credentials"
# section in .env.example).
# Set NEXT_PUBLIC_BACKEND_URL=https://app.yourdomain.com and build
# the image (NEXT_PUBLIC_BACKEND_URL is baked into the JS bundle).
nano .env.production
# 3. Build the image (NEXT_PUBLIC_* vars are build-time ARGs)
source .env.production && docker compose -f docker-compose.production.yaml build \
--build-arg NEXT_PUBLIC_BACKEND_URL="$NEXT_PUBLIC_BACKEND_URL"
# 4. Start everything
docker compose -f docker-compose.production.yaml up -d
# 5. Create the first admin account
docker exec -it postsider-app pnpm bootstrap
# 6. Check logs
docker compose -f docker-compose.production.yaml logs -f postsiderThe app is then available on port 5000 (put nginx or a reverse proxy in front for HTTPS).
docker compose -f docker-compose.production.yaml pull
docker compose -f docker-compose.production.yaml up -dMigrations run automatically on each restart.
The critical data lives in PostgreSQL. Back up the postsider-postgres volume regularly:
docker exec postsider-postgres pg_dump -U postsider postsider_prod > backup.sql# Run backend only
pnpm dev:backend
# Run frontend only
pnpm dev:frontend
# Run orchestrator only
pnpm dev:orchestrator
# Generate Prisma client after schema changes
pnpm prisma-generate
# Create a migration after schema changes
pnpm prisma-migrate-dev
# Apply pending migrations
pnpm prisma-migrate-deploy
# Build all apps
pnpm build
# Build SDK
pnpm build:sdk- Path aliases:
@postsider/backend/*,@postsider/helpers/*,@postsider/nestjs-libraries/*, and so on - Global DatabaseModule: all Prisma repositories and services are provided globally via
DatabaseModule - Integration pattern: each social provider extends
SocialAbstractand implementsSocialProvider - Temporal workflows: defined in
apps/orchestrator/src/workflows/ - Migrations, not db push: commit Prisma migration files; the server runs
prisma migrate deployon boot
PostSider exposes a public REST API for programmatic access. Authenticate with your org's API key via the Authorization header.
npm install @postsider/nodeimport Postsider from '@postsider/node';
const client = new Postsider('your-api-key', 'https://your-instance.com');
// Create a post
await client.post({
type: 'schedule',
date: '2025-01-15T10:00:00',
posts: [{ integration: { id: 'channel-id' }, value: [{ content: 'Hello!' }] }],
});
// List posts
const posts = await client.postList({ page: 0, limit: 20 });
// List connected channels
const channels = await client.integrations();PostSider ships an MCP server so AI agents (Claude Code, Claude Desktop, Codex, and any MCP-compatible client) can drive the platform directly: list channels, schedule and publish posts, upload media, and read analytics. It is a thin, dependency-light wrapper over the public API.
pnpm --filter @postsider/mcp buildThen point your agent at apps/mcp/dist/index.js with POSTSIDER_API_KEY (and
POSTSIDER_API_URL for a self-hosted instance). See
apps/mcp/README.md for client config snippets and the
full tool list.
Contributions are welcome. Here is how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Ensure TypeScript compiles:
pnpm run build:backend - Commit with a clear message
- Open a Pull Request
- Bug fixes with clear reproduction steps
- New social platform integrations
- Documentation improvements
- Performance optimizations
- Test coverage
- TypeScript strict mode (excluding
strictNullChecksfor now; PRs to fix null-safety are welcome) - Prettier for formatting (
.prettierrcin root) - ESLint for linting
- Broaden test coverage for core flows (auth, posts, integrations)
- Enable
strictNullChecksacross the codebase - GitHub Actions CI (lint + typecheck + build)
- Mobile app (React Native)
- Plugin system for custom integrations
- Advanced analytics dashboard
PostSider is licensed under the GNU Affero General Public License v3.0.
This means you can use, modify, and distribute PostSider freely, but if you run a modified version as a network service, you must make your source code available to users of that service.
