262588213843476 · Gist

╭─── Claude Code v2.1.12 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ Tips for getting started │ │ Welcome back Jonny! │ Run /init to create a CLAUDE.md file with instructions for Claude │ │ │ │ │ │ ───────────────────────────────────────────────────────────────── │ │ ▐▛███▜▌ │ Recent activity │ │ ▝▜█████▛▘ │ No recent activity │ │ ▘▘ ▝▝ │ │ │ Opus 4.5 · Claude Max · jonny@remotion.dev's │ │ │ Organization │ │ │ ~/skills-announcement │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ❯ we are creating a remotion animation for a new command "npx skills add remotion-dev/remotion". first start out by making a new composition, 1280x1000px of a macos terminal window-like console that has an empty prompt in it. light theme ⏺ I'll start by exploring the existing codebase structure to understand how compositions are set up. ⏺ Search(pattern: "**/*.{tsx,ts}") ⎿ Found 100 files (ctrl+o to expand) ⏺ Search(pattern: "src/**/*.{tsx,ts}") ⎿ Found 3 files (ctrl+o to expand) ⏺ Read(src/Root.tsx) ⎿ Read 19 lines ⏺ Read(src/Composition.tsx) ⎿ Read 4 lines ⏺ Read(src/index.ts) ⎿ Read 5 lines ⏺ Let me check if there's a CSS file to understand the styling setup. ⏺ Search(pattern: "src/**/*.css") ⎿ Found 1 file (ctrl+o to expand) ⏺ Read(src/index.css) ⎿ Read 2 lines ⏺ I'll create a new macOS terminal component and update the composition. Let me create the terminal component. ⏺ Write(src/MacTerminal.tsx) ⎿ Wrote 44 lines to src/MacTerminal.tsx 1 import { AbsoluteFill } from "remotion"; 2 export const MacTerminal: React.FC = () => { 3 return ( 4 <AbsoluteFill className="bg-[#f5f5f5] flex items-center justify-center p-8"> 5 <div 6 className="w-full h-full rounded-xl overflow-hidden flex flex-col" 7 style={{ 8 backgroundColor: "#ffffff", 9 boxShadow: … +34 lines (ctrl+o to expand) ⏺ Now let me update Root.tsx to register the new composition with 1280x1000 dimensions. ⏺ Update(src/Root.tsx) ⎿ Added 5 lines, removed 5 lines 1 import "./index.css"; 2 import { Composition } from "remotion"; 3 -import { MyComposition } from "./Composition"; 3 +import { MacTerminal } from "./MacTerminal"; 4 5 export const RemotionRoot: React.FC = () => { 6 return ( 7 <> 8 <Composition 9 - id="MyComp" 10 - component={MyComposition} 11 - durationInFrames={60} 9 + id="SkillsAnnouncement" 10 + component={MacTerminal} 11 + durationInFrames={300} 12 fps={30} 13 width={1280} 14 - height={720} 14 + height={1000} 15 /> 16 </> 17 ); ⏺ Let me start the Remotion studio to preview the composition. ⏺ Bash(npm run dev 2>&1 &) timeout: 10s ⎿ (No content) ⏺ Bash(sleep 3 && curl -s http://localhost:3000 > /dev/null && echo "Server is running on http://localhost:3000") timeout: 10s ⎿ Server is running on http://localhost:3000 ⏺ The composition is created and the dev server is running. I've created: 1. src/MacTerminal.tsx - A new component that renders a macOS-style terminal window with: - Light gray background (#f5f5f5) - White terminal window with subtle shadow - Title bar with the three traffic light buttons (red, yellow, green) - "Terminal" title in the center - Empty prompt area with ~ $ and a blinking cursor 2. Updated src/Root.tsx - Registered the new composition: - ID: SkillsAnnouncement - Dimensions: 1280x1000px - Duration: 300 frames (10 seconds at 30fps) The Remotion studio is running at http://localhost:3000 where you can preview the terminal. ✻ Brewed for 57s ❯ okay, nice. remove the background and the font size needs to be a lot bigger. ⏺ Update(src/MacTerminal.tsx) ⎿ Added 23 lines, removed 32 lines 2 3 export const MacTerminal: React.FC = () => { 4 return ( 5 - <AbsoluteFill className="bg-[#f5f5f5] flex items-center justify-center p-8"> 6 - <div 7 - className="w-full h-full rounded-xl overflow-hidden flex flex-col" 8 - style={{ 9 - backgroundColor: "#ffffff", 10 - boxShadow: 11 - "0 25px 50px -12px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05)", 12 - }} 13 - > 14 - {/* Title bar */} 15 - <div className="h-12 bg-[#f6f6f6] flex items-center px-4 border-b border-[#e0e0e0]"> 16 - {/* Traffic lights */} 17 - <div className="flex gap-2"> 18 - <div className="w-3 h-3 rounded-full bg-[#ff5f57]" /> 19 - <div className="w-3 h-3 rounded-full bg-[#febc2e]" /> 20 - <div className="w-3 h-3 rounded-full bg-[#28c840]" /> 21 - </div> 22 - {/* Title */} 23 - <div className="flex-1 text-center"> 24 - <span className="text-[#4d4d4d] text-sm font-medium"> 25 - Terminal 26 - </span> 27 - </div> 28 - {/* Spacer for symmetry */} 29 - <div className="w-14" /> 5 + <AbsoluteFill className="flex flex-col"> 6 + {/* Title bar */} 7 + <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 8 + {/* Traffic lights */} 9 + <div className="flex gap-2.5"> 10 + <div className="w-4 h-4 rounded-full bg-[#ff5f57]" /> 11 + <div className="w-4 h-4 rounded-full bg-[#febc2e]" /> 12 + <div className="w-4 h-4 rounded-full bg-[#28c840]" /> 13 </div> 14 + {/* Title */} 15 + <div className="flex-1 text-center"> 16 + <span className="text-[#4d4d4d] text-base font-medium"> 17 + Terminal 18 + </span> 19 + </div> 20 + {/* Spacer for symmetry */} 21 + <div className="w-16" /> 22 + </div> 23 32 - {/* Terminal content */} 33 - <div className="flex-1 bg-white p-4 font-mono text-sm"> 34 - <div className="flex items-center text-[#333]"> 35 - <span className="text-[#2ecc71] font-semibold">~</span> 36 - <span className="text-[#333] mx-1">$</span> 37 - <span className="w-2 h-5 bg-[#333] ml-1 animate-pulse" /> 38 - </div> 24 + {/* Terminal content */} 25 + <div className="flex-1 bg-white p-6 font-mono text-2xl"> 26 + <div className="flex items-center text-[#333]"> 27 + <span className="text-[#2ecc71] font-semibold">~</span> 28 + <span className="text-[#333] mx-2">$</span> 29 + <span className="w-3 h-7 bg-[#333] ml-1" /> 30 </div> 31 </div> 32 </AbsoluteFill> ⏺ Done. I removed the outer gray background so the terminal fills the entire frame, and increased the font size from text-sm to text-2xl. Also made the traffic lights and title bar slightly larger to match. The changes should be visible in the studio. ❯ add some margin nonetheless, but keep it transparent. ⏺ Update(src/MacTerminal.tsx) ⎿ Added 4 lines, removed 3 lines 2 3 export const MacTerminal: React.FC = () => { 4 return ( 5 - <AbsoluteFill className="flex flex-col"> 6 - {/* Title bar */} 7 - <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 5 + <AbsoluteFill className="p-8"> 6 + <div className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl"> 7 + {/* Title bar */} 8 + <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 9 {/* Traffic lights */} 10 <div className="flex gap-2.5"> 11 <div className="w-4 h-4 rounded-full bg-[#ff5f57]" /> ⏺ Read(src/MacTerminal.tsx) ⎿ Read 36 lines ⎿ Found 2 new diagnostic issues in 1 file (ctrl+o to expand) ⏺ I need to fix the closing tag structure. ⏺ Update(src/MacTerminal.tsx) ⎿ Added 7 lines, removed 6 lines 22 <div className="w-16" /> 23 </div> 24 25 - {/* Terminal content */} 26 - <div className="flex-1 bg-white p-6 font-mono text-2xl"> 27 - <div className="flex items-center text-[#333]"> 28 - <span className="text-[#2ecc71] font-semibold">~</span> 29 - <span className="text-[#333] mx-2">$</span> 30 - <span className="w-3 h-7 bg-[#333] ml-1" /> 25 + {/* Terminal content */} 26 + <div className="flex-1 bg-white p-6 font-mono text-2xl"> 27 + <div className="flex items-center text-[#333]"> 28 + <span className="text-[#2ecc71] font-semibold">~</span> 29 + <span className="text-[#333] mx-2">$</span> 30 + <span className="w-3 h-7 bg-[#333] ml-1" /> 31 + </div> 32 </div> 33 </div> 34 </AbsoluteFill> ⏺ Read(src/MacTerminal.tsx) ⎿ Read 37 lines ⏺ The structure is broken. Let me rewrite it properly. ⏺ Write(src/MacTerminal.tsx) ⎿ Added 14 lines, removed 14 lines 6 <div className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl"> 7 {/* Title bar */} 8 <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 9 - {/* Traffic lights */} 10 - <div className="flex gap-2.5"> 11 - <div className="w-4 h-4 rounded-full bg-[#ff5f57]" /> 12 - <div className="w-4 h-4 rounded-full bg-[#febc2e]" /> 13 - <div className="w-4 h-4 rounded-full bg-[#28c840]" /> 9 + {/* Traffic lights */} 10 + <div className="flex gap-2.5"> 11 + <div className="w-4 h-4 rounded-full bg-[#ff5f57]" /> 12 + <div className="w-4 h-4 rounded-full bg-[#febc2e]" /> 13 + <div className="w-4 h-4 rounded-full bg-[#28c840]" /> 14 + </div> 15 + {/* Title */} 16 + <div className="flex-1 text-center"> 17 + <span className="text-[#4d4d4d] text-base font-medium"> 18 + Terminal 19 + </span> 20 + </div> 21 + {/* Spacer for symmetry */} 22 + <div className="w-16" /> 23 </div> 15 - {/* Title */} 16 - <div className="flex-1 text-center"> 17 - <span className="text-[#4d4d4d] text-base font-medium"> 18 - Terminal 19 - </span> 20 - </div> 21 - {/* Spacer for symmetry */} 22 - <div className="w-16" /> 23 - </div> 24 25 {/* Terminal content */} 26 <div className="flex-1 bg-white p-6 font-mono text-2xl"> ⏺ Done. Added p-8 padding around the terminal with a transparent background, and added rounded corners with a shadow to the terminal window itself. ❯ make the terminal content a separate component in a new file. add a typewriter animation to it that types out "npx skills add remotion-dev/skills" ⏺ Write(src/TerminalContent.tsx) ⎿ Wrote 31 lines to src/TerminalContent.tsx 1 import { useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 2 export const TerminalContent: React.FC = () => { 3 const frame = useCurrentFrame(); 4 const { fps } = useVideoConfig(); 5 const command = "npx skills add remotion-dev/skills"; 6 const charsPerSecond = 15; 7 const framesPerChar = fps / charsPerSecond; … +21 lines (ctrl+o to expand) ⏺ Update(src/MacTerminal.tsx) ⎿ Added 2 lines, removed 8 lines 1 import { AbsoluteFill } from "remotion"; 2 +import { TerminalContent } from "./TerminalContent"; 3 4 export const MacTerminal: React.FC = () => { 5 return ( ... 23 <div className="w-16" /> 24 </div> 25 25 - {/* Terminal content */} 26 - <div className="flex-1 bg-white p-6 font-mono text-2xl"> 27 - <div className="flex items-center text-[#333]"> 28 - <span className="text-[#2ecc71] font-semibold">~</span> 29 - <span className="text-[#333] mx-2">$</span> 30 - <span className="w-3 h-7 bg-[#333] ml-1" /> 31 - </div> 32 - </div> 26 + <TerminalContent /> 27 </div> 28 </AbsoluteFill> 29 ); ⏺ Done. Created src/TerminalContent.tsx with a typewriter animation that types out the command at 15 characters per second. The cursor shows while typing and disappears when complete. The MacTerminal now imports and uses this component. ❯ keep the cursor in the end, and refactor it into it's own component in it's own file. keep it blinking while there is no typing. ⏺ Write(src/Cursor.tsx) ⎿ Wrote 23 lines to src/Cursor.tsx 1 import { useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 2 interface CursorProps { 3 blinking: boolean; 4 } 5 export const Cursor: React.FC<CursorProps> = ({ blinking }) => { 6 const frame = useCurrentFrame(); 7 const { fps } = useVideoConfig(); … +13 lines (ctrl+o to expand) ⏺ Update(src/TerminalContent.tsx) ⎿ Added 2 lines, removed 1 line 1 import { useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 2 +import { Cursor } from "./Cursor"; 3 4 export const TerminalContent: React.FC = () => { 5 const frame = useCurrentFrame(); ... 24 <span className="text-[#2ecc71] font-semibold">~</span> 25 <span className="text-[#333] mx-2">$</span> 26 <span>{displayedText}</span> 26 - {isTyping && <span className="w-3 h-7 bg-[#333] ml-0.5" />} 27 + <Cursor blinking={!isTyping} /> 28 </div> 29 </div> 30 ); ⏺ Done. Created src/Cursor.tsx as a separate component that takes a blinking prop. The cursor now stays visible after typing completes and blinks every half second when not typing. ❯ /skills ⎿ Skills dialog dismissed ❯ nice. increase the font size more, and make the composition a bit less smaller. mostly less tall ⏺ Update(src/TerminalContent.tsx) ⎿ Added 1 line, removed 1 line 19 const isTyping = visibleChars < command.length; 20 21 return ( 22 - <div className="flex-1 bg-white p-6 font-mono text-2xl"> 22 + <div className="flex-1 bg-white p-6 font-mono text-4xl"> 23 <div className="flex items-center text-[#333]"> 24 <span className="text-[#2ecc71] font-semibold">~</span> 25 <span className="text-[#333] mx-2">$</span> ⏺ Update(src/Cursor.tsx) ⎿ Added 1 line, removed 1 line 15 16 return ( 17 <span 18 - className="w-3 h-7 bg-[#333] ml-0.5 inline-block" 18 + className="w-4 h-10 bg-[#333] ml-0.5 inline-block" 19 style={{ opacity }} 20 /> 21 ); ⏺ Update(src/Root.tsx) ⎿ Added 2 lines, removed 2 lines 10 component={MacTerminal} 11 durationInFrames={300} 12 fps={30} 13 - width={1280} 14 - height={1000} 13 + width={1080} 14 + height={400} 15 /> 16 </> 17 ); ⏺ Done. Increased font size to text-4xl, made the cursor larger to match, and changed the composition to 1080x400. ❯ make the composition is a bit taller nonetheless ⏺ Update(src/Root.tsx) ⎿ Added 1 line, removed 1 line 11 durationInFrames={300} 12 fps={30} 13 width={1080} 14 - height={400} 14 + height={500} 15 /> 16 </> 17 ); ⏺ Done. Changed the height to 500px. ❯ height of 700 ⏺ Update(src/Root.tsx) ⎿ Added 1 line, removed 1 line 11 durationInFrames={300} 12 fps={30} 13 width={1080} 14 - height={500} 14 + height={700} 15 /> 16 </> 17 ); ⏺ Done. ❯ ok, make a new master composition and and the current composition as a sequence. give the master composition a grayish background ⏺ Write(src/Master.tsx) ⎿ Wrote 15 lines to src/Master.tsx 1 import { AbsoluteFill, Series } from "remotion"; 2 import { MacTerminal } from "./MacTerminal"; 3 export const Master: React.FC = () => { 4 return ( 5 <AbsoluteFill className="bg-[#e5e5e5]"> 6 <Series> 7 <Series.Sequence durationInFrames={300}> 8 <MacTerminal /> 9 </Series.Sequence> … +5 lines (ctrl+o to expand) ⏺ Update(src/Root.tsx) ⎿ Added 2 lines, removed 2 lines 1 import "./index.css"; 2 import { Composition } from "remotion"; 3 -import { MacTerminal } from "./MacTerminal"; 3 +import { Master } from "./Master"; 4 5 export const RemotionRoot: React.FC = () => { 6 return ( 7 <> 8 <Composition 9 id="SkillsAnnouncement" 10 - component={MacTerminal} 10 + component={Master} 11 durationInFrames={300} 12 fps={30} 13 width={1080} ⏺ Done. Created src/Master.tsx with a grayish background (#e5e5e5) that contains MacTerminal as a sequence. Root.tsx now uses the Master composition. ❯ use a sequence, not a series ⏺ Update(src/Master.tsx) ⎿ Added 4 lines, removed 6 lines 1 -import { AbsoluteFill, Series } from "remotion"; 1 +import { AbsoluteFill, Sequence } from "remotion"; 2 import { MacTerminal } from "./MacTerminal"; 3 4 export const Master: React.FC = () => { 5 return ( 6 <AbsoluteFill className="bg-[#e5e5e5]"> 7 - <Series> 8 - <Series.Sequence durationInFrames={300}> 9 - <MacTerminal /> 10 - </Series.Sequence> 11 - </Series> 7 + <Sequence from={0} durationInFrames={300}> 8 + <MacTerminal /> 9 + </Sequence> 10 </AbsoluteFill> 11 ); 12 }; ⏺ Done. Changed to use Sequence instead of Series. ❯ add a 3d rotation to the temrinal. like 20 degree of x and y rotation. ⎿ Found 1 new diagnostic issue in 1 file (ctrl+o to expand) ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 4 export const Master: React.FC = () => { 5 return ( 6 <AbsoluteFill className="bg-[#e5e5e5]"> 7 - <Sequence from={0} durationInFrames={300}> 7 + <Sequence durationInFrames={300}> 8 <MacTerminal /> 9 </Sequence> 10 </AbsoluteFill> ⏺ Read(src/MacTerminal.tsx) ⎿ Read 31 lines ⏺ Update(src/MacTerminal.tsx) ⎿ Added 8 lines, removed 2 lines 3 4 export const MacTerminal: React.FC = () => { 5 return ( 6 - <AbsoluteFill className="p-8"> 7 - <div className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl"> 6 + <AbsoluteFill 7 + className="p-8 flex items-center justify-center" 8 + style={{ perspective: 1000 }} 9 + > 10 + <div 11 + className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl" 12 + style={{ transform: "rotateX(20deg) rotateY(-20deg)" }} 13 + > 14 {/* Title bar */} 15 <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 16 {/* Traffic lights */} ⏺ Done. Added 3D rotation with rotateX(20deg) and rotateY(-20deg) to the terminal, with a perspective of 1000 on the parent. ❯ add the transform to the sequence, not the terminal itself ⏺ Update(src/MacTerminal.tsx) ⎿ Added 2 lines, removed 8 lines 3 4 export const MacTerminal: React.FC = () => { 5 return ( 6 - <AbsoluteFill 7 - className="p-8 flex items-center justify-center" 8 - style={{ perspective: 1000 }} 9 - > 10 - <div 11 - className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl" 12 - style={{ transform: "rotateX(20deg) rotateY(-20deg)" }} 13 - > 6 + <AbsoluteFill className="p-8"> 7 + <div className="w-full h-full flex flex-col rounded-xl overflow-hidden shadow-2xl"> 8 {/* Title bar */} 9 <div className="h-14 bg-[#f6f6f6] flex items-center px-5 border-b border-[#e0e0e0]"> 10 {/* Traffic lights */} ⏺ Update(src/Master.tsx) ⎿ Added 5 lines, removed 2 lines 3 4 export const Master: React.FC = () => { 5 return ( 6 - <AbsoluteFill className="bg-[#e5e5e5]"> 7 - <Sequence durationInFrames={300}> 6 + <AbsoluteFill className="bg-[#e5e5e5]" style={{ perspective: 1000 }}> 7 + <Sequence 8 + durationInFrames={300} 9 + style={{ transform: "rotateX(20deg) rotateY(-20deg)" }} 10 + > 11 <MacTerminal /> 12 </Sequence> 13 </AbsoluteFill> ⏺ Done. Moved the 3D transform to the Sequence in Master.tsx and reverted MacTerminal.tsx. ❯ okay, over total length of the composition, slowly rotate Y axis from 20 to -20 degrees ⏺ Update(src/Master.tsx) ⎿ Added 7 lines, removed 2 lines 1 -import { AbsoluteFill, Sequence } from "remotion"; 1 +import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 2 import { MacTerminal } from "./MacTerminal"; 3 4 export const Master: React.FC = () => { 5 + const frame = useCurrentFrame(); 6 + const { durationInFrames } = useVideoConfig(); 7 + 8 + const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 9 + 10 return ( 11 <AbsoluteFill className="bg-[#e5e5e5]" style={{ perspective: 1000 }}> 12 <Sequence 13 durationInFrames={300} 9 - style={{ transform: "rotateX(20deg) rotateY(-20deg)" }} 14 + style={{ transform: `rotateX(20deg) rotateY(${rotateY}deg)` }} 15 > 16 <MacTerminal /> 17 </Sequence> ⏺ Done. The Y rotation now animates from 20 to -20 degrees over the full 300 frames. ❯ run the command "npx skills install remotion-dev/skills" yourself. look at the output and add the beginning of the output as terminal content ⏺ Bash(npx skills install remotion-dev/skills 2>&1) timeout: 1m 0s ⎿ Error: Exit code 1 ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝ ███████╗█████╔╝ ██║██║ ██║ ███████╗ ╚════██║██╔═██╗ ██║██║ ██║ ╚════██║ ███████║██║ ██╗██║███████╗███████╗███████║ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝ … +17 lines (ctrl+o to see all) ⏺ I see the output. It shows an ASCII art "SKILLS" logo and installation progress. Let me update the TerminalContent to show this output after the command is typed. ⏺ Read(src/TerminalContent.tsx) ⎿ Read 32 lines ⏺ Update(src/TerminalContent.tsx) ⎿ Added 32 lines, removed 3 lines 1 import { useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 2 import { Cursor } from "./Cursor"; 3 4 +const SKILLS_LOGO = `███████╗██╗ ██╗██╗██╗ ██╗ ███████╗ 5 +██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝ 6 +███████╗█████╔╝ ██║██║ ██║ ███████╗ 7 +╚════██║██╔═██╗ ██║██║ ██║ ╚════██║ 8 +███████║██║ ██╗██║███████╗███████╗███████║ 9 +╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝`; 10 + 11 +const OUTPUT_LINES = [ 12 + "", 13 + "┌ skills", 14 + "│", 15 + "◇ Source: https://github.com/remotion-dev/skills.git", 16 +]; 17 + 18 export const TerminalContent: React.FC = () => { 19 const frame = useCurrentFrame(); 20 const { fps } = useVideoConfig(); ... 23 const charsPerSecond = 15; 24 const framesPerChar = fps / charsPerSecond; 25 26 + const typingEndFrame = command.length * framesPerChar; 27 + const outputStartFrame = typingEndFrame + fps * 0.5; // 0.5s delay after typing 28 + 29 const visibleChars = Math.floor( 13 - interpolate(frame, [0, command.length * framesPerChar], [0, command.length], { 30 + interpolate(frame, [0, typingEndFrame], [0, command.length], { 31 extrapolateRight: "clamp", 32 }) 33 ); 34 35 const displayedText = command.slice(0, visibleChars); 36 const isTyping = visibleChars < command.length; 37 + const showOutput = frame >= outputStartFrame; 38 39 return ( 22 - <div className="flex-1 bg-white p-6 font-mono text-4xl"> 40 + <div className="flex-1 bg-white p-6 font-mono text-4xl overflow-hidden"> 41 <div className="flex items-center text-[#333]"> 42 <span className="text-[#2ecc71] font-semibold">~</span> 43 <span className="text-[#333] mx-2">$</span> 44 <span>{displayedText}</span> 27 - <Cursor blinking={!isTyping} /> 45 + {!showOutput && <Cursor blinking={!isTyping} />} 46 </div> 47 + 48 + {showOutput && ( 49 + <div className="mt-4 text-[#666] text-lg leading-tight"> 50 + <pre className="text-[#333]">{SKILLS_LOGO}</pre> 51 + {OUTPUT_LINES.map((line, i) => ( 52 + <div key={i} className="text-[#333]"> 53 + {line} 54 + </div> 55 + ))} 56 + </div> 57 + )} 58 </div> 59 ); 60 }; ⏺ Done. After the command is typed, there's a 0.5 second delay, then the SKILLS ASCII art logo and the beginning of the installation output appear. ✻ Worked for 34s ❯ can you add a bit more of the content? ⏺ Update(src/TerminalContent.tsx) ⎿ Added 12 lines 13 "┌ skills", 14 "│", 15 "◇ Source: https://github.com/remotion-dev/skills.git", 16 + "│", 17 + "◇ Repository cloned", 18 + "│", 19 + "◇ Found 1 skill", 20 + "│", 21 + "● Skill: remotion-best-practices", 22 + "│", 23 + "│ Best practices for Remotion - Video creation in React", 24 + "│", 25 + "◇ Detected 2 agents", 26 + "│", 27 + "└ Installation complete", 28 ]; 29 30 export const TerminalContent: React.FC = () => { ⏺ Done. Added more output lines including the repository cloning, skill detection, and installation complete messages. ❯ stagger the lines, make one appear every 50ms ⏺ Update(src/TerminalContent.tsx) ⎿ Added 13 lines, removed 1 line 47 const displayedText = command.slice(0, visibleChars); 48 const isTyping = visibleChars < command.length; 49 const showOutput = frame >= outputStartFrame; 50 + const framesPerLine = fps * 0.05; // 50ms per line 51 + const logoFrame = outputStartFrame; 52 + const linesStartFrame = logoFrame + framesPerLine; 53 54 + const visibleLines = Math.floor( 55 + interpolate( 56 + frame, 57 + [linesStartFrame, linesStartFrame + OUTPUT_LINES.length * framesPerLine], 58 + [0, OUTPUT_LINES.length], 59 + { extrapolateLeft: "clamp", extrapolateRight: "clamp" } 60 + ) 61 + ); 62 + 63 return ( 64 <div className="flex-1 bg-white p-6 font-mono text-4xl overflow-hidden"> 65 <div className="flex items-center text-[#333]"> ... 72 {showOutput && ( 73 <div className="mt-4 text-[#666] text-lg leading-tight"> 74 <pre className="text-[#333]">{SKILLS_LOGO}</pre> 63 - {OUTPUT_LINES.map((line, i) => ( 75 + {OUTPUT_LINES.slice(0, visibleLines).map((line, i) => ( 76 <div key={i} className="text-[#333]"> 77 {line} 78 </div> ⏺ Done. Each output line now appears 50ms after the previous one. ❯ in the master composition, make the terminal jump in from the bottom using a fast spring animation, but no bounce ⏺ Update(src/Master.tsx) ⎿ Added 15 lines, removed 3 lines 1 -import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate } from "remotion"; 1 +import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion"; 2 import { MacTerminal } from "./MacTerminal"; 3 4 export const Master: React.FC = () => { 5 const frame = useCurrentFrame(); 6 - const { durationInFrames } = useVideoConfig(); 6 + const { durationInFrames, fps } = useVideoConfig(); 7 8 + const slideIn = spring({ 9 + frame, 10 + fps, 11 + config: { 12 + damping: 200, 13 + stiffness: 100, 14 + }, 15 + }); 16 + 17 + const translateY = interpolate(slideIn, [0, 1], [700, 0]); 18 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 19 20 return ( 21 <AbsoluteFill className="bg-[#e5e5e5]" style={{ perspective: 1000 }}> 22 <Sequence 23 durationInFrames={300} 14 - style={{ transform: `rotateX(20deg) rotateY(${rotateY}deg)` }} 24 + style={{ 25 + transform: `translateY(${translateY}px) rotateX(20deg) rotateY(${rotateY}deg)`, 26 + }} 27 > 28 <MacTerminal /> 29 </Sequence> ⏺ Done. Added a spring animation with high damping (200) to prevent bounce. The terminal slides up from the bottom of the frame. ❯ render it ⏺ Bash(npx remotion render SkillsAnnouncement out/video.mp4 2>&1) ⎿ Downloading Chrome Headless Shell https://www.remotion.dev/chrome-headless-shell Getting Headless Shell - 9.5 Mb/85.4 Mb Getting Headless Shell - 19.1 Mb/85.4 Mb … +329 lines (ctrl+o to expand) ⏺ Rendered to out/video.mp4 (2.6 MB). ❯ make a new composition and add it to Root.tsx. it should display the remotion logo as an image (Without title (light mode) from https://remotion.dev/brand) as well as a "+" as well as a claude code logo and opencode logo ⏺ Fetch(https://remotion.dev/brand) ⎿ Received 431 bytes (307 Temporary Redirect) ⏺ Fetch(https://github.com/remotion-dev/logo) ⎿ Received 304.8KB (200 OK) ⏺ Web Search("Claude Code logo PNG SVG Anthropic") ⎿ Did 1 search in 15s ⏺ Web Search("OpenCode logo AI coding assistant") ⎿ Did 1 search in 17s ⏺ Fetch(https://github.com/sst/opencode) ⎿ Received 351.8KB (200 OK) ⏺ Fetch(https://github.com/anthropics/claude-code) ⎿ Received 293.5KB (200 OK) ⏺ Fetch(https://commons.wikimedia.org/wiki/File:Claude_AI_logo.svg) ⎿ Error: Request failed with status code 403 ⏺ Fetch(https://uxwing.com/claude-ai-icon/) ⎿ Received 69.6KB (200 OK) ⏺ Let me download the logos and create the component. ⏺ Bash(mkdir -p /Users/jonathanburger/skills-announcement/public && ls /Users/jonathanburger/skills-announcement/public) ⎿ (No content) ⏺ Bash(cd /Users/jonathanburger/skills-announcement/public && curl -sL timeout: "https://github.com/remotion-dev/brand/raw/main/withouttitle/element-0.png" -o remotion-logo.png…) 30s ⎿ total 80 drwxr-xr-x@ 5 jonathanburger staff 160 Jan 20 15:31 . drwxrwxr-x@ 17 jonathanburger staff 544 Jan 20 15:28 .. … +3 lines (ctrl+o to expand) ⏺ Write(src/LogoCombo.tsx) ⎿ Wrote 28 lines to src/LogoCombo.tsx 1 import { AbsoluteFill, Img, staticFile } from "remotion"; 2 export const LogoCombo: React.FC = () => { 3 return ( 4 <AbsoluteFill className="bg-white flex items-center justify-center"> 5 <div className="flex items-center gap-12"> 6 <Img 7 src={staticFile("remotion-logo.png")} 8 className="h-32" 9 alt="Remotion" … +18 lines (ctrl+o to expand) ⏺ Read(src/Root.tsx) ⎿ Read 19 lines ⏺ Update(src/Root.tsx) ⎿ Added 9 lines 1 import "./index.css"; 2 import { Composition } from "remotion"; 3 import { Master } from "./Master"; 4 +import { LogoCombo } from "./LogoCombo"; 5 6 export const RemotionRoot: React.FC = () => { 7 return ( ... 14 width={1080} 15 height={700} 16 /> 17 + <Composition 18 + id="LogoCombo" 19 + component={LogoCombo} 20 + durationInFrames={90} 21 + fps={30} 22 + width={1080} 23 + height={400} 24 + /> 25 </> 26 ); 27 }; ⏺ Done. Created src/LogoCombo.tsx with the three logos separated by "+" signs and added it to Root.tsx as a new composition called "LogoCombo" (1080x400, 3 seconds at 30fps). The logos are downloaded to the public/ folder: - remotion-logo.png - from Remotion brand assets - claude-logo.svg - from UXWing - opencode-logo.svg - from OpenCode GitHub You can preview it in the studio by selecting the "LogoCombo" composition. ✻ Baked for 1m 33s ❯ okay nice. remove the second plus and make the opencode combo quite a bit smaller. ⏺ Update(src/LogoCombo.tsx) ⎿ Added 1 line, removed 2 lines 15 className="h-32" 16 alt="Claude Code" 17 /> 18 - <span className="text-6xl font-light text-gray-400">+</span> 18 <Img 19 src={staticFile("opencode-logo.svg")} 21 - className="h-32" 20 + className="h-16" 21 alt="OpenCode" 22 /> 23 </div> ⏺ Done. Removed the second "+" and reduced the OpenCode logo from h-32 to h-16. ❯ remove the background from this composition, and make the claude code logo also considerably smaller ⏺ Update(src/LogoCombo.tsx) ⎿ Added 1 line, removed 1 line 2 3 export const LogoCombo: React.FC = () => { 4 return ( 5 - <AbsoluteFill className="bg-white flex items-center justify-center"> 5 + <AbsoluteFill className="flex items-center justify-center"> 6 <div className="flex items-center gap-12"> 7 <Img 8 src={staticFile("remotion-logo.png")} ⏺ Update(src/LogoCombo.tsx) ⎿ Added 1 line, removed 1 line 12 <span className="text-6xl font-light text-gray-400">+</span> 13 <Img 14 src={staticFile("claude-logo.svg")} 15 - className="h-32" 15 + className="h-16" 16 alt="Claude Code" 17 /> 18 <Img ⏺ Done. Removed the white background and reduced the Claude logo to h-16. ❯ make the claude code a bit bigger ⏺ Update(src/LogoCombo.tsx) ⎿ Added 1 line, removed 1 line 12 <span className="text-6xl font-light text-gray-400">+</span> 13 <Img 14 src={staticFile("claude-logo.svg")} 15 - className="h-16" 15 + className="h-24" 16 alt="Claude Code" 17 /> 18 <Img ⏺ Done. Increased Claude logo to h-24. ❯ the plus should be a bit darker ⏺ Update(src/LogoCombo.tsx) ⎿ Added 1 line, removed 1 line 9 className="h-32" 10 alt="Remotion" 11 /> 12 - <span className="text-6xl font-light text-gray-400">+</span> 12 + <span className="text-6xl font-light text-gray-600">+</span> 13 <Img 14 src={staticFile("claude-logo.svg")} 15 className="h-24" ⏺ Done. Changed the plus to text-gray-600. ❯ add this composition to the master composition as a sequence coming in after the terminal output is done. the logocombo should be behind the terminal. push the terminal down again when it is done with the output ⏺ Read(src/Master.tsx) ⎿ Read 33 lines ⏺ Read(src/TerminalContent.tsx) ⎿ Read 85 lines ⏺ Update(src/Master.tsx) ⎿ Added 24 lines, removed 1 line 1 import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion"; 2 import { MacTerminal } from "./MacTerminal"; 3 +import { LogoCombo } from "./LogoCombo"; 4 5 +const OUTPUT_DONE_FRAME = 120; 6 + 7 export const Master: React.FC = () => { 8 const frame = useCurrentFrame(); 9 const { durationInFrames, fps } = useVideoConfig(); ... 17 }, 18 }); 19 17 - const translateY = interpolate(slideIn, [0, 1], [700, 0]); 20 + const slideOut = spring({ 21 + frame: frame - OUTPUT_DONE_FRAME, 22 + fps, 23 + config: { 24 + damping: 200, 25 + stiffness: 100, 26 + }, 27 + }); 28 + 29 + const translateYIn = interpolate(slideIn, [0, 1], [700, 0]); 30 + const translateYOut = frame >= OUTPUT_DONE_FRAME 31 + ? interpolate(slideOut, [0, 1], [0, 700]) 32 + : 0; 33 + const translateY = translateYIn + translateYOut; 34 + 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 37 return ( 38 <AbsoluteFill className="bg-[#e5e5e5]" style={{ perspective: 1000 }}> 39 + {/* LogoCombo behind the terminal */} 40 + <Sequence from={OUTPUT_DONE_FRAME} durationInFrames={300 - OUTPUT_DONE_FRAME}> 41 + <LogoCombo /> 42 + </Sequence> 43 + 44 + {/* Terminal on top */} 45 <Sequence 46 durationInFrames={300} 47 style={{ ⏺ Done. Added LogoCombo behind the terminal (appears at frame 120) and the terminal slides down with another spring animation when the output is done. ❯ make the background of the master composition the color #FFF ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 37 return ( 38 - <AbsoluteFill className="bg-[#e5e5e5]" style={{ perspective: 1000 }}> 38 + <AbsoluteFill className="bg-[#FFF]" style={{ perspective: 1000 }}> 39 {/* LogoCombo behind the terminal */} 40 <Sequence from={OUTPUT_DONE_FRAME} durationInFrames={300 - OUTPUT_DONE_FRAME}> 41 <LogoCombo /> ⏺ Done. ❯ make it the color #f8fafc ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 37 return ( 38 - <AbsoluteFill className="bg-[#FFF]" style={{ perspective: 1000 }}> 38 + <AbsoluteFill className="bg-[#f8fafc]" style={{ perspective: 1000 }}> 39 {/* LogoCombo behind the terminal */} 40 <Sequence from={OUTPUT_DONE_FRAME} durationInFrames={300 - OUTPUT_DONE_FRAME}> 41 <LogoCombo /> ⏺ Done. ❯ the logomark should actually be a series of 2 sequences. first, for 2 seconds show text "Agent Skills now available" in GT Planar font, font size 80, medium weight, only then show the logo ⏺ Read(src/LogoCombo.tsx) ⎿ Read 27 lines ⏺ Update(src/LogoCombo.tsx) ⎿ Added 32 lines, removed 2 lines 1 -import { AbsoluteFill, Img, staticFile } from "remotion"; 1 +import { AbsoluteFill, Img, staticFile, Series } from "remotion"; 2 3 -export const LogoCombo: React.FC = () => { 3 +const AnnouncementText: React.FC = () => { 4 return ( 5 <AbsoluteFill className="flex items-center justify-center"> 6 + <span 7 + style={{ 8 + fontFamily: "GT Planar, sans-serif", 9 + fontSize: 80, 10 + fontWeight: 500, 11 + color: "#333", 12 + }} 13 + > 14 + Agent Skills now available 15 + </span> 16 + </AbsoluteFill> 17 + ); 18 +}; 19 + 20 +const Logos: React.FC = () => { 21 + return ( 22 + <AbsoluteFill className="flex items-center justify-center"> 23 <div className="flex items-center gap-12"> 24 <Img 25 src={staticFile("remotion-logo.png")} ... 41 </AbsoluteFill> 42 ); 43 }; 44 + 45 +export const LogoCombo: React.FC = () => { 46 + return ( 47 + <Series> 48 + <Series.Sequence durationInFrames={60}> 49 + <AnnouncementText /> 50 + </Series.Sequence> 51 + <Series.Sequence durationInFrames={120}> 52 + <Logos /> 53 + </Series.Sequence> 54 + </Series> 55 + ); 56 +}; ⏺ Done. Updated LogoCombo to use a Series with: 1. First sequence (2 seconds): "Agent Skills now available" text in GT Planar font, size 80, medium weight 2. Second sequence: the logos Note: GT Planar font needs to be loaded for it to display correctly. Do you have the font file to add, or should we load it from a different source? ❯ make the font only 60px but bolder ⏺ Update(src/LogoCombo.tsx) ⎿ Added 2 lines, removed 2 lines 6 <span 7 style={{ 8 fontFamily: "GT Planar, sans-serif", 9 - fontSize: 80, 10 - fontWeight: 500, 9 + fontSize: 60, 10 + fontWeight: 700, 11 color: "#333", 12 }} 13 > ⏺ Done. Changed to 60px and font-weight 700. ❯ add a scale animation to the text, use an easing out curve and it half a second long ⏺ Update(src/LogoCombo.tsx) ⎿ Added 10 lines, removed 1 line 1 -import { AbsoluteFill, Img, staticFile, Series } from "remotion"; 1 +import { AbsoluteFill, Img, staticFile, Series, useCurrentFrame, useVideoConfig, interpolate, Easing } from "remotion"; 2 3 const AnnouncementText: React.FC = () => { 4 + const frame = useCurrentFrame(); 5 + const { fps } = useVideoConfig(); 6 + 7 + const scale = interpolate(frame, [0, fps * 0.5], [0, 1], { 8 + extrapolateRight: "clamp", 9 + easing: Easing.out(Easing.cubic), 10 + }); 11 + 12 return ( 13 <AbsoluteFill className="flex items-center justify-center"> 14 <span ... 17 fontSize: 60, 18 fontWeight: 700, 19 color: "#333", 20 + transform: `scale(${scale})`, 21 }} 22 > 23 Agent Skills now available ⏺ Done. Added a scale animation from 0 to 1 over half a second with an ease-out cubic curve. ❯ nice! almost done. - make the composition only 8 seconds long. - make the sequence holding the terminal a bit bigger using a scale transform. increase the scale transform very slightly over time ⏺ Update(src/Root.tsx) ⎿ Added 1 line, removed 1 line 9 <Composition 10 id="SkillsAnnouncement" 11 component={Master} 12 - durationInFrames={300} 12 + durationInFrames={240} 13 fps={30} 14 width={1080} 15 height={700} ⏺ Read(src/Master.tsx) ⎿ Read 56 lines ⏺ Update(src/Master.tsx) ⎿ Added 4 lines, removed 3 lines 33 const translateY = translateYIn + translateYOut; 34 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 + const scale = interpolate(frame, [0, durationInFrames], [1.1, 1.15]); 37 38 return ( 39 <AbsoluteFill className="bg-[#f8fafc]" style={{ perspective: 1000 }}> 40 {/* LogoCombo behind the terminal */} 40 - <Sequence from={OUTPUT_DONE_FRAME} durationInFrames={300 - OUTPUT_DONE_FRAME}> 41 + <Sequence from={OUTPUT_DONE_FRAME} durationInFrames={durationInFrames - OUTPUT_DONE_FRAME}> 42 <LogoCombo /> 43 </Sequence> 44 45 {/* Terminal on top */} 46 <Sequence 46 - durationInFrames={300} 47 + durationInFrames={durationInFrames} 48 style={{ 48 - transform: `translateY(${translateY}px) rotateX(20deg) rotateY(${rotateY}deg)`, 49 + transform: `translateY(${translateY}px) rotateX(20deg) rotateY(${rotateY}deg) scale(${scale})`, 50 }} 51 > 52 <MacTerminal /> ⏺ Done. Changed the composition to 8 seconds (240 frames) and added a scale transform to the terminal that goes from 1.1 to 1.15 over time. ❯ make the scale transform a bit 0.05 less ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 33 const translateY = translateYIn + translateYOut; 34 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 - const scale = interpolate(frame, [0, durationInFrames], [1.1, 1.15]); 36 + const scale = interpolate(frame, [0, durationInFrames], [1.05, 1.1]); 37 38 return ( 39 <AbsoluteFill className="bg-[#f8fafc]" style={{ perspective: 1000 }}> ⏺ Done. Scale now goes from 1.05 to 1.1. ❯ actually, we should decrease the scale more, to only 0.9 and it goes to 1 but we need to position the terminal 100px lower overall for it to look nice ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 33 const translateY = translateYIn + translateYOut; 34 35 const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 36 - const scale = interpolate(frame, [0, durationInFrames], [1.05, 1.1]); 36 + const scale = interpolate(frame, [0, durationInFrames], [0.9, 1]); 37 38 return ( 39 <AbsoluteFill className="bg-[#f8fafc]" style={{ perspective: 1000 }}> ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 26 }, 27 }); 28 29 - const translateYIn = interpolate(slideIn, [0, 1], [700, 0]); 29 + const translateYIn = interpolate(slideIn, [0, 1], [700, 100]); 30 const translateYOut = frame >= OUTPUT_DONE_FRAME 31 ? interpolate(slideOut, [0, 1], [0, 700]) 32 : 0; ⏺ Done. Scale now goes from 0.9 to 1, and the terminal rests 100px lower. ❯ the -20 to 20 degree rotation is a bit much. let's only do 10 to -10 ⏺ Update(src/Master.tsx) ⎿ Added 1 line, removed 1 line 32 : 0; 33 const translateY = translateYIn + translateYOut; 34 35 - const rotateY = interpolate(frame, [0, durationInFrames], [20, -20]); 35 + const rotateY = interpolate(frame, [0, durationInFrames], [10, -10]); 36 const scale = interpolate(frame, [0, durationInFrames], [0.9, 1]); 37 38 return ( ⏺ Done. Rotation now goes from 10 to -10 degrees. ❯ ok, new idea! instead of pushing the terminal down, flip the terminal towards the camera by rotating the X axis. this might need a perspective on the parent and the transform origin needs to be at the bottom. maybe wrap it it another sequence to make it easier ⏺ Read(src/Master.tsx) ⎿ Read 57 lines ⏺ Update(src/Master.tsx) ⎿ Added 25 lines, removed 8 lines 17 }, 18 }); 19 20 - const slideOut = spring({ 20 + const flipOut = spring({ 21 frame: frame - OUTPUT_DONE_FRAME, 22 fps, 23 config: { ... 26 }, 27 }); 28 29 - const translateYIn = interpolate(slideIn, [0, 1], [700, 100]); 30 - const translateYOut = frame >= OUTPUT_DONE_FRAME 31 - ? interpolate(slideOut, [0, 1], [0, 700]) 32 - : 0; 33 - const translateY = translateYIn + translateYOut; 34 - 29 + const translateY = interpolate(slideIn, [0, 1], [700, 100]); 30 const rotateY = interpolate(frame, [0, durationInFrames], [10, -10]); 31 const scale = interpolate(frame, [0, durationInFrames], [0.9, 1]); 32 33 + const flipRotateX = frame >= OUTPUT_DONE_FRAME 34 + ? interpolate(flipOut, [0, 1], [0, -90]) 35 + : 0; 36 + 37 return ( 38 <AbsoluteFill className="bg-[#f8fafc]" style={{ perspective: 1000 }}> 39 {/* LogoCombo behind the terminal */} ... 48 transform: `translateY(${translateY}px) rotateX(20deg) rotateY(${rotateY}deg) scale(${scale})`, 49 }} 50 > 52 - <MacTerminal /> 51 + {/* Flip wrapper with transform origin at bottom */} 52 + <div 53 + style={{ 54 + width: "100%", 55 + height: "100%", 56 + perspective: 1000, 57 + }} 58 + > 59 + <div 60 + style={{ 61 + width: "100%", 62 + height: "100%", 63 + transformOrigin: "center bottom", 64 + transform: `rotateX(${flipRotateX}deg)`, 65 + }} 66 + > 67 + <MacTerminal /> 68 + </div> 69 + </div> 70 </Sequence> 71 </AbsoluteFill> 72 );

Read the original on gist.github.com ↗