shieldcn — Introducing shieldcn Plus
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/shieldcn-plusRender it locally
Renders the MP4 on your machine with the Remotion CLI.
$ pnpm dlx remotion render shieldcn-plus out/shieldcn-plus.mp4 --scale=2 --crf=15 --x264-preset=slower --jpeg-quality=95 --gl=angleThe prompt
Reconstructed draftA reconstruction of the prompt this video was generated from.
The code
The exact source the AI wrote — the same files the install command puts in your project.
import React, { useEffect, useMemo, useState, type ReactNode } from "react";
import {
AbsoluteFill,
Easing,
Img,
Sequence,
Series,
continueRender,
delayRender,
interpolate,
interpolateColors,
spring,
useCurrentFrame,
useVideoConfig,
} from "remotion";
import { demoAsset } from "@/lib/demo-assets";
import {
TransitionSeries,
linearTiming,
type TransitionPresentation,
type TransitionPresentationComponentProps,
} from "@remotion/transitions";
import { loadFont as loadSora } from "@remotion/google-fonts/Sora";
import { RemocnUIProvider } from "@/lib/remocn-ui";
import { ShortSlideRight } from "@/components/remocn/short-slide-right";
import { ClaudeChat } from "@/components/remocn/claude-chat";
import { ShimmerSweep } from "@/components/remocn/shimmer-sweep";
import { LineByLineSlide } from "@/components/remocn/line-by-line-slide";
import { RGBGlitchText } from "@/components/remocn/rgb-glitch-text";
import { RollingNumber } from "@/components/remocn/rolling-number";
import { BlurIn } from "@/components/remocn/blur-in";
import { useBlurInTransition } from "@/components/remocn/use-blur-in-transition";
import { ShaderWarp } from "@/components/remocn/shader-warp";
// The whole video is set in Sora — one family for headlines, URLs, params and
// repo names alike. Nothing goes above weight 500 (reserved for the lockups
// and the rolling stat); everything else is regular 400. The remocn text
// components read var(--font-geist-sans), so feeding Sora into that variable
// re-fonts them without touching library files.
const { fontFamily: SORA_FAMILY } = loadSora("normal", {
subsets: ["latin"],
weights: ["400", "500"],
});
const SANS =
"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif";
const MONO = "var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace";
// The shieldcn register: zinc canvas, ink, and the badge-value green. The
// violet and amber accents exist ONLY inside the brand-morph scene, and only
// as real renders fetched from shieldcn.dev with color= params.
const BG = "#09090b";
const INK = "#fafafa";
const MUTED = "#a1a1aa";
const FAINT = "rgba(250,250,250,0.45)";
const BORDER = "rgba(255,255,255,0.10)";
// Card surfaces are OPAQUE — the warp backdrop must never bleed through a
// card, only live between them.
const CARD = "#101014";
const GREEN = "#22c55e";
const GREEN_SOFT = "#4ade80";
const VIOLET = "#8b5cf6";
const AMBER = "#f59e0b";
const clampOpts = {
extrapolateLeft: "clamp" as const,
extrapolateRight: "clamp" as const,
};
// ---------------------------------------------------------------------------
// Scene timings (frames @ 30fps), one per beat. Transitions overlap.
// ---------------------------------------------------------------------------
const S_FRONTDOOR = 150; // the README assembles itself under a camera glide
// "This is shieldcn." then the category montage — Badges / Charts / Headers,
// each label backed by a REAL shieldcn render, hard-cut one into the next.
const WHAT_INTRO = 54;
const CAT_BADGES = 62;
const CAT_CHARTS = 58;
const CAT_HEADERS = 60;
const S_WHAT = WHAT_INTRO + CAT_BADGES + CAT_CHARTS + CAT_HEADERS;
const S_NEWS = 96; // now it has accounts — with sync
const S_MEET = 132; // Meet shieldcn Plus (shield draws on)
const S_SYNC = 138; // 75 saved READMEs, synced
const S_LIBRARY = 126; // the saved badges library
const S_MIGRATE = 132; // mass migration PR cascade
// The kinetic build itself takes ~81f (6 words: 10f first + 5 × 13f pushes,
// entering at frame 6) — the beat holds the assembled line for ~20f before
// the squeeze takes it, so the cut never lands mid-build.
const S_AI_TITLE = 118; // "AI generates and polishes your READMEs" (kinetic build + hold)
// AI writes the README — the dark Claude chat types the prompt, then a
// parallax hand-off pushes the chat DOWN while "Thinking" flies UP out of
// it (a gentle initial kick, long deceleration), and the result lands.
const AI_PUSH_AT = 88; // the chat is pushed away right after typing settles
const AI_PUSH_DUR = 18;
const AI_THINK = 56;
const AI_XFADE = 12; // thinking → result cross-dissolve overlap
const AI_RESULT = 88;
const S_AI = AI_PUSH_AT + AI_THINK + AI_RESULT;
const S_BRAND = 240; // one managed brand — the crown
const S_OFFER = 84; // 20% off your first 6 months (line-by-line)
const S_CTA = 170; // the closing shieldcn lockup
// Post-credits stinger — a hard cut after the lockup (the shared warp
// backdrop carries through, so it reads as a beat after the credits), then
// the promo code catches signal.
const STING_IN = 10; // black beat before the code flickers on
const STING_CAPTION = 34; // "promo code" label settles after the burst
const STING_EXIT = 96; // glitch-out burst + upward throw
const S_STINGER = 122;
const T_X = 14; // crossfade
const T_SQ = 16; // squeeze — mechanical collapse hidden under a blur envelope
const T_ZOOM = 18; // zoom-blur at section turns
const T_IRIS = 22; // pill-shaped iris reveal into the CTA
export const SHIELDCN_PLUS_DURATION =
S_FRONTDOOR +
S_WHAT +
S_NEWS +
S_MEET +
S_SYNC +
S_LIBRARY +
S_MIGRATE +
S_AI_TITLE +
S_AI +
S_BRAND +
S_OFFER +
S_CTA +
S_STINGER -
(T_SQ +
T_ZOOM +
T_ZOOM +
T_SQ +
T_X +
T_SQ +
T_X +
T_SQ +
T_ZOOM +
T_X +
T_IRIS);
// ---------------------------------------------------------------------------
// 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>
);
};
// ---------------------------------------------------------------------------
// SlideLine — a short-slide-right line stacked inside a flex column.
// SlideRich — the same motion for rich content (marker highlights etc.).
// ---------------------------------------------------------------------------
const SlideLine: React.FC<{
text: string;
at: number;
fontSize: number;
color?: string;
fontWeight?: number;
}> = ({ text, at, fontSize, color = INK, fontWeight = 400 }) => (
<div
style={{
position: "relative",
width: "100%",
height: Math.round(fontSize * 1.35),
}}
>
<Sequence from={at} layout="none">
<ShortSlideRight
text={text}
fontSize={fontSize}
color={color}
fontWeight={fontWeight}
/>
</Sequence>
</div>
);
const SlideRich: React.FC<{ at: number; children: ReactNode }> = ({
at,
children,
}) => {
const frame = useCurrentFrame();
const easing = Easing.bezier(0.2, 0.8, 0.2, 1);
const t = frame - at;
const x = interpolate(t, [0, 16], [-24, 0], { ...clampOpts, easing });
const opacity = interpolate(t, [0, 10], [0, 1], { ...clampOpts, easing });
const blurVal = interpolate(t, [0, 16], [1.2, 0], { ...clampOpts, easing });
return (
<div
style={{
transform: `translateX(${x}px)`,
opacity,
filter: `blur(${blurVal}px)`,
}}
>
{children}
</div>
);
};
// ---------------------------------------------------------------------------
// ShieldMark — the REAL shieldcn icon path from the repo
// (packages/core/src/icons/shieldcn.svg), stroke-drawing itself on before the
// fill settles in.
// ---------------------------------------------------------------------------
const SHIELD_PATH_A =
"M148.02,363.76c-4.48,0-8.64-2.42-10.86-6.32l-54.29-95.68c-2.15-3.8-2.15-8.52,0-12.32l54.29-95.68c2.21-3.9,6.37-6.32,10.86-6.32h18.51c4.44,0,8.45,2.28,10.73,6.09,2.27,3.82,2.37,8.43.25,12.33l-42.23,77.99c-3.98,7.36-3.98,16.14,0,23.49l22.22,41.02c4.25,7.85,12.43,12.8,21.36,12.92,0,0,45.08.61,45.11.61,8.68,0,16.83-4.64,21.26-12.12l24.87-41.99c2.23-3.77,6.34-6.11,10.72-6.12l19.47-.04c4.48,0,8.49,2.29,10.76,6.12,2.27,3.83,2.35,8.45.21,12.35l-42.2,77.17c-2.19,4-6.39,6.49-10.95,6.49h-110.08Z";
const SHIELD_PATH_B =
"M346.7,363.69c-4.44,0-8.45-2.28-10.73-6.09-2.27-3.82-2.37-8.43-.25-12.33l42.23-77.99c3.98-7.35,3.98-16.14,0-23.49l-22.22-41.02c-4.25-7.85-12.44-12.8-21.36-12.92,0,0-46.51-.63-46.53-.63-8.88,0-17.12,4.81-21.48,12.54l-23.35,41.36c-2.2,3.9-6.36,6.34-10.84,6.35l-19.21.04c-4.48,0-8.49-2.29-10.76-6.12-2.27-3.83-2.35-8.45-.22-12.36l42.2-77.17c2.19-4.01,6.39-6.5,10.95-6.5h110.08c4.48,0,8.64,2.42,10.86,6.32l54.29,95.68c2.16,3.8,2.16,8.52,0,12.32l-54.29,95.68c-2.21,3.9-6.37,6.32-10.86,6.32h-18.51Z";
const ShieldMark: React.FC<{ size: number; at?: number }> = ({
size,
at = 0,
}) => {
const frame = useCurrentFrame();
const draw = (start: number) =>
interpolate(frame, [at + start, at + start + 26], [1, 0], {
...clampOpts,
easing: Easing.inOut(Easing.cubic),
});
const fillOpacity = interpolate(frame, [at + 20, at + 38], [0, 1], {
...clampOpts,
easing: Easing.inOut(Easing.quad),
});
const strokeOpacity = interpolate(
frame,
[at + 30, at + 44],
[1, 0],
clampOpts,
);
return (
<svg width={size} height={size} viewBox="0 0 512 512">
{[SHIELD_PATH_A, SHIELD_PATH_B].map((d, i) => (
<path
key={i}
d={d}
pathLength={1}
strokeDasharray={1}
strokeDashoffset={draw(i * 6)}
stroke={INK}
strokeWidth={10}
strokeOpacity={strokeOpacity}
fill={INK}
fillOpacity={fillOpacity}
/>
))}
</svg>
);
};
// ===========================================================================
// Scene 1 — The front door, alive. A README assembles itself from REAL
// shieldcn renders while the camera pushes in and glides down the page.
// ===========================================================================
const PAGE_W = 720;
const PAGE_INNER = PAGE_W - 64;
const ProseLine: React.FC<{ width: string; at: number }> = ({ width, at }) => {
const frame = useCurrentFrame();
const p = interpolate(frame, [at, at + 12], [0, 1], {
...clampOpts,
easing: Easing.out(Easing.cubic),
});
return (
<div
style={{
width,
height: 10,
borderRadius: 5,
background: "rgba(255,255,255,0.08)",
transform: `scaleX(${p})`,
transformOrigin: "left center",
}}
/>
);
};
const FrontDoorScene: React.FC = () => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
// One continuous camera move: push in while gliding down the page.
const glide = interpolate(frame, [0, durationInFrames], [26, -470], {
...clampOpts,
easing: Easing.inOut(Easing.quad),
});
const zoom = interpolate(frame, [0, durationInFrames], [1.04, 1.17], {
...clampOpts,
easing: Easing.inOut(Easing.quad),
});
// The page itself materializes first; the content assembles onto it.
const pageIn = interpolate(frame, [0, 16], [0, 1], {
...clampOpts,
easing: Easing.out(Easing.cubic),
});
return (
<AbsoluteFill style={{ alignItems: "center" }}>
<div style={{ transform: `scale(${zoom}) translateY(${glide}px)` }}>
<div
style={{
width: PAGE_W,
borderRadius: 16,
border: `1px solid ${BORDER}`,
background: "#0c0c0e",
padding: 32,
display: "flex",
flexDirection: "column",
gap: 18,
opacity: pageIn,
transform: `translateY(${(1 - pageIn) * 26}px) scale(${0.98 + pageIn * 0.02})`,
}}
>
{/* The real graph header lands first */}
<Reveal delay={10} distance={18} blur={12} duration={16}>
<Img
src={demoAsset("shieldcn/header-graph.svg")}
style={{ width: PAGE_INNER, height: "auto", display: "block" }}
/>
</Reveal>
{/* Three real xs badges snap in one after another */}
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
{["stars-shieldcn-xs", "license-xs", "npm-react-xs"].map(
(name, i) => (
<Reveal
key={name}
delay={20 + i * 5}
distance={8}
blur={6}
duration={10}
>
<Img
src={demoAsset(`shieldcn/${name}.svg`)}
style={{ height: 22, width: "auto", display: "block" }}
/>
</Reveal>
),
)}
</div>
{/* Prose skeleton draws on */}
<div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
<ProseLine width="94%" at={32} />
<ProseLine width="100%" at={37} />
<ProseLine width="72%" at={42} />
</div>
{/* The real star-history chart slides into place */}
<Reveal delay={42} distance={26} blur={14} duration={18}>
<Img
src={demoAsset("shieldcn/chart-stars.svg")}
style={{ width: PAGE_INNER, height: "auto", display: "block" }}
/>
</Reveal>
{/* The real sponsor wall settles at the bottom */}
<Reveal delay={58} distance={26} blur={14} duration={18}>
<Img
src={demoAsset("shieldcn/sponsors.svg")}
style={{ width: PAGE_INNER, height: "auto", display: "block" }}
/>
</Reveal>
</div>
</div>
</AbsoluteFill>
);
};
// ===========================================================================
// Scene 2 — What this is. Two beats on the shared Z axis.
// ===========================================================================
const MicroPhase: React.FC<{ children: ReactNode; outAt?: number }> = ({
children,
outAt,
}) => {
const frame = useCurrentFrame();
const easing = Easing.bezier(0.32, 0.72, 0, 1);
const opacityIn = interpolate(frame, [0, 18], [0, 1], {
...clampOpts,
easing,
});
const scale = interpolate(frame, [0, 18], [0.96, 1], {
...clampOpts,Showing the first 400 of 2250 lines. View the full file on GitHub.