social-sdk: one typed publish call across seven platforms and five hosted backends
Typed TypeScript SDK for direct and managed social platform integrations, with capability checks, explicit outcomes, and deterministic testing.
At a glance
- What is it?
- Social SDK is a TypeScript toolkit that publishes, reads and analyses content on X, Threads, Bluesky, YouTube, TikTok, Instagram and LinkedIn through one typed interface, with either direct adapters or hosted backends behind it. It suits small teams adding a social feature, and it asks you to read the capability matrix before assuming two platforms behave the same.
- Who is it for?
- social-sdk is worth adopting for a small team that needs to publish to more than one social network from one server-side codebase, because the client shape, the capability manifests and the per-destination outcome model mean you write the publish call once rather than seven times, and because the mock backend lets you build and test that call before you own a single credential.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One client shape, two very different ways to reach a platform
Social SDK is an open-source TypeScript toolkit aimed at solo founders and small teams adding social features to their apps. The promise in the project description's own words is to publish, read and access analytics or comments where available across X, Threads, Bluesky, YouTube, TikTok, Instagram and LinkedIn through a typed interface.
The interesting design decision is that there are two ways to reach any of those platforms, and the client shape does not change between them. The first is direct platform access, with an adapter per platform. The second is a managed backend, and the named ones are Zernio, Post for Me, PostFast, Postiz and Buffer.
What direct versus managed actually changes is where the credentials and the policy compliance live. With a direct adapter you hold the OAuth tokens, you deal with each platform's rate limits and review requirements yourself, and you are exposed when a platform changes an API. With a managed backend you hold the backend's credentials, the backend holds the platform credentials, and it absorbs some of the churn, at the cost of routing your content through someone else's service. The documentation is explicit that managed services are optional and that a direct integration does not require a Social SDK account.
The topics list covers the platform names, and the OAuth and atproto tags point at the two authorisation families in play: OAuth 2 for the walled gardens, and AT Protocol for Bluesky. That is a real structural difference between the platforms, and one that any SDK covering all seven has to paper over.
Outcomes are per destination, and four states is not three
The outcome model is the part of the design that tells you the author has thought about the hard cases. Each publish returns independent per-destination outcomes, and there are four states: complete, processing, uncertain and failed.
Complete is obvious. Failed is obvious. Processing means the platform has accepted the work and is still working on it, which happens with anything that goes through a media processing pipeline before it becomes a public post. Uncertain is the interesting one, and it is the state that decides whether your integration is trustworthy. A network timeout after a request was sent leaves you unable to tell whether the post went out, and treating that as failed leads to duplicate posts, while treating it as complete leads to a post you thought you had scheduled and did not.
The documentation list points at a page on handling outcomes and reconciliation, and that page is the one to read before writing the retry logic. The quickstart example prints exactly these two fields, the overall status and the first outcome's state, and in the mock scenario it prints complete and published, which is the happy path and the least interesting case.
The other detail worth noting is idempotency. The publish call takes an idempotencyKey, and the example uses a fixed string. A key lets the platform recognise a retry as the same request, which is the mechanism that makes the uncertain state recoverable rather than a source of duplicates.
The mock backend lets you build the whole flow without a credential
The recommended first step is the mock backend, and the reason given is concrete: to verify an integration without credentials, platform calls, or billable provider requests.
The whole example is short. You create a client with createSocial, passing a backend built by mockBackend with a named scenario, then call posts.publish with a list of targets, content, and an idempotency key:
import { createSocial, connectedAccountRef } from "@opencoredev/social-sdk";
import { mockBackend } from "@opencoredev/social-sdk/testing";
const social = createSocial({
backend: mockBackend({ scenario: "immediate-text-success" }),
});
const result = await social.posts.publish({
targets: [
{
account: connectedAccountRef({
backend: "default",
platform: "x",
accountId: "mock-account-1",
}),
},
],
content: { text: "Hello from Social SDK" },
idempotencyKey: "quickstart-1",
});
console.log(result.status, result.outcomes[0]?.state);
// complete publishedTwo things about the shape of that call are worth pausing on. The mock backend is imported from a separate subpath, @opencoredev/social-sdk/testing, so the testing surface is not in your production bundle by accident. And the account is referenced through connectedAccountRef with a backend name, a platform and an account id, which is what lets the same target structure work whether that account is a direct X credential or a managed one.
The scenario name, immediate-text-success, implies there are others. A mock with named scenarios is a contract test in disguise, and the project documentation lists a deterministic mock backend for local development and contract tests as a headline feature.
A deliberately offline CLI for discovery and validation
The social-sdk CLI is offline. The documentation is specific about what that means: it does not authenticate accounts, upload media, publish content, or make hidden network requests.
That constraint is the point. A CLI that quietly talks to a platform is a CLI you cannot run in CI without spending API quota or triggering a review. This one can be run anywhere, including in a pipeline, and it still answers the questions you actually have when an integration is not working: which adapters exist, what a given adapter supports, whether a request body is shaped correctly, and what a specific backend looks like when the doctor runs.
The commands are:
npm exec -- social-sdk adapters --json
npm exec -- social-sdk capabilities --adapter youtube --json
npm exec -- social-sdk doctor --adapter zernio --json
npm exec -- social-sdk examples --json
npm exec -- social-sdk validate --adapter mock --file request.json --jsonEvery one of them takes --json, which is the right default for a tool meant to be scripted. The capabilities command with a named adapter is the one to reach for when you need to know what an adapter can do, and validate with a request file is the one to run in a test to check that a payload you are about to send is well formed before you send it.
One packaging detail catches people out. The package installs the binary into the project's node_modules/.bin, which is not on the shell PATH, so you invoke it through npm exec from the project directory, or replace npm exec -- with bun run under Bun.
The capability matrix is the contract you code against
The documentation tells you to read the platform capability matrix before choosing an adapter, and to treat it as describing the normalized operations each integration implements. That is a small sentence with a large consequence: the seven platforms do not offer the same operations, and the matrix is where that difference is written down.
Some of it is obvious once stated. Reading comments exists on some platforms and not others. Analytics coverage differs. Video and media handling differs. The topic list includes atproto, which is Bluesky's protocol, and the project documentation mentions atproto in the context of OAuth, so the authorisation flow for Bluesky is not the same OAuth dance as the others.
The documentation also puts a limit on what the matrix is worth, and it is an important one: it does not replace provider permissions, account eligibility, or live verification. In other words, a green cell in the matrix means the SDK implements the operation, not that your account is allowed to perform it. Review requirements, app review for new applications, per-platform permission scopes and account standing all sit outside the SDK's reach, and a normalised interface cannot hide them.
So the SDK saves you the per-platform API plumbing and the per-platform response shapes. It does not save you from per-platform policy, and a team that has never published to any of these platforms will still have to learn the rules for each one.
Node 22 or Bun, and secrets that must stay on the server
The install is a normal package install:
npm install @opencoredev/social-sdk
# or
bun add @opencoredev/social-sdkThe runtime requirement is stated before the install command, not after: Social SDK runs in trusted server-side code on Node.js 22.12+ or Bun, and the instruction is to keep platform tokens, managed-provider keys, OAuth secrets and webhook secrets out of browser bundles.
That is a hard architectural boundary rather than a style preference, and it is the one that decides whether the SDK fits your product. A social publishing feature in a Next.js application belongs in a route handler or a server action, not in a client component. If the feature you want is a browser-side composer that posts as the current user, this library is not the tool, and a client-side OAuth flow for these platforms has its own constraints that the SDK explicitly does not address.
The repository itself is a Bun workspace: the root package.json is private, with workspaces of apps/* and packages/*, Turbo for task orchestration, oxlint and oxfmt for linting and formatting, changesets for versioning and a bun.lock. The scripts show a strict release path, with a release:gate that runs before release:ci, a check that runs lint, format check, type check, tests and a rebrand check in sequence, and separate benchmark scripts. The published package is scoped as @opencoredev/social-sdk and the current release is 0.5.0, published on 2026-09-24 alongside 0.4.0 and 0.3.0 the same day.
Where social-sdk is the wrong tool
The first limit is the server-side requirement, and it is the one that excludes the most projects. There is no browser build, and the documentation tells you to keep every secret out of browser bundles, which means the whole integration has to sit behind a server. A pure front-end app with no backend has nowhere to put the tokens.
The second limit is that the platforms are not uniform and the SDK does not make them uniform. It normalises what it can and publishes a manifest for what it cannot. If your product depends on a specific Instagram or TikTok capability that no adapter implements, no amount of TypeScript will conjure it, and the closest you get is the capability matrix telling you so.
The third is the dependency on hosted providers if you take the managed route. A managed backend means your publishing pipeline depends on that provider's availability, its own rate limits and its own data handling, and it means you are paying for requests you might otherwise make directly. The sponsors listed in the project documentation are PostFast and Postiz, so the project is partly funded by the hosted route, which is worth knowing when you weigh the two options.
The fourth is maturity. Version 0.5.0 with three releases in a single day in September 2026 is a fast-moving 0.x package, and the semver pre-1.0 convention means minor versions can carry breaking changes. The changesets setup in the repository is the right mechanism for communicating them, but you should expect to read the changelog on every upgrade rather than take a patch bump on faith. The last push was on 2026-10-18, so the project is being worked on.
Editorial conclusion
social-sdk is worth adopting for a small team that needs to publish to more than one social network from one server-side codebase, because the client shape, the capability manifests and the per-destination outcome model mean you write the publish call once rather than seven times, and because the mock backend lets you build and test that call before you own a single credential. It is the wrong tool for a browser-only application, since the documentation is explicit that tokens and secrets must stay out of browser bundles, and it is the wrong tool if you need a platform operation the capability matrix does not list. Before you commit, check the three things the documentation points you at: the platform capability matrix, which describes the normalized operations each integration actually implements and which does not replace provider permissions, account eligibility or live verification; the outcome states, since a publish can end up complete, processing, uncertain or failed per destination and your code has to handle the uncertain case; and whether you want direct access or a managed backend, since the two paths share the client shape but differ in where tokens live and who absorbs the platform policy changes.
Frequently asked questions
How do I install social-sdk?
Run npm install @opencoredev/social-sdk, or bun add @opencoredev/social-sdk under Bun. It runs in trusted server-side code on Node.js 22.12 or later, or on Bun, and platform tokens, managed-provider keys, OAuth secrets and webhook secrets should be kept out of browser bundles.
What is the difference between a direct adapter and a managed backend in social-sdk?
Direct platform access uses an adapter for Bluesky, Instagram, LinkedIn, Threads, TikTok, X or YouTube, and you hold the platform credentials. The managed route goes through Zernio, Post for Me, PostFast, Postiz or Buffer instead. The client shape is the same either way, and managed services are optional, so a direct integration does not require a Social SDK account.
What do the four publish outcome states mean in social-sdk?
Each destination gets its own outcome, and the states are complete, processing, uncertain and failed. The distinction that matters is between uncertain and failed, since an uncertain result leaves you unable to tell whether the post went out, which is what the idempotencyKey on the publish call is there to make recoverable.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/opencoredev-social-sdk)Was this useful?