Swishy

What can I help animate?

Your AI motion designer for stunning animations and typefaces

2026

Create this asccii animation where it shows as regular text then shows as ascii and has a really interesting flow

Typing Effect

Code editor mockup with realistic typing animation and cursor

App video showcase

Create an animation with portrait videos that look exactly like the image inspo I shared. The videos are auto playing no audio and has a simple animation displaying the cards

Night Street Market

Generate a template that looks like this

Make with Notion

Create the exact animation, create the shapes as well and match every pixel and smoothness of the animation and changes of shapes

Laptop Opening

MacBook-style laptop opening animation with 3D perspective

folder gallery

i want to create an animation where the starting point is: - a blue folder with 3-4 images peeping out a bit, below the folder is name "untitled" - as the cursor travel near the folder, the images peep out even more, displaying almost all the images - once the cursor clicks on the folder the end point: (see image 2) - a macos finder window with all the images neatly laid out for the photos in the folder... you can use any photos right now

Phone Messages

iPhone mockup with animated iMessage conversation bubbles

the Future of design

Create something very similar to this image I shared, where the "future" uses a font like that, and the animation is the future does an ease blur from the left

Bar Chart

Animated bar chart with staggered spring animations for data visualization

Simple Timelapse

Minimalist time display animating between start and end times

Alarm toggle

I want to create an animation of an alarm toggle the animation start where the toggle is off (image 1) and ends when toggle is swiped on (image two in green) canvas should be transparent, i can edit the number of the time later

(Broken .MOV) Pencil Drawing

Animated pencil drawing a bezier curve path on canvas

Upwork Ad

Create this upwork animation

(Broken .MOV) Sticky Notes

Lets do an animation with a bunch of sticky nnotes that fly in and then it shows a logo name called "Sticky"

Logo spin

Add an animation that uses this image and make sure there is an image setting

Logo Reveal

Shape morphing logo reveal with rotation and scale animations

Notifications

Stack of animated notification cards sliding in with spring physics

Time Lapse

Animated clock showing time progression from afternoon to twilight

Website reveal

Create the animation where a website eases and blurs in from the bottom of the page

Audio Visualizer

Music visualizer with animated frequency bars and glow effects

Logo code

Help me create an animation where a user can change the input in realtime for the main word in the inspo photos it is Stagger, and the animation is each letter changes to characters +,-, =,; *, and other characters that you can see in the image I shared then shows the word. IT shuold be a black background and white text

Countdown

Dramatic countdown timer with circular progress indicator

Showcase terminal

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 ); ⏺ Done. The terminal now flips towards the camera by rotating the X axis from 0 to -90 degrees when the output is done. Added a wrapper with perspective and transform-origin at the bottom. ❯ boom! this is awesome! render the video ⏺ Bash(cd /Users/jonathanburger/skills-announcement && npx remotion render SkillsAnnouncement out/video.mp4 2>&1) ⎿ Bundling 6% Bundling 21% Bundling 45% … +257 lines (ctrl+o to expand) ⏺ Rendered to out/video.mp4 (817 kB). ❯ /usage ⏺ I don't have access to your usage statistics directly. The /usage command is a built-in Claude Code CLI command that should display your token usage and costs. If the command didn't produce output, you can also check your usage at https://console.anthropic.com (if using an API key) or through your Claude subscription dashboard. In this session, we've: - Created a Remotion animation with a macOS terminal - Added typewriter animation for the command - Added terminal output with staggered lines - Created a LogoCombo component with Remotion, Claude, and OpenCode logos - Added 3D transforms, spring animations, and a flip transition - Rendered two videos to out/video.mp4

Storytime video

create a video about a dog called winnie

Sentence reveal

I want a simple animation that has words like this that the user can have a single input where the example is just a list of words with new line and the aniamtion is the next word moves down to be bolded almost like a clock movement

Financials

Generate the step by step animation where it first starts blurry then moves to show the finanicial graph slowly moving up as the words behind increases. I want it to look extremely alike to the exact version I shared in the screenshots. take your time to make sure it is working exactly how the screenshot. They should be identical

Image shuffle

So I have a card with 4 images that flips like a cool stack of cards, where it shows the images one after the other. Please add the input cards to the sidebar so we can change the images out. But the animation should be smooth and have a very cool shuffle to it

Github stars

Create an animated version of this github stars where users can input the amount of stars and graph will change based on the amount of stars they want it go, there is a dropdown of different ways the line graph goes that the user can generate. The animation is teh line stars from 0 then makes it way to final star input on the right

Youtube subscribe button

Create an animated youtube button where the mouse hand comes out from the bottom and then clicks the button and the button changes color

Simulation terminated

Technology style animation "Simulation terminated" in green and blue

Comic Style

Slide in text animation with the word "Testing" in purple

Professional AI Animations & Motion Graphics

Create stunning kinetic typography, animated typefaces, and motion graphics with AI. The intelligent alternative to After Effects for modern creators.

10K+
Creators Using Swishy
500K+
AI Animations Created
30sec
Average Generation Time
4.9/5
User Satisfaction

Frequently Asked Questions About AI Animation

Everything you need to know about AI animations, typeface animations, and motion graphics