
Create Remotion Geist
Add syntax-highlighted, animated code blocks to Remotion videos without brittle regex highlighting.
Overview
create-remotion-geist is an agent skill for the Build phase that teaches Remotion CodeBlock patterns with prism-react-renderer and frame-based animation.
Install
npx skills add https://github.com/vercel-labs/skill-remotion-geist --skill create-remotion-geistWhat is this skill?
- Uses prism-react-renderer instead of regex-based syntax highlighting
- CodeBlock props: code, language, delay, animate, highlightLines, fontSize
- Fade-in via useCurrentFrame interpolate tied to fps and delay
- Optional typewriter reveal character-by-character over frames
- Geist-styled container classes (background, border, rounded-lg)
- Explicit rule: do not use regex-based syntax highlighting
- CodeBlock exposes 6 primary props including highlightLines and fontSize
Adoption & trust: 370 installs on skills.sh; 24 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need polished code in Remotion videos but regex highlighters break and manual styling does not sync with your timeline.
Who is it for?
Solo builders producing dev marketing or tutorial Remotion videos who want maintainable highlighted code in React.
Skip if: Teams not using Remotion or who only need static screenshots without programmatic video timelines.
When should I use this skill?
Building Remotion scenes that display code and you need prism-react-renderer patterns instead of regex highlighting.
What do I get? / Deliverables
You ship a reusable CodeBlock with prism themes, fade-in, optional typewriter, and line highlights aligned to Remotion frames.
- CodeBlock.tsx component using Highlight and themes from prism-react-renderer
- npm install step for prism-react-renderer
Recommended Skills
Journey fit
How it compares
Prefer this over ad-hoc regex or pasted HTML for in-video code—built for Remotion’s frame model, not generic markdown fences.
Common Questions / FAQ
Who is create-remotion-geist for?
Indie creators and engineers using Remotion to render code-heavy videos with React and prism-react-renderer.
When should I use create-remotion-geist?
During Build when composing Remotion scenes, or at Launch when refreshing promo clips with animated snippets.
Is create-remotion-geist safe to install?
Review the Security Audits panel on this Prism page before trusting it in your repo; it is documentation and component patterns, not a hosted service.
SKILL.md
READMESKILL.md - Create Remotion Geist
# Code Blocks for Remotion Videos **IMPORTANT:** Do NOT use regex-based syntax highlighting - it breaks easily. Use `prism-react-renderer` instead. ## Installation ```bash npm install prism-react-renderer ``` ## CodeBlock Component ```tsx // src/components/CodeBlock.tsx import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion'; import { Highlight, themes } from 'prism-react-renderer'; type CodeBlockProps = { code: string; language?: string; delay?: number; animate?: boolean; highlightLines?: number[]; fontSize?: number; }; export function CodeBlock({ code, language = 'typescript', delay = 0, animate = true, highlightLines = [], fontSize = 16, }: CodeBlockProps) { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); // Fade in animation const opacity = interpolate( frame, [delay * fps, (delay + 0.3) * fps], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } ); // Typewriter effect - reveal characters over time const charsToShow = animate ? Math.floor( interpolate( frame, [(delay + 0.2) * fps, (delay + 0.2) * fps + code.length * 0.5], [0, code.length], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } ) ) : code.length; const displayCode = code.slice(0, charsToShow); return ( <div className="bg-background-200 border border-gray-400 rounded-lg overflow-hidden" style={{ opacity }} > <Highlight theme={geistDarkTheme} code={displayCode} language={language}> {({ style, tokens, getLineProps, getTokenProps }) => ( <pre style={{ ...style, margin: 0, padding: 24, fontSize, lineHeight: 1.6, fontFamily: "'Geist Mono', monospace", backgroundColor: 'transparent', }} > {tokens.map((line, i) => { const isHighlighted = highlightLines.includes(i + 1); return ( <div key={i} {...getLineProps({ line })} style={{ display: 'flex', backgroundColor: isHighlighted ? 'rgba(0, 112, 243, 0.15)' : 'transparent', margin: isHighlighted ? '0 -24px' : 0, padding: isHighlighted ? '0 24px' : 0, }} > <span style={{ color: '#525252', marginRight: 24, minWidth: 24, textAlign: 'right', userSelect: 'none', }} > {i + 1} </span> <span> {line.map((token, key) => ( <span key={key} {...getTokenProps({ token })} /> ))} </span> </div> ); })} </pre> )} </Highlight> </div> ); } // Geist-inspired dark theme for prism-react-renderer const geistDarkTheme = { plain: { color: '#ededed', backgroundColor: '#171717', }, styles: [ { types: ['comment', 'prolog', 'doctype', 'cdata'], style: { color: '#525252', fontStyle: 'italic' as const }, }, { types: ['punctuation'], style: { color: '#737373' }, }, { types: ['property', 'tag', 'boolean', 'number', 'constant', 'symbol'], style: { color: '#0070F3' }, }, { types: ['selector', 'attr-name', 'string', 'char', 'builtin', 'inserted'], style: { color: '#46A758' }, }, { types: ['operator', 'entity', 'url', 'variable'], style: { color: '#ededed' }, }, { types: ['atrule', 'attr-value', 'keyword'], style: { color: '#FF6B8A' }, // Pink for keywords },