zeekayandHanzo Dev 50aa91efd4 Hanzo Social — publish to every account an org owns
A social publishing surface on @hanzo/gui + @hanzo/ui, written against the
platform's own /v1/social and /v1/integration. Six screens: the org roll-up,
a composer, the posts in every state, a month calendar, the networks with
their consent and their handles, and the delivery record.

Two facts shape it. A post carries one channel, so the composer stores one
post per network — which is also what makes writing separately for a single
network free, since it is a different content on that row. Media is a list of
addresses, so a video is ordinary content rather than a second kind of post,
and each network's own rules are checked before the post is stored rather
than discovered at a publish hours later.

State is drawn in luminance on a palette with no hues, and the inversion is
spent once per screen on the thing a person has to act on. Refusals are the
platform's own sentence, read off the RFC 7807 detail the SDK's extractor
drops — a 503 that names the missing credentials is the whole of what anyone
can act on.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 06:40:41 -07:00

Hanzo Social

Write once. Publish to every account your organization owns — now, or at a time you pick.

Seven networks: X, Facebook, Instagram, LinkedIn, TikTok, YouTube, Threads. Text, photos and video on every one of them that takes video, which is all seven.

Run it

pnpm install
pnpm dev        # http://localhost:3300

The port is pinned because it is half of a redirect: IAM returns the browser to the address the client registered, and that address carries the port.

vite.config.ts proxies /v1 to api.hanzo.ai on both the dev server and the preview of a build, so a localhost origin reaches the gateway without failing a preflight. Point it elsewhere with VITE_HANZO_API.

How it is put together

src/social.ts Every /v1 address this app speaks, in one file
src/network.ts What each network accepts, and whether this post satisfies it
src/status.tsx How a state is drawn on a palette with no hues
src/client.tsx The platform client, and the organization it speaks for
src/page.tsx The heading, the signed-out gate, the way a refusal reads
src/post.tsx One post, as every pane shows it

Six screens, one per address: Overview, Compose, Posts, Calendar, Accounts, Analytics. src/routes.tsx is the table, and the sidebar reads the same one.

Two planes, not one

A network needs both before anything goes out, and the Accounts screen shows them side by side:

  • /v1/integration — the organization's credential for a network. The OAuth consent a person gives once, sealed into KMS. Connect leads here.
  • /v1/social — the accounts a post fans out to, and the posts themselves.

No credential ever reaches this code. GET /v1/integration/connectors/:id/token is the platform's one custody exit and nothing here calls it: a browser has no use for a provider token, and a surface holding one would be a place to leak it from.

What it does not do

The platform records no engagement — no views, likes or reach — and no endpoint serves any, so the Analytics screen measures delivery and says so. Bluesky is not here because the platform's channel vocabulary does not carry it. Media is given as an address rather than uploaded, because a presigned URL expires and a network fetches the media when the post goes out.

S
Description
Mirror of github.com/hanzoai/social
Readme
14 MiB
Languages
TypeScript 94.2%
CSS 2.8%
HTML 1.6%
Dockerfile 1.4%