Overview
Socialog is a social-media scheduler. You write a post once, attach media, choose which connected accounts it goes to and when, and Socialog publishes it — to X, Instagram, Threads, LinkedIn, YouTube, Pinterest and Paragraph, each through that platform's own API. The pitch is the one every scheduler makes: stop pasting the same thing into five different tabs. The interesting part is everything behind that promise, because "publish one post to seven networks, reliably, on a schedule" turns into a surprising amount of engineering once you take the reliability seriously.
I built and run Socialog solo — the product, the publish engine, the billing, the marketing site, and the mascot (Memo, a small elephant who "never forgets to post"). It's built on TanStack Start running on Cloudflare Workers, which shapes a lot of the decisions below: the publish loop is a Worker cron, media lives in R2, and the database is reached through Hyperdrive at the edge.
The product
The core surface is a calendar and a composer. You draft a post, attach images or video from a media library, pick the target accounts, and either save it as a draft or give it a scheduledAt time to queue it. A post can go to several accounts at once, and each account is a separate publish target underneath, so one of them failing doesn't take the others down with it.
Around that sit the things a real scheduling product needs: OAuth connections per network, teams so more than one person can share a content calendar, per-plan limits enforced through billing entitlements, and an analytics view that pulls engagement metrics back from the platforms that expose them. There's also a content studio for assembling short-form vertical video from images, clips and music — with AI generation layered on top — that feeds straight back into the scheduler.
The publish engine
The heart of the product is a small, boring, correct queue. Every minute a scheduled tick wakes up at the edge, claims the batch of posts that are due, and publishes them. The design constraint that shapes everything is that ticks can overlap and workers can die mid-publish — so the engine is built so that no matter how ticks race or crash, a post publishes exactly once. Claiming a post is atomic, two concurrent ticks can never pick up the same one, and each tick takes a bounded batch so a backlog drains steadily instead of stampeding.
Failure handling is designed in rather than bolted on. Every failure is classified as retryable or fatal: retryable ones go back into the queue with backoff and a cap, fatal ones fail fast with a clear status the user can see. And because some platforms publish in multiple steps that can be interrupted halfway, the engine records its progress — a retry resumes the publish it started rather than creating a duplicate post. The scheduler itself knows nothing about the edge runtime it runs on, which is what lets the exact same engine run under a local ticker in development.
One adapter per network
Every network is its own little world. X wants media uploaded in one way, Meta wants a multi-step create-then-publish dance, and Paragraph isn't even a social network — it's a newsletter platform that emails subscribers. Rather than let those differences leak into the engine, each platform lives behind its own adapter with one shared contract: the engine hands over a neutral, platform-agnostic description of "this post, this media, this account" and the adapter deals with that network's quirks.
That boundary is what keeps the system honest. The queue, retry, and exactly-once logic live once, in the engine; a new network is just one more adapter that inherits all of it for free. There's also a fake publisher that stands in for demo accounts, so the whole product can be shown and tested end to end without posting to anyone's real profile.
One detail I'm fond of: media is uploaded to an R2 bucket and served from a public URL specifically because the platforms pull it themselves at publish time. Meta and X don't want your bytes inline; they want a URL they can fetch. Modelling media as "already a public URL" by the time it reaches an adapter made every adapter simpler.
Built for agents
Socialog is usable by a person in a calendar and by an AI agent over a tool call, and both go through the same core. Alongside a versioned REST API there's a full MCP server: list and create posts, attach media, read analytics, list connected accounts. The tools are scoped — posts:read, posts:write, and so on — and authenticated with API keys, the same scopes that gate the REST surface.
That symmetry is deliberate. An agent can prepare a scheduled post now and leave the accounts to be attached by a human later; a post that reaches its time with no accounts is simply skipped rather than published to nowhere. Building the agent interface on the same server functions the UI uses means there's one definition of what "create a post" means, and it's correct in both places.
Architecture
The whole product — app, API, publish engine, webhooks — ships as a single Cloudflare Worker built on TanStack Start with React 19. Data is Postgres, reached through Hyperdrive so the edge gets pooled, low-latency database connections, with Drizzle as the data layer. One deploy, one runtime, one place for secrets: for a solo-run SaaS, keeping the operational surface that small is a feature in itself.
Auth is Better Auth with passkey support; billing is Polar, with plan entitlements enforced inside the publish loop itself — limits hold at the moment of publishing, not just in the UI. The most sensitive thing in the system is the users' platform OAuth tokens, so those are encrypted at rest and only decrypted at the moment a publish call needs them. A second scheduled job syncs engagement analytics back from the connected accounts, reusing the same adapter-per-platform shape as publishing.
What I'm proud of
The thing I like most about Socialog is that the hard part is invisible. A user sees "I scheduled a post and it went out." Underneath, that sentence is a race-free atomic claim, a per-platform adapter negotiating a different API for each network, encrypted tokens, idempotent retries against services that can duplicate on you, and a queue that runs on infrastructure designed to kill your process mid-request. Getting all of that to feel like one calm calendar — as one person — is the work.
