Porting tracker
Port of Postiz at commit e424fb5 (v1.47.0).
The original copyright notice is preserved in LICENSE.
Status: ✅ ported, tested against mocks · 🟡 partial · ⬜ not done · ➖ removed by design
Nothing here has been tested against a real platform, email service or storage bucket. Most provider code was machine-ported from the TypeScript and checked by its tests. X, LinkedIn, Instagram, Facebook, Threads, YouTube, TikTok, Reddit, Pinterest, Bluesky, Mastodon, Discord, Slack and Telegram also had a machine-run line-by-line comparison with upstream, not a human review. The other providers had spot checks only.
Architecture
| Postiz | This port |
|---|---|
| NestJS + Next.js + orchestrator | ✅ one binary |
| Temporal + Postgres + Elasticsearch | ✅ jobs table and in-process worker |
| Postgres (Prisma) | ✅ SQLite in WAL mode; same table and column names, no data migration tool |
| Redis | ✅ OAuth state is in SQLite; request limits are in-process and per server process |
@mastra/mcp | ✅ rmcp, spec 2026-07-28 and older |
| Mastra / LangChain / CopilotKit agents | ➖ agents bring their own LLM |
| Next.js frontend, calendar, visual editor | ➖ no GUI |
| Sentry | ➖ tracing logs |
Providers: 35 of 36
All 35 are ✅: bluesky, dev.to, discord, dribbble, facebook, farcaster (wrapcast), gmb,
hashnode, instagram, instagram-standalone, kick, lemmy, linkedin, linkedin-page, listmonk,
mastodon, mastodon-custom, medium, mewe, moltbook, nostr, pinterest, reddit, slack,
telegram, threads, tiktok, tiktok-business, tumblr, twitch, vk, whop, wordpress, x, youtube.
➖ skool: it only works through the Chrome extension, which was removed.
Known provider differences:
imagereplacessharp, and a hand-built PDF replacespdfkit, so output bytes differ. X and LinkedIn uploads need checking against the real APIs.- X articles use a small HTML parser instead of parse5.
- Rust’s regex has no lookaround, so a few patterns were rewritten as equivalents.
- Farcaster doesn’t validate BIP-39 words. Its Neynar endpoints come from public docs because the SDK source wasn’t available.
- Analytics dates use UTC rather than server-local time.
Engine
| Workflow | Status |
|---|---|
| Publishing, threads, pending media, token refresh, duplicate protection, repeats | ✅ |
| Missing posts and token refresh sweeps | ✅ |
| Plugs (global and internal) | ✅ dispatch tested at provider level |
| RSS autopost | ✅ posts feed items as they are; LLM rewrite and image generation removed by design |
| Streak, digest and transactional email | ✅ Resend tested against a mock; SMTP/SES are config-tested only |
| Media | ✅ JPEG conversion works on local and object storage (mock store in tests); thumbnails need ffmpeg |
| Short links (Dub, Short.io, Kutt, LinkDrip) | ✅ Short.io stats read up to 10 pages |
API and MCP
| Area | Status |
|---|---|
Public API /public/v1, including analytics, webhooks, tags, sets, signatures, customers, posting times | ✅ |
| MCP: 31 tools covering channels, posts, media, analytics, management, plugs, autopost | ✅ |
| CLI for agents over the public API | ✅ channels connect not run against a real login |
| Edit and reschedule posts, media delete, mention lookup | ✅ |
| Headless connections for every provider (Telegram, Moltbook, Farcaster included) | ✅ mock servers only |
Provider readiness (providers/status, early refusal when credentials are missing) | ✅ |
| MCP OAuth: PKCE, Client ID Metadata Documents, DCR for older clients | ✅ |
| MCP Tasks extension, polling | ✅ type: "now" only |
| MCP URL elicitation for login links | 🟡 implemented, no test with a real client |
MCP subscriptions/listen | ✅ polls the database; slow-client drop is untested |
| Storage: local, S3, R2 | 🟡 S3/R2 use a mock store in tests |
| Docker image | ⬜ Dockerfile exists, not built in this port |
Removed by design
Users, login, teams and invites (the API key identifies an organization), Stripe billing and
credits, admin, marketplace, the Chrome extension, the Node SDK, all media generation (image,
video, slides, clipping, HeyGen, ReelFarm, Seedance), HubSpot, and upstream’s LLM draft
splitting (/posts/separate-posts). Agents bring their own LLM and media tools.
Deliberate behaviour changes
- A stray job for an already-published post finishes silently; Postiz marks the post ERROR.
- Unknown publish errors wait 5 seconds before retrying.
- Request bodies are redacted before being stored in
Errors. - The server refuses to start without
JWT_SECRET;rustiz initgenerates it. - Only creating posts over REST uses
API_LIMIT, as upstream./mcpand other API routes get a separateREQUEST_LIMIT, and OAuth endpoints have per-address limits. - Media delete keeps the stored file, as upstream does.
- Importing data from an existing Postiz is not offered: hosted users’ account tokens stay on Postiz’s servers, so they would reconnect anyway.
/mcp/{key}is gone: API keys only travel in headers.previewUrlis gone fromschedulePostToolresults, since there is no preview page.