Files
social/index.html
T
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

54 lines
2.0 KiB
HTML

<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8" />
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="color-scheme" content="dark light" />
<title>Hanzo Social</title>
<meta
name="description"
content="Write once. Publish to every account you own, now or on a schedule."
/>
<style>
/* The two things only the host document can answer: how tall the app is,
and that its one child is a flex item. @hanzo/ui's stylesheet resets and
paints everything else. Without this the app grows to fit its content
instead of filling the window, and every pane that scrolls inside it
scrolls the page instead. */
#root {
display: flex;
height: 100dvh;
}
</style>
<script>
/* Keep gui's theme class in step with next-themes'. One decision, two
names: next-themes writes `light` on <html> and gui reads `t_light` /
`t_dark`, so without this the account's choice moves one of them and the
page stays painted the other way.
`was` is not an optimisation — a `classList.toggle` that changes nothing
still writes the attribute, and an observer reacting to its own write is
a loop. Comparing first makes the callback a no-op unless the theme
moved. Inline and in <head>, because the first paint happens before any
module runs. */
;(function () {
var e = document.documentElement, was
function s() {
var l = e.classList.contains('light')
if (l === was) return
was = l
e.classList.toggle('t_light', l)
e.classList.toggle('t_dark', !l)
}
s()
new MutationObserver(s).observe(e, { attributes: true, attributeFilter: ['class'] })
})()
</script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>