Skip to content

Concepts

The ideas that shape Keryx, and the reasoning behind each.

Why the authoring loop is human-in-the-loop

A reel is built in stages that iterate independently: distil the post into a storyboard, render a silent draft to check pacing, generate voice, generate music, generate card art, assemble, then compose the social copy.

The stages are separate because generation is non-deterministic and expensive. A voice-over take that reads a word wrong, an illustration with a stray letter in it, a music bed that fights the narration — each is a small fix, and each would be prohibitively slow if fixing it meant regenerating the whole reel. So every stage produces N candidate takes and you promote one; the promoted take is the committed input the assembly consumes, and re-rolling one line leaves every other selection untouched.

That is also why nothing auto-publishes. Taste is the point of the loop, and a generated artefact that nobody looked at is not something you want on a public account.

Why the storyboard is the single creative seed

The storyboard is an ordered JSON array of cards, and it is the only file that describes what the reel says. Each card carries the on-screen text, a separate vo narration, palette roles, an optional scene prompt for generated art, and resolved media.

Keeping the on-screen words and the narration as separate fields is deliberate. On screen you want a tight distillation that reads in two seconds; spoken you want a fuller sentence, possibly with pauses and phonetic respellings the renderer must never draw. Collapsing them into one field would force one of the two to be wrong.

Storyboards

Why themes are configuration rather than code

Palette, fonts, card treatment, illustration style, music tone and voice settings all live in configuration, identified by a keyword.

Two things follow from that, and both were the reason. A run of reels sharing one hard coded look is monotonous, and varying it should not require a release. And a second brand — or somebody else's project entirely — should be new configuration, not a fork.

It is also why no themes ship in the binary. A style library baked into a reusable tool would mean every install inherits one project's taste, and changing that taste would mean cutting a release. So a fresh install has an empty catalog and says so.

Themes

Why every backend sits behind an interface

Image, video, voice, music and rendering each have a narrow Go interface, and the concrete adapter is chosen from configuration at construction. No call site names a vendor; requests carry Keryx's intent — a prompt and an aspect, narration text and clone settings, a timeline of segments — and each adapter maps that to its own API.

The immediate payoff is not vendor choice, which barely exists yet: it is testability. Because every backend is an interface, the deterministic core — timing maths, text wrapping, theme resolution, the posting ledger — is unit-tested with no network, no ffmpeg and no API keys.

Providers

Why posting has an approval gate

Each platform's social set moves draft → approved → posted, with an optional schedule per outlet. Posting refuses anything not approved.

This exists because the unattended path is real: a scheduled CI pipeline runs keryx post due with credentials, on its own. Without an explicit human approval recorded in the repo, a mistake in a storyboard becomes a public post nobody chose to make. Approval is the point where a person takes responsibility, and it is recorded in git alongside what was approved.

Why Keryx keeps no state of its own

There is no Keryx database, no per-project cache outside the workspace, and no server. The owning project's git repo is the store, and it is also the concurrency boundary: two people editing the same reel conflict the way two people editing the same file conflict, with a tool they already know.

The cost is that large media in git is awkward, which is what the configurable object store is for — the workspace keeps the authored state and a manifest, and the blobs live in S3, GCS, Azure or a local directory.

The benefit is that a reel is reproducible from committed inputs. When every selected asset is also locked, reel build says so, and that claim is checkable by anyone with the repo.

Reel workspaces · Generation cache