Alter

Elixir · Phoenix · Postgres · Oban · Rust

A production content system, built and run by one engineer.

Alter drafts, illustrates, voices, renders and publishes video for two YouTube channels, then measures what happened and writes it back against every decision that went into the upload. It has shipped every week since August 2026 on infrastructure its author owns.

Read the engineering notes Not taking new accounts

Live. The always-on collector has been sampling competitor uploads hourly since 13 September.

86

migrations, every one run on a live database

2,505

tests, 44k lines of them against 111k of code

31

background workers across 8 queues, on two nodes

647

commits since 31 July 2026

One pipeline, from a topic to a measured upload.

A topic becomes an 800-line episode specification, checked by the same builders that render it. The spec drives picture generation, voice synthesis and the render, and the three agree on file names through one function, so nothing is stitched by hand. A human approves once, on a review page. Then the upload is scheduled, published, and read back.

01 · Draft

Spec from topic

LLM drafting through plain tool use, never constrained decoding: measured 6 usable sets in 6 against 2 in 12 the other way.

02 · Make

Pictures, voice, render

Image generation with a receipt per candidate, ElevenLabs voice, and a Rust document renderer on Skia/Metal at 5 ms a frame.

03 · Approve

One human step

A review page is the only gate. Approving runs the brand's publish rule; nothing goes public by accident and nothing waits on a person twice.

04 · Measure

Outcome joined to choice

Retention curves land on the exact scene timeline the render recorded. Impressions, velocity and the public label are read back on a schedule.

How it's built.

Release discipline

Every push passes mix compile --warnings-as-errors, a format check and the full suite. Lessons that cost money are pinned as tests, not written in a wiki: the node-role test that stops the collector from ever holding a publish queue, the fidelity probes that read pixels back from the renderer, the test that keeps renders out of the Desktop root. A regression has to get past the thing that already caught it once.

Migrations on live data

86 migrations across 44 tables, including a rename of the core tenant model (personas to brands) and a swap of a column's meaning under running jobs, both applied to a production database with users on it. Append-only where history matters: picture decisions are a log, never an update.

Infrastructure, owned

Two Elixir nodes on one Postgres: an always-on collector restricted by role to the queues it's allowed, and an app node that renders and publishes. Deploys through Kamal to hosts the author runs, EU hosted, with secrets, access control and logging owned end to end. Query logging is off in production by design, so OAuth tokens can never reach a log file.

Measurement and prediction

A competitor corpus of about 750 videos across 15 channels, sampled for view velocity at 1 h, 6 h, 24 h, 48 h and 7 days from upload, with an LLM structure pass over every public transcript run through the Batch API under a cost cap. A production ledger records each generation, each picture decision and each upload choice so it joins to the outcome. Hypotheses are first-class rows with arms. More on the about page.

Security and scope

Multi-tenant from the first migration: organisation, then brand, with every context query scoped. Magic-link login with a rate limit, HMAC-verified inbound webhooks, and a content security policy built at request time so the media host is the only third-party origin allowed.

Written with AI assistants, under review

Most of this code was drafted with an AI coding assistant and none of it shipped unread. The project file that steers the assistant holds the invariants that were paid for the hard way, and the rule is that a fix names its root cause or it doesn't merge.

The measurement is allowed to say no.

The corpus was built to find what predicts a video's reach. Across 713 videos it found that nothing about the video does: within one channel the spread from the 10th to the 90th percentile is 15x to 500x, and neither hook, title, length nor time-to-first-round moves it. Two "measured" claims in an earlier plan were wrong, and the plan says so now.

That readout changed the strategy from tuning openings to raising production rate, which is a cheaper answer and a truer one.

Alter runs its author's channels and isn't taking new accounts.

The engineering notes explain the system, the decisions, and what's being built next.

Engineering notes