Files
mintel.me/apps/video/CLAUDE.md
T
mmintelandClaude Opus 5.5 4bfbcbcacd feat: video films for social media, with the skill to make more
Adds apps/video, a standalone Remotion package (not part of the pnpm
workspace, so it never reaches the web build or the Docker image). It
renders six looping films, one per service, in German and English, as
4:5 for LinkedIn and 16:9 for YouTube and ads, together with the text
to post and an overview page.

Each film is one continuous shot: close on something abstract, the
camera pulls back to show what it really is, the form changes, and the
picture folds back into its opening. The slide deck code from the
earlier attempts is still in the package and no longer used.

Also adds the Google Ads concept, brings the relaunch concept in line
with the site as built, and a project skill that describes how to make
further films.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 21:23:01 +02:00

6.7 KiB

apps/video

Social media videos (LinkedIn first, 16:9 for YouTube and Google Ads) in the mintel.me look, made with Remotion. Standalone package: it is not in pnpm-workspace.yaml, so it never ends up in the web build, the Dockerfile or pnpm -r. apps/web must never import from here, and this package imports nothing from apps/web.

Commands (run from this folder)

  • Install: pnpm install --ignore-workspace
  • Studio (the playground, http://localhost:3000): pnpm studio
  • One frame as PNG: pnpm still WebsiteDone-de-feed out/check.png --frame=40
  • One video: pnpm render WebsiteDone-de-feed out/website.mp4
  • The whole library: pnpm library (= node scripts/export.ts; --only <VideoId>, --formats feed,wide, --page to rewrite only post texts and the overview). Writes out/library/index.html (watch, copy the post text, download) and out/library/<video>/<language>/ with the MP4s and post.txt.
  • pnpm typecheck, pnpm test

Compositions are named <VideoId>-<language>-<format>: languages en, de; formats feed (4:5, LinkedIn), wide (16:9), square, story (9:16). out/ is gitignored.

Where things are

  • src/content/videos.ts: every word. Headlines per slide, the post text per video, both languages, and the German for labels inside drawings (LABELS_DE). Drawing code writes labels in English; they are translated when rendered. German addresses the viewer as "Sie".
  • src/compositions/<Video>.tsx: the slides of one video (ids, durations, illustrations). No text.
  • src/slides: SlideDeck (panel, headline, curtain, loop, portrait and 16:9 layout), ServiceVideo (frame + language + deck), ctaSlide (closing slide with the button).
  • src/illustrations: parts.tsx (tile, icon, cursor, data chip, window, page, badges, day box), scenes.tsx (scenes several videos share), motion.ts (easing helpers).
  • src/brand: tokens, fonts, BrandFrame (logo, labels, digit texture), Panel (the dark panel with the website's light effects), BrandButton.
  • src/lib: pure, tested logic (bits.ts, aura.ts).

How to make a new video

  1. Add the texts to src/content/videos.ts (new VideoId, both languages, post text).
  2. Add src/compositions/<Name>.tsx with its slides and register it in src/Root.tsx.
  3. Look before reporting: render the MP4, pull one frame per slide and read them, in feed and wide, in both languages (German lines are longer). Do not hand over a video you have not seen.
  4. pnpm library --only <Name> and tell the owner where the files are.

Films (the current format, owner approved 2026-10-04)

Every video is a film in src/films: one continuous shot on a dark stage, not a deck of slides.

  • Shared: FilmStage (backdrop, one centred statement at a time, signature, address) and shot.ts (one timeline T, the camera move cameraAt, the six caption slots hook/reveal/problem/turn/calm/cta).
  • The pattern: close on something abstract that looks like something else ("Looks like ping-pong."), the camera pulls back and shows what it really is ("It's your office."), it stops, resolves, rests, and returns to the opening picture so the film loops. Frame 0 is the preview image.
  • Minimal and calm (owner feedback: earlier versions were hectic). Only squares, dots, lines and bars; no icons or labels in the drawing. One statement of two short lines, held for about three seconds. A little sarcasm in the hook is welcome. German has to read like a native wrote it.
  • One font size per film: the largest at which the longest line fits, so keep lines short.
  • The logo is the white signature (public/logo-mark.svg): bottom left, and very large and faint behind.
  • The slide deck code (src/slides/SlideDeck, src/illustrations, BrandFrame, Panel) is no longer used by any video and can be removed once the owner confirms.

Rules

  • Before any work: bring the worktree up to date with main (owner feedback, twice). Take wording, styles and effects from the website as it is now: texts in apps/web/src/content/de.ts and en.ts, styles in apps/web/app/globals.css, drawings in apps/web/src/components/illustrations. Do not state prices, terms or durations that are not in the texts.
  • Picture first, few words (owner feedback): 6 to 8 slides of about 2 s, each one large animated illustration plus a headline of two to four words. No paragraphs, no captions.
  • It has to look stunning (owner feedback, repeated: "not enough yet"). The videos carry every effect of the website: the dark Panel with BitAura (light along the edge, digits drifting off), BitGlow (light over the dot grid) and bit-aurora (indigo light drifting behind the drawing); slides change with the BitCurtain (ragged front of digits, src/lib/curtain.ts); the button has the bit-cta light running round its edge. When the website gets a new effect, bring it here as a pure function of the frame in src/lib.
  • Drawings follow PathScenes.tsx: fine light lines, tinted glass surfaces (DRAW.tint, DRAW.glass) instead of solid blocks, amber packets with a halo (DRAW.mark), emerald for done, soft glows on what is active.
  • UI in a video must be the website's real UI, rebuilt faithfully (owner feedback): read the component in apps/web/src/components first. The button is BrandButton (twin of Button.tsx); do not draw your own.
  • Almost no frame (owner feedback: the drawing matters far more than what surrounds it). No border, no name, no topic label, no progress bar. Only one small line at the bottom: the logo, small and dimmed, and www.mintel.me (with www. so that it reads as an address). The stage is scaled as large as the frame allows.
  • Light is drawn with plain gradients that fade to transparent. No filter: blur, mix-blend-mode or dashed strokes for glows: they came out with hard edges in the rendered video (owner feedback).
  • Every video loops: the first slide is complete on frame 0 (it is the preview image) and fades back in at the end. Anything that moves outside the slides (Panel) must repeat exactly over the length of the video.
  • Frame-driven only: all motion comes from useCurrentFrame() / interpolate(). No setTimeout, setInterval, CSS animations, Math.random() or framer-motion: they do not render correctly frame by frame. Pure logic goes in src/lib with a *.spec.ts.
  • 30 fps, about 15 seconds. The video must work without sound and make sense in the first two seconds.
  • Copy rules as on the website (see root CLAUDE.md): no AI as the owner's tool, no internal method vocabulary, modest and factual, no promises the owner did not confirm. Never write the full email address.
  • The hero design of the website (binary-digit headline) is approved: do not recreate it here with changes.