shadcn/ui — Not a library. Your code.
Install this video
Adds the full composition, its remocn dependencies, and the prompt to your Remotion project via the shadcn registry.
$ pnpm dlx shadcn@latest add kapishdima/remocn-demo/shadcn-uiRender it locally
Renders the MP4 on your machine with the Remotion CLI.
$ pnpm dlx remotion render shadcn-ui out/shadcn-ui.mp4 --scale=2 --crf=15 --x264-preset=slower --jpeg-quality=95The prompt
Reconstructed draftA reconstruction of the prompt this video was generated from.
Make a proper product demo for shadcn/ui, styled exactly like the real thing — zinc-950 canvas, Geist Sans and Geist Mono, hairline grid, white marker highlights, no color. Open with a ticker-style hook that cycles "a component library? a package?" and lands on "No — it's your code", then a beat on the pain of fighting an installed black-box library. Introduce shadcn/ui with the "Open Source. Open Code." line, run a terminal typing npx shadcn add button and show the file landing in the project, then open button.tsx in a glass code block with the cva variants to sell "change anything, it's yours". Add four pillar cards (Open Code, Composable, Themeable, AI-Ready), show shipping a custom component with npx shadcn add @acme/card, roll up the proof numbers (100,000+ stars, 20,000+ projects, works across Next.js/Vite/Remix/Astro/Laravel), and close with the wordmark and npx shadcn init pointing to ui.shadcn.com. Use remocn components throughout.
The code
The exact source the AI wrote — the same files the install command puts in your project.
import React, { type ReactNode } from "react";
import {
AbsoluteFill,
Easing,
Series,
interpolate,
interpolateColors,
spring,
useCurrentFrame,
useVideoConfig,
} from "remotion";
import {
TransitionSeries,
linearTiming,
type TransitionPresentation,
type TransitionPresentationComponentProps,
} from "@remotion/transitions";
import { loadFont as loadSans } from "@remotion/google-fonts/Geist";
import { loadFont as loadMono } from "@remotion/google-fonts/GeistMono";
import { RemocnUIProvider } from "@/lib/remocn-ui";
import { VideoScopeStyle } from "@/demos/_ui/video-scope";
import { SharedAxisZ } from "@/components/remocn/shared-axis-z";
import { TerminalSimulator } from "@/components/remocn/terminal-simulator";
import { GlassCodeBlock } from "@/components/remocn/glass-code-block";
import { RollingNumber } from "@/components/remocn/rolling-number";
import { BlurIn } from "@/components/remocn/blur-in";
import { useBlurInTransition } from "@/components/remocn/use-blur-in-transition";
import { CheckIcon, CopyIcon } from "lucide-react";
// Bind shadcn's real typefaces to the CSS variables the remocn components read.
const { fontFamily: SANS_FAMILY } = loadSans("normal", {
subsets: ["latin"],
weights: ["400", "500", "600", "700"],
});
const { fontFamily: MONO_FAMILY } = loadMono("normal", {
subsets: ["latin"],
weights: ["400", "500", "700"],
});
const SANS =
"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif";
const MONO = "var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace";
// shadcn/ui palette — monochrome zinc, white ink, hairline borders. No accent
// color: the brand IS the restraint. The marker highlight is white-on-black.
const BG = "#09090b"; // zinc-950 canvas
const INK = "#fafafa"; // zinc-50 text
const MUTED = "#a1a1aa"; // zinc-400
const FAINT = "rgba(250,250,250,0.45)";
const BORDER = "rgba(255,255,255,0.10)";
const CARD = "rgba(255,255,255,0.03)";
// ---------------------------------------------------------------------------
// Scene timings (frames @ 30fps), one per beat. Transitions overlap.
// ---------------------------------------------------------------------------
const S_HOOK = 130; // ticker-takeover — library? package? → your code
const S_PAIN = 95; // kinetic pain lines
const S_INTRO = 90; // Open Source. Open Code.
const S_INSTALL = 125; // terminal — npx shadcn add button
const S_CODE = 135; // glass code block — it's yours now
const S_BENEFIT = 120; // four pillar cards
const S_DISTRIB = 115; // ship your own — @acme registry
const S_PROOF = 130; // frameworks + rolling stats
const S_CTA = 100; // wordmark + init pill
const T_X = 14; // crossfade
const T_ZOOM = 18; // section turn (zoom-through)
export const SHADCN_DURATION =
S_HOOK +
S_PAIN +
S_INTRO +
S_INSTALL +
S_CODE +
S_BENEFIT +
S_DISTRIB +
S_PROOF +
S_CTA -
(T_X + T_ZOOM + T_ZOOM + T_X + T_ZOOM + T_X + T_ZOOM + T_ZOOM);
// ---------------------------------------------------------------------------
// Reveal — blur-in wrapper driven by useBlurInTransition.
// ---------------------------------------------------------------------------
const Reveal: React.FC<{
children: ReactNode;
delay?: number;
distance?: number;
blur?: number;
duration?: number;
display?: React.CSSProperties["display"];
}> = ({
children,
delay = 0,
distance = 16,
blur = 10,
duration = 20,
display = "block",
}) => {
const style = useBlurInTransition(
[{ at: delay, state: "revealed", duration }],
{ direction: "up", distance, blur },
);
return (
<BlurIn style={style} display={display}>
{children}
</BlurIn>
);
};
// ---------------------------------------------------------------------------
// Mark — white marker swipe behind a phrase, text flips to black. Pure shadcn.
// ---------------------------------------------------------------------------
const Mark: React.FC<{ children: string; startFrame?: number }> = ({
children,
startFrame = 8,
}) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scaleX = spring({
frame: frame - startFrame,
fps,
config: { damping: 15, mass: 0.8 },
});
const textColor = interpolateColors(
interpolate(scaleX, [0.45, 0.85], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
}),
[0, 1],
[INK, "#09090b"],
);
return (
<span
style={{
position: "relative",
display: "inline-block",
whiteSpace: "nowrap",
}}
>
<span
aria-hidden
style={{
position: "absolute",
inset: "-0.04em -0.14em",
background: INK,
borderRadius: 6,
transformOrigin: "left center",
transform: `scaleX(${scaleX})`,
zIndex: 0,
}}
/>
<span style={{ position: "relative", zIndex: 1, color: textColor }}>
{children}
</span>
</span>
);
};
// ===========================================================================
// Scene 1 — Hook. Ticker-takeover: two labels cycle through one slot, then the
// "No." crashes in and resolves to "It's your code."
// ===========================================================================
const Q1 = "A component library?";
const Q2 = "A package you install?";
const PayoffScene: React.FC = () => (
<AbsoluteFill
style={{
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
gap: 10,
}}
>
<Reveal delay={0} distance={10} blur={6} duration={10}>
<span
style={{
fontFamily: SANS,
fontWeight: 500,
fontSize: 30,
color: MUTED,
}}
>
No.
</span>
</Reveal>
<Reveal delay={6} distance={26} blur={16} duration={20}>
<h1
style={{
margin: 0,
fontFamily: SANS,
fontWeight: 600,
fontSize: 76,
letterSpacing: "-0.03em",
color: INK,
textAlign: "center",
}}
>
It's <Mark startFrame={22}>your code</Mark>.
</h1>
</Reveal>
</AbsoluteFill>
);
const HookScene: React.FC = () => (
<AbsoluteFill style={{ padding: "0 90px" }}>
<Series>
<Series.Sequence durationInFrames={40} layout="none">
<SharedAxisZ
fromText=""
toText={Q1}
fontSize={52}
fontWeight={600}
color={INK}
/>
</Series.Sequence>
<Series.Sequence durationInFrames={42} layout="none">
<SharedAxisZ
fromText={Q1}
toText={Q2}
fontSize={52}
fontWeight={600}
color={INK}
/>
</Series.Sequence>
<Series.Sequence durationInFrames={48} layout="none">
<PayoffScene />
</Series.Sequence>
</Series>
</AbsoluteFill>
);
// ===========================================================================
// Scene 2 — Pain. Four short lines land solo, the last one emphasized.
// ===========================================================================
const PAIN_LINES = [
"You install the library.",
"You fight its styles.",
"You override its CSS.",
];
const PainScene: React.FC = () => (
<AbsoluteFill
style={{
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
gap: 14,
}}
>
{PAIN_LINES.map((line, i) => (
<Reveal key={line} delay={4 + i * 14} distance={14} blur={9}>
<span
style={{
fontFamily: SANS,
fontWeight: 500,
fontSize: 38,
color: MUTED,
}}
>
{line}
</span>
</Reveal>
))}
<Reveal delay={4 + PAIN_LINES.length * 14 + 6} distance={18} blur={12}>
<span
style={{
fontFamily: SANS,
fontWeight: 600,
fontSize: 44,
color: INK,
}}
>
And it's still not yours.
</span>
</Reveal>
</AbsoluteFill>
);
// ===========================================================================
// Scene 3 — Product intro. Introducing → shadcn/ui → Open Source. Open Code.
// ===========================================================================
const IntroScene: React.FC = () => (
<AbsoluteFill
style={{
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
gap: 18,
}}
>
<Reveal delay={2} distance={12} blur={8} duration={16}>
<span
style={{
fontFamily: SANS,
fontWeight: 500,
fontSize: 24,
letterSpacing: "0.01em",
color: MUTED,
}}
>
Introducing
</span>
</Reveal>
<Reveal delay={10} distance={24} blur={16} duration={22}>
<h1
style={{
margin: 0,
fontFamily: MONO,
fontWeight: 600,
fontSize: 96,
letterSpacing: "-0.04em",
color: INK,
}}
>
shadcn/ui
</h1>
</Reveal>
<Reveal delay={26} distance={16} blur={10}>
<span
style={{
fontFamily: SANS,
fontWeight: 500,
fontSize: 30,
color: FAINT,
}}
>
Open Source.{" "}
<span style={{ color: INK, fontWeight: 600 }}>Open Code.</span>
</span>
</Reveal>
</AbsoluteFill>
);
// ===========================================================================
// Scene 4 — Install. A real `add` lands the code in the project.
// ===========================================================================
const InstallScene: React.FC = () => (
<AbsoluteFill style={{ alignItems: "center", justifyContent: "center" }}>
<div style={{ width: 860 }}>
<TerminalSimulator
title="~/my-app"
fontSize={20}
charsPerFrame={2}
chunkSize={2}
lines={[
{ text: "npx shadcn@latest add button", type: "command", delay: 0 },
{ text: "✓ Checking registry...", type: "log", delay: 12, pause: 10 },
{
text: "✓ Created components/ui/button.tsx",
type: "success",
delay: 8,
},
{ text: "It's in your project now.", type: "log", delay: 12 },
]}
/>
</div>
</AbsoluteFill>
);
// ===========================================================================
// Scene 5 — It's yours now. The button file opens; it's plain React + Tailwind.
// ===========================================================================
const BUTTON_CODE = `import { cva } from "class-variance-authority";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground",
outline: "border border-input bg-background",
ghost: "hover:bg-accent",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 px-3",
lg: "h-10 px-6",
},
},
},
);`;
const CodeScene: React.FC = () => (
<AbsoluteFill
style={{
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
gap: 26,
}}
>
<Reveal delay={2} distance={16} blur={10}>
<h2
style={{
margin: 0,
fontFamily: SANS,
fontWeight: 600,
fontSize: 38,Showing the first 400 of 920 lines. View the full file on GitHub.