Skip to content

Commit 3601add

Browse files
authored
Create promo video using remotion (#25)
2 parents 29f7eb7 + 4ffbd03 commit 3601add

13 files changed

Lines changed: 3319 additions & 48 deletions

File tree

.changeset/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"access": "public",
88
"baseBranch": "main",
99
"updateInternalDependencies": "patch",
10-
"ignore": ["agentcrumbs-docs"]
10+
"ignore": ["agentcrumbs-docs", "papertrail", "agentcrumbs-sizzle-reel"]
1111
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ dist
66
.env
77
.env.*
88
.claude/
9+
out/

examples/sizzle-reel/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "agentcrumbs-sizzle-reel",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"studio": "remotion studio",
7+
"render": "remotion render AgentCrumbsDemo out/agentcrumbs-demo.mp4",
8+
"render:gif": "remotion render AgentCrumbsDemo out/agentcrumbs-demo.gif"
9+
},
10+
"dependencies": {
11+
"@remotion/cli": "4.0.434",
12+
"react": "^19.0.0",
13+
"react-dom": "^19.0.0",
14+
"remotion": "4.0.434"
15+
},
16+
"devDependencies": {
17+
"@remotion/eslint-config": "4.0.434",
18+
"@types/react": "^19.0.0",
19+
"typescript": "^5.7.0"
20+
}
21+
}

examples/sizzle-reel/src/AgentCrumbsDemo.tsx

Lines changed: 494 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import type React from "react";
2+
import { theme, fonts } from "./theme";
3+
4+
type ClaudeCodeShellProps = {
5+
children: React.ReactNode;
6+
scrollY?: number;
7+
inputText?: string;
8+
showInput?: boolean;
9+
frame?: number;
10+
};
11+
12+
export const ClaudeCodeShell: React.FC<ClaudeCodeShellProps> = ({
13+
children,
14+
scrollY = 0,
15+
inputText = "",
16+
showInput = false,
17+
frame = 0,
18+
}) => {
19+
// Cost ticks up over time
20+
const cost = (0.0001 + frame * 0.000008).toFixed(4);
21+
return (
22+
<div
23+
style={{
24+
width: "100%",
25+
height: "100%",
26+
backgroundColor: theme.termBg,
27+
fontFamily: fonts.mono,
28+
fontSize: 18,
29+
lineHeight: 1.55,
30+
color: theme.fg,
31+
display: "flex",
32+
flexDirection: "column",
33+
overflow: "hidden",
34+
}}
35+
>
36+
{/* Terminal chrome title bar */}
37+
<div
38+
style={{
39+
height: 48,
40+
flexShrink: 0,
41+
backgroundColor: theme.bg,
42+
display: "flex",
43+
alignItems: "center",
44+
paddingLeft: 16,
45+
paddingRight: 16,
46+
borderBottom: `1px solid ${theme.border}`,
47+
}}
48+
>
49+
{/* Traffic lights */}
50+
<div style={{ display: "flex", gap: 7 }}>
51+
<div style={{ width: 12, height: 12, borderRadius: "50%", backgroundColor: "#FF5F57" }} />
52+
<div style={{ width: 12, height: 12, borderRadius: "50%", backgroundColor: "#FEBC2E" }} />
53+
<div style={{ width: 12, height: 12, borderRadius: "50%", backgroundColor: "#28C840" }} />
54+
</div>
55+
56+
{/* Center title */}
57+
<div style={{ flex: 1, textAlign: "center", fontSize: 15, color: theme.comment }}>
58+
claude — ~/papertrail
59+
</div>
60+
61+
{/* Watermark */}
62+
<div
63+
style={{
64+
display: "flex",
65+
alignItems: "center",
66+
gap: 10,
67+
fontSize: 18,
68+
opacity: 0.8,
69+
}}
70+
>
71+
<span>
72+
<span style={{ color: theme.fgBright, fontWeight: "bold" }}>agent</span>
73+
<span style={{ color: theme.green, fontWeight: "bold" }}>crumbs</span>
74+
</span>
75+
<span style={{ color: theme.comment, fontSize: 15 }}>by</span>
76+
<span style={{ color: theme.comment, fontSize: 15, display: "flex", alignItems: "center", gap: 5 }}>
77+
<svg width="15" height="15" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
78+
<path fillRule="evenodd" clipRule="evenodd" d="M41.6889 52.2795L60.4195 20L106.839 100H14L32.7305 67.7195L45.9801 75.3312L40.5003 84.7756H80.3387L60.4195 50.4478L54.9396 59.8922L41.6889 52.2795Z" fill="#A8FF53"/>
79+
</svg>
80+
Trigger.dev
81+
</span>
82+
</div>
83+
</div>
84+
85+
{/* Scrollable content area — content pinned to bottom */}
86+
<div
87+
style={{
88+
flex: 1,
89+
overflow: "hidden",
90+
display: "flex",
91+
flexDirection: "column",
92+
justifyContent: "flex-end",
93+
}}
94+
>
95+
<div
96+
style={{
97+
padding: "0 24px 12px",
98+
transform: `translateY(${-scrollY}px)`,
99+
}}
100+
>
101+
{children}
102+
</div>
103+
</div>
104+
105+
{/* Input bar */}
106+
{showInput && (
107+
<div
108+
style={{
109+
flexShrink: 0,
110+
borderTop: `1px solid ${theme.border}`,
111+
padding: "10px 20px",
112+
fontSize: 18,
113+
}}
114+
>
115+
<span style={{ color: theme.comment }}>{"› "}</span>
116+
<span style={{ color: theme.fgBright }}>{inputText}</span>
117+
<span
118+
style={{
119+
backgroundColor: theme.fg,
120+
width: 10,
121+
height: 20,
122+
display: "inline-block",
123+
marginLeft: 1,
124+
verticalAlign: "text-bottom",
125+
}}
126+
/>
127+
</div>
128+
)}
129+
130+
{/* Footer status bar */}
131+
<div
132+
style={{
133+
height: 36,
134+
flexShrink: 0,
135+
borderTop: `1px solid ${theme.border}`,
136+
display: "flex",
137+
alignItems: "center",
138+
justifyContent: "space-between",
139+
paddingLeft: 20,
140+
paddingRight: 20,
141+
fontSize: 14,
142+
color: theme.comment,
143+
}}
144+
>
145+
<div>
146+
<span style={{ color: theme.green }}>{"▸▸ "}</span>
147+
<span style={{ color: theme.green }}>accept edits on</span>
148+
<span>{" (shift+tab to cycle)"}</span>
149+
</div>
150+
<div>
151+
papertrail | Opus 4.6 (1M context) | ${cost}
152+
</div>
153+
</div>
154+
</div>
155+
);
156+
};
157+
158+
// Styled spans for Claude Code output
159+
export const Prompt: React.FC<{ children: React.ReactNode }> = ({
160+
children,
161+
}) => <span style={{ color: theme.green }}>{"❯ "}</span>;
162+
163+
export const ClaudeIcon: React.FC = () => (
164+
<span style={{ color: "#D4A574" }}>{"⏺ "}</span>
165+
);
166+
167+
export const Dim: React.FC<{ children: React.ReactNode }> = ({ children }) => (
168+
<span style={{ color: theme.comment }}>{children}</span>
169+
);
170+
171+
export const Bright: React.FC<{ children: React.ReactNode }> = ({
172+
children,
173+
}) => <span style={{ color: theme.fgBright }}>{children}</span>;
174+
175+
export const Keyword: React.FC<{ children: React.ReactNode }> = ({
176+
children,
177+
}) => <span style={{ color: theme.keyword }}>{children}</span>;
178+
179+
export const Str: React.FC<{ children: React.ReactNode }> = ({ children }) => (
180+
<span style={{ color: theme.string }}>{children}</span>
181+
);
182+
183+
export const Fn: React.FC<{ children: React.ReactNode }> = ({ children }) => (
184+
<span style={{ color: theme.function }}>{children}</span>
185+
);
186+
187+
export const Comment: React.FC<{ children: React.ReactNode }> = ({
188+
children,
189+
}) => <span style={{ color: theme.comment }}>{children}</span>;
190+
191+
export const Type: React.FC<{ children: React.ReactNode }> = ({
192+
children,
193+
}) => <span style={{ color: theme.type }}>{children}</span>;
194+
195+
export const Err: React.FC<{ children: React.ReactNode }> = ({
196+
children,
197+
}) => <span style={{ color: theme.error }}>{children}</span>;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import type React from "react";
2+
import { theme } from "./theme";
3+
4+
type CrumbLineProps = {
5+
ns: string;
6+
nsColor: string;
7+
msg: string;
8+
dt: string;
9+
data?: string;
10+
depth?: number;
11+
type?: "crumb" | "scope:enter" | "scope:exit" | "scope:error" | "time" | "snapshot" | "session:start";
12+
tags?: string[];
13+
sid?: string;
14+
};
15+
16+
export const CrumbLine: React.FC<CrumbLineProps> = ({
17+
ns,
18+
nsColor,
19+
msg,
20+
dt,
21+
data,
22+
depth = 0,
23+
type = "crumb",
24+
tags,
25+
}) => {
26+
const pad = " ".repeat(depth);
27+
const dtStyle = { color: theme.comment };
28+
29+
let msgDisplay: React.ReactNode;
30+
31+
switch (type) {
32+
case "scope:enter":
33+
msgDisplay = (
34+
<>
35+
{pad}
36+
<span style={{ fontWeight: "bold" }}>[{msg}]</span>{" "}
37+
<span style={dtStyle}></span> enter
38+
</>
39+
);
40+
break;
41+
case "scope:exit":
42+
msgDisplay = (
43+
<>
44+
{pad}
45+
<span style={{ fontWeight: "bold" }}>[{msg}]</span>{" "}
46+
<span style={dtStyle}></span> exit
47+
</>
48+
);
49+
break;
50+
case "scope:error":
51+
msgDisplay = (
52+
<>
53+
{pad}
54+
<span style={{ fontWeight: "bold" }}>[{msg}]</span>{" "}
55+
<span style={{ color: theme.error }}>!!</span>{" "}
56+
<span style={{ color: theme.error }}>error</span>
57+
</>
58+
);
59+
break;
60+
case "time":
61+
msgDisplay = (
62+
<>
63+
{pad}
64+
<span style={dtStyle}>time:</span> {msg}
65+
</>
66+
);
67+
break;
68+
case "snapshot":
69+
msgDisplay = (
70+
<>
71+
{pad}
72+
<span style={dtStyle}>snapshot:</span> {msg}
73+
</>
74+
);
75+
break;
76+
case "session:start":
77+
msgDisplay = (
78+
<>
79+
{pad}
80+
<span style={{ fontWeight: "bold" }}>session start:</span> {msg}
81+
</>
82+
);
83+
break;
84+
default:
85+
msgDisplay = (
86+
<>
87+
{pad}
88+
{msg}
89+
</>
90+
);
91+
}
92+
93+
return (
94+
<div style={{ whiteSpace: "pre", fontSize: 16, lineHeight: 1.5 }}>
95+
<span style={{ color: nsColor, display: "inline-block", width: 140 }}>
96+
{ns}
97+
</span>
98+
{" "}
99+
<span style={{ color: theme.fgBright }}>{msgDisplay}</span>
100+
{" "}
101+
<span style={dtStyle}>{dt}</span>
102+
{tags && tags.length > 0 && (
103+
<span style={dtStyle}> [{tags.join(", ")}]</span>
104+
)}
105+
{data && (
106+
<span style={{ color: theme.comment }}> {data}</span>
107+
)}
108+
</div>
109+
);
110+
};

examples/sizzle-reel/src/Root.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Composition } from "remotion";
2+
import { AgentCrumbsDemo } from "./AgentCrumbsDemo";
3+
4+
export const RemotionRoot: React.FC = () => {
5+
return (
6+
<Composition
7+
id="AgentCrumbsDemo"
8+
component={AgentCrumbsDemo}
9+
durationInFrames={849}
10+
fps={30}
11+
width={1920}
12+
height={1080}
13+
/>
14+
);
15+
};

0 commit comments

Comments
 (0)