Munchable's social videos are not screen recordings. They are sixteen React components, rendered to 1080x1920 MP4 by Remotion, and the phone inside them is a rebuild of the app's own screens rather than a picture of one.
That sounds like the hard way to make an advert. It is, for about a week. Then it starts paying you back in a currency screen recordings cannot offer: the advert cannot say something the product would not.
The claim in the video is computed, not typed
Every Munchable reel shows a phone scanning a product and giving a verdict for someone's gut condition. The verdict in the frame is not a string in the composition. It is the output of the production rules engine, imported into the video package and called at render time:
/**
* Every verdict in a reel comes out of @munchable/rules-engine at render time.
* There is no hand-typed "Good fit" anywhere in the compositions, so the reels
* cannot promise something the app would not say.
*/
export function assess(def: ProductDef, profile: Profile): FitCheck {
return fitCheck(engineProduct(def), profile);
}
The profiles in the reels are real profiles: one condition, two conditions, a lactose sensitivity setting turned up or down, a declared allergy sitting above a condition. The engine reads the demo product's ingredient list and returns what it would return on a phone in a supermarket.
Change a rule and re-render, and the video updates or it visibly stops making the point it was cut to make. Either outcome is honest. A screen recording, by contrast, is frozen marketing from the day it was captured, and nothing in your repository knows it exists.
If your product makes a claim on camera, the claim should be executable.
The look is imported, not matched
The first version of the theme file hand-copied the palette and the labels out of the app, under a comment promising they mirrored it. That comment aged exactly as well as you would expect. Change the caution colour in the app and the reels keep rendering the old one, with no type error and no test failure, because a copy is not a dependency.
Now the palette, the spacing scale, the verdict icons and the verdict vocabulary are imported from the shared design tokens package that the mobile app itself re-exports. What the video package defines is only what a video needs and an app does not: CSS font stacks, pixel line heights, and the dark card the camera picture sits in.
The same rule applies one level up. The four screens that appear in the reels (scan, result, capture, recipes) are components that follow the app's real layout, including the modal header, the verdict hero, one disclosure row per condition with the engine's own reason sentences underneath, and the standing disclaimer. Not "something that looks like the app". The app's structure, drawn with the app's tokens, filled by the app's engine.
There is a deliberate exception worth mentioning, because it is the opposite decision: our marketing website does not consume the design tokens package. A website has its own typography, its own density and its own reasons to change, and coupling it to a phone app's tokens would make both worse. The rule is not "share everything", it is "share the things that must never disagree". A verdict colour must never disagree. A hero font size is allowed to.
The cast is generic on purpose
Every product in the reels is an invented pack: a made-up brand, a plausible name, and a real ingredient list.
Generic because real brands in a paid placement are a trademark problem you do not want to discover after the spend. Real ingredient lists because the whole premise is that the engine scores them, and you cannot score a label that says "ingredients go here".
One detail I did not anticipate needing. Pack colours are constrained to stay off green and red:
const PACK = {
sky: ['#BFD9F2', '#8FB6DC'],
butter: ['#F7DFA0', '#DEBE63'],
blush: ['#F9C9D4', '#E497AB'],
};
In a video where green and red mean "suits you" and "avoid", a green box on the shelf reads as a verdict before the scan has happened. The palette has to leave the semantic colours alone so the meaningful ones stay meaningful. Any interface with a colour vocabulary has this problem; video makes it obvious because the viewer sees the shelf for two seconds and draws a conclusion.
The test that keeps the cast honest
The ingredient ids for each demo pack are hand-typed next to its ingredient text, which is exactly the kind of thing that drifts. So:
test('every reel product is built from ids the engine knows', () => {
const unknown = [];
for (const [key, product] of Object.entries(PRODUCTS)) {
for (const tag of product.ingredientsTags ?? []) {
if (!isKnownTag(tag)) unknown.push(`${key}: ${tag}`);
}
}
assert.deepEqual(unknown, []);
});
Without it, a typo means the reel scores a product carrying an unknown ingredient, which the engine handles by applying a confidence penalty the app would never apply to the real product. The video would still render, look fine, and quietly show the wrong verdict. Worse, a rule added later to the correct id would change the app while the published video kept showing the old answer.
Marketing assets rot silently. Tests are how you hear about it.
Two small things I would do again
A proof sheet that is not a reel. One composition renders every pack in the cast, front and back, so label copy can be proofread in one still instead of by scrubbing sixteen videos. It ships in the same registry as the reels and is marked as not being one.
Composition ids validated, then passed as arguments. The render script checks each requested id against the known set and passes them to Remotion as an argument list rather than interpolating them into a shell string. A typo now prints "Unknown composition" and the known list, instead of failing somewhere deep inside a renderer twenty seconds later.
The reels are also silent by design. The app has no sound effects, so neither do the videos; music is added later in an editor rather than baked into a render.
See the engine for yourself
The reels live on social, but the thing that makes them trustworthy is public, because the same engine produces the answers on the website:
- munchable.app/answers, 373 pages whose verdicts are computed the same way the reels' are
- munchable.app/conditions, what each condition's rules actually check
- munchable.app/recipes, recipes filtered by those same rules
- app.munchable.app, the app the phone in the reels is drawn from
If you are making product video with code, the test is simple. Pick the most confident claim in your advert and ask which module computes it. If the answer is "the video file", you are maintaining two products that will disagree.
Top comments (0)