Skip to content

Instantly share code, notes, and snippets.

@StarKnightt
Created July 16, 2026 17:38
Show Gist options
  • Select an option

  • Save StarKnightt/596128c1690858db1c7e1d55a66a26fd to your computer and use it in GitHub Desktop.

Select an option

Save StarKnightt/596128c1690858db1c7e1d55a66a26fd to your computer and use it in GitHub Desktop.

Build a 6-second, Apple-style motion video announcing a Twitter/X handle change, rendered as a real MP4 using Remotion (React + TypeScript). Follow every spec below exactly — colors, frame numbers, easing configs — they are tuned values, not suggestions.

CUSTOMIZE (fill in your own)

  • DISPLAY_NAME: "Your Name" — your display name as it appears on X
  • OLD_HANDLE: "your_old_handle" (without @)
  • NEW_HANDLE: "your_new_handle" (without @)
  • AVATAR: your profile photo (square) saved to public/avatar.png

Tech setup

  • Remotion 4 project: remotion, @remotion/cli, @remotion/google-fonts, React 18, TypeScript.
  • One composition: HandleReveal, 1920x1080, 60 fps, 360 frames (6.0s).
  • Font: Inter via @remotion/google-fonts/Inter, weights 500/600/700/800, fallback -apple-system, 'Segoe UI', sans-serif.
  • Render: npx remotion render src/index.ts HandleReveal out/handle-reveal.mp4 --codec h264 --crf 16.
  • Colors: ink #0f1419, gray #536471, verified blue #1d9bf0, boil silver #9aa1ab.

Scene

  • Background: radial-gradient(115% 115% at 50% 40%, #ffffff 0%, #f2f4f6 55%, #e6e9ed 100%) (light theme, never dark).
  • Centered X profile hover-card: width 720, padding 44, border-radius 28, background #ffffff, border 1px solid #eef1f3, layered shadow 0 48px 100px -24px rgba(15,20,25,0.32), 0 16px 40px rgba(15,20,25,0.10), 0 2px 8px rgba(15,20,25,0.05) — strong enough that the card separates from the background while the video plays.
  • Card contents (nothing else — no bio, no follower counts):
    • Top row: circular avatar 124px (thin border 1px solid rgba(15,20,25,0.08)) top-left; official X logo SVG (24x24 path, ink color) at 30px top-right.
    • Name row (margin-top 26): DISPLAY_NAME at 48px Inter 800, letter-spacing -0.02em, ink color, with the official X verified-badge SVG (22x22 blue seal + white check path, fill #1d9bf0) at 40px, gap 12. The blue tick sits beside the name and is visible 100% of the time.
    • Handle line (margin-top 8): 40px, line-height 1.35. Starts as @OLD_HANDLE in gray weight 500, ends as @NEW_HANDLE in metallic silver weight 800.

Metallic silver (the hero material)

  • Gradient: linear-gradient(180deg, #dfe2e7 0%, #b6bbc3 30%, #7d848f 55%, #99a0a9 75%, #bfc4ca 100%) with background-clip: text, transparent color. Smooth — deliberately NO hard white "horizon" stripe (it reads as a line through the letters) and NO text-shadow (it smudges).
  • Depth: filter: drop-shadow(0 2px 3px rgba(15,20,25,0.3)) on the silver text.
  • Weight 800 so it reads bold and solid, never washed out.

Timeline (frame numbers at 60 fps)

  1. Entrance (0–45): card fades in (opacity 0→1 over 18), rises 24px and scales 0.95→1 with spring({damping: 200, durationInFrames: 45}). Contents stagger in (avatar delay 6, X logo 10, name 12, handle 16): each fades + rises 12px over 24 frames, Easing.out(Easing.cubic).
  2. Zoom in (88): whole scene scales 1→1.7 with spring({damping: 200, durationInFrames: 60}), transform-origin 41% 60% (the handle area). The full card must stay inside the frame at peak zoom.
  3. Matrix scramble (106): the handle decodes like a Matrix/decoder effect:
    • The "@" never moves; it crossfades gray→silver over frames 106–126.
    • Each character position i joins the "boil" at 106 + i*2: it cycles a new random glyph every 4 frames from charset abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ0123456789, drawn deterministically (Remotion random() seeded by position + step). Boiling glyphs: color #9aa1ab, weight 600, opacity 0.92, blur 0.5px, random vertical jitter ±1.5px per swap.
    • Fixed-width cells prevent wobble: each cell is an inline-block containing an invisible sizer glyph (the old character at weight 500 before its boil starts, the new character at weight 800 after) plus the visible boiling glyph absolutely positioned and centered over it.
    • Old-handle characters beyond the new handle's length boil briefly then dissolve: opacity 0.9→0 starting boilStart + 8 over 9 frames, then unmount.
  4. Locks (134, one per 7 frames): new characters lock in one by one, left to right, at 134 + i*7. Each lock: the final silver glyph appears with spring({damping: 14, stiffness: 180, mass: 0.7}) driving scale 1.16→1 (origin 50% 70%), brightness 1.32→1, blur 0.8px→0.
  5. Letter glint (184–230): a white light band travels across the finished handle: an overlaid copy of @NEW_HANDLE (weight 800) with background-clip: text, gradient linear-gradient(100deg, transparent 42%, rgba(255,255,255,0.95) 50%, transparent 58%), background-size 260% 100%, background-position animated 100%→0% with Easing.inOut(Easing.cubic).
  6. Zoom out (212): second spring (damping 200, 64 frames) subtracts 0.58 of scale — settles at 1.12x, a touch closer than the start.
  7. Card shine sweep (274–332): two skewed (-18deg) vertical bands sweep left→right across the card (inside an overflow-hidden, border-radius-inherit overlay; left goes -70%→180%, eased inOut cubic): a 48%-wide soft slate tint rgba(148,163,184,0.22) plus, offset +11%, a 26%-wide white band rgba(255,255,255,0.9) with mix-blend-mode: overlay so it glints over the avatar, name, tick, and silver letters.
  8. Hold the final frame to 360.

Sound (generated, no downloads)

Write a Node script (scripts/make-sfx.js) that synthesizes a 6.0s 48kHz stereo 16-bit WAV to public/sfx.wav, added to the composition with <Audio src={staticFile('sfx.wav')} />. Use seeded (deterministic) noise, an RBJ biquad bandpass with exponential frequency sweeps, raised-cosine envelopes, exponential-decay sine tones, and equal-power panning. Events (seconds):

  • 0.08: soft air swell, noise 220→520 Hz, gain 0.05.
  • 1.45: rising whoosh with the zoom-in, noise 260→1500 Hz over 1.05s, gain 0.13.
  • 1.78: digital flutter under the boil, noise 2400→3200 Hz, gain 0.032, amplitude-modulated at 15 Hz (matches glyph swaps).
  • Lock ticks at (134 + i*7)/60 for i = 0..6: sine tick at 1250 * 2^(st/12) Hz with st = [0,2,4,7,9,11,14] (rising, musical), decay 0.045, gain 0.085 (last one 0.12), plus a low 290+i*24 Hz thock (gain 0.05) and a 4ms noise click (gain 0.06).
  • 176/60: gentle bell as the last letter lands — 1318.5 Hz + 2.76x harmonic at 0.28, decay 0.55, gain 0.07.
  • 3.54: falling breath with the zoom-out, noise 1200→340 Hz, gain 0.08.
  • 4.6: airy shimmer with the shine sweep, noise 3200→8200 Hz, gain 0.05, panned -0.75→+0.75.
  • Normalize the final mix to 0.45 peak (cap makeup gain at 3x). Keep everything subtle — Apple-quiet, no loud effects.

Quality bar / verification

  • Before the final render, render PNG stills at frames ~118 (boil), ~150 (locks mid-zoom), ~205 (glint), ~278 (shine), 356 (end) with npx remotion still and inspect them: the silver must look bold and metallic (not washed out, no line through it), the whole card must be visible at peak zoom, the tick must sit beside the name in every frame.
  • Verify the MP4 has both streams with npx remotion ffprobe: h264 1920x1080 60fps video + AAC 48kHz stereo audio.
  • Final output: out/handle-reveal.mp4.

The finished video should read: calm white scene → card settles → camera pushes in → the handle boils like decoding text → letters lock into bold silver one by one with rising ticks → light passes over the letters → camera settles back → a shine sweeps the card → hold. Clean, minimal, professional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment