);
}
diff --git a/remotion/src/scenes/SecretsScene.tsx b/remotion/src/scenes/SecretsScene.tsx
index 61c2113..20d69a3 100644
--- a/remotion/src/scenes/SecretsScene.tsx
+++ b/remotion/src/scenes/SecretsScene.tsx
@@ -2,54 +2,54 @@ import { interpolate } from 'remotion';
import { C } from '../lib/colors';
import { springIn, softSpring, clampLerp } from '../lib/easings';
-// Phase 1.5 (frames 75–165 global → localFrame 0..90): the prompt panel from
-// Phase 1 slides left and a second, vault-styled panel appears to its right.
-// The user's API key is masked (`secret_•••••••••••••••••••3a8f`) and a
-// "stored AES-256 · never sent to the AI" sub-label calms the trust nerves.
-//
-// Toward the end of the phase, two arrows fork apart:
-// • prompt → LLM brain icon (active, glowing) → continues right/down
-// • secrets → vault icon (active) → cross-marked through the LLM,
-// re-emerging beyond it
-// Both reconverge at the right edge to set up the Phase 2 build/server card.
-//
-// The arrow forking IS the architectural punchline: prose lives goes through
-// the LLM, the secret value does not.
+// Phase 3 (now 456 frames, ~15.2s): prompt panel + vault panel + arrow fork
+// (original beats over first ~90 frames). Then new beats:
+// • AES-256-GCM stamp appears next to the vault (frame ~95).
+// • Masked key value animates from the vault into a `key={NOTION_API_KEY}`
+// env-var pill placed beside a small container outline → "injected at
+// runtime" moment (frames ~180–340).
+// • Late beat: the prompt panel flickers back in DIM and labeled
+// "what the model sees", visually separating from the vault.
const PROMPT_TEXT = 'Build me an MCP server that searches our Notion workspace.';
const KEY_LABEL = 'NOTION_API_KEY';
-const KEY_VISIBLE = 'secret_'; // typed portion before masking
+const KEY_VISIBLE = 'secret_';
const KEY_BULLETS = '•••••••••••••••••••';
const KEY_TAIL = '3a8f';
-export function SecretsScene({ localFrame, fps }: { localFrame: number; fps: number }) {
- // Layout: two panels side-by-side, each ~620 wide, centered.
- // Prompt mini-panel sits on the left at x≈260; secrets vault at x≈1040.
- // Prompt panel slides in from its Phase-1 center position; secrets panel
- // springs in from the right at frame ~8.
+const SCENE_LEN = 456;
- // Prompt panel: enters by sliding left from its previous (centered) home.
+// Original phase-1.5 beats (unchanged):
+const TYPE_START = 30;
+const TYPE_END = 44;
+const MASK_START = 46;
+const MASK_END = 60;
+const TAIL_START = 60;
+const TAIL_END = 66;
+const LOCK_SNAP_AT = 66;
+const ARROW_START = 70;
+const ARROW_END = 88;
+
+// New beats:
+const AES_STAMP_AT = 95;
+const INJECT_START = 180; // ~6s — key chip pops out of vault
+const INJECT_FLY_END = 240; // chip arrives at container
+const CONTAINER_IN = 200;
+const FLICKER_PROMPT_AT = 300; // "the model only sees the description"
+
+const EXIT_START = SCENE_LEN - 12;
+
+export function SecretsScene({ localFrame, fps }: { localFrame: number; fps: number }) {
+ // Prompt panel: enters by sliding left from center.
const promptShift = clampLerp(localFrame, 0, 18);
- // Phase 1 ended centered. Phase 1.5 puts the prompt panel at left third.
const promptX = interpolate(promptShift, [0, 1], [410, 60]);
- // Secrets panel: spring in from below-right.
+ // Secrets vault panel: spring in from below-right.
const vaultIn = springIn(localFrame, fps, 8);
const vaultOpacity = clampLerp(localFrame, 8, 24);
const vaultY = interpolate(vaultIn, [0, 1], [40, 0]);
const vaultScale = interpolate(vaultIn, [0, 1], [0.92, 1]);
- // Key field typing: "secret_" appears in plaintext for a beat (chars/sec ~24),
- // then masking pass: bullets fade in while plaintext fades out, tail "3a8f"
- // reveals at the end. Locked-icon snaps closed once masking finishes.
- const TYPE_START = 30;
- const TYPE_END = 44; // shows "secret_"
- const MASK_START = 46;
- const MASK_END = 60; // bullets in
- const TAIL_START = 60;
- const TAIL_END = 66;
- const LOCK_SNAP_AT = 66;
-
const typingProgress = clampLerp(localFrame, TYPE_START, TYPE_END);
const maskProgress = clampLerp(localFrame, MASK_START, MASK_END);
const tailProgress = clampLerp(localFrame, TAIL_START, TAIL_END);
@@ -62,18 +62,45 @@ export function SecretsScene({ localFrame, fps }: { localFrame: number; fps: num
const tailChars = Math.floor(tailProgress * KEY_TAIL.length);
const tailShown = KEY_TAIL.slice(0, tailChars);
- // Once masking begins, fade the "secret_" plaintext into a stable header
- // of bullets (the user no longer sees raw prefix either).
- const plaintextOpacity = interpolate(maskProgress, [0, 1], [1, 1]); // keep "secret_" as prefix
-
- // Arrow fork animation starts at localFrame ~70 and runs until 88.
- const ARROW_START = 70;
- const ARROW_END = 88;
const arrowProgress = clampLerp(localFrame, ARROW_START, ARROW_END);
const xMarkPop = springIn(localFrame, fps, ARROW_START + 8);
- // Phase exit drift — last 6 frames, lift up subtly (parent already crossfades).
- const exitProgress = clampLerp(localFrame, 84, 90);
+ // After ~110 frames, the arrows + LLM icon fade out to clear the canvas for
+ // the new beats (env-var injection).
+ const arrowFadeOut = 1 - clampLerp(localFrame, 110, 140);
+
+ // AES stamp.
+ const aesIn = springIn(localFrame, fps, AES_STAMP_AT);
+
+ // Env-var injection: the masked key value flies from the vault into a
+ // container outline.
+ const injectProgress = clampLerp(localFrame, INJECT_START, INJECT_FLY_END);
+ const containerIn = springIn(localFrame, fps, CONTAINER_IN);
+
+ // Lock-snap flash — a short bright indigo ring expands outward from the
+ // lock the moment it closes. Lifts the snap from "subtle SVG morph" to
+ // "the vault clicked shut". Lasts ~12 frames, peaks at frame 66+4.
+ const lockFlashT = clampLerp(localFrame, LOCK_SNAP_AT, LOCK_SNAP_AT + 16);
+ const lockFlashFade = 1 - clampLerp(localFrame, LOCK_SNAP_AT + 6, LOCK_SNAP_AT + 22);
+ const lockFlash = Math.min(lockFlashT, lockFlashFade);
+
+ // Late stage: keep vault at FULL opacity throughout so the eye still has
+ // it as the anchor while the env-var injection happens to the side. The
+ // prompt panel still fades — that beat is owned by the arrow fork.
+ const stageShift = clampLerp(localFrame, INJECT_START - 20, INJECT_START + 10);
+ const vaultLateOpacity = 1;
+ const promptLateOpacity = interpolate(stageShift, [0, 1], [1, 0]);
+
+ // Vault → container connector — a soft dashed line drawn between the
+ // vault's bottom edge and the container's env slot at the moment the
+ // chip travels. Anchors the architectural story: this key came FROM
+ // that vault.
+ const connectorReveal = clampLerp(localFrame, INJECT_START - 6, INJECT_START + 18);
+ const connectorFade = 1 - clampLerp(localFrame, INJECT_FLY_END + 6, INJECT_FLY_END + 30);
+ const connectorAlpha = Math.min(connectorReveal, connectorFade);
+
+ // Exit drift.
+ const exitProgress = clampLerp(localFrame, EXIT_START, SCENE_LEN);
const exitY = interpolate(exitProgress, [0, 1], [0, -24]);
return (
@@ -84,17 +111,21 @@ export function SecretsScene({ localFrame, fps }: { localFrame: number; fps: num
transform: `translateY(${exitY}px)`,
}}
>
- {/* Prompt mini-panel (left) */}
-
+ {/* Original prompt mini-panel (left). Fades into the late stage. */}
+
+
+
- {/* Secrets vault panel (right) */}
+ {/* Vault panel (right) — stays at FULL opacity through the whole
+ scene so the eye keeps it as the anchor while the env-var
+ chip travels to the container below. */}
+ {/* Lock-snap flash — bright ring expanding out from the lock
+ icon at the exact moment it closes. The lock icon itself
+ sits at the vault panel's header (top-left), so the flash
+ is anchored there. */}
+ {lockFlash > 0.02 && (
+
+
+
+
+ )}
- {/* Arrow fork SVG overlay — drawn full-frame, but only the arrow paths
- are visible; the rest is transparent. */}
-
+ {/* AES-256-GCM stamp */}
+ {aesIn > 0.02 && (
+
+ AES-256-GCM
+
+ )}
+
+ {/* Arrow fork SVG (fades out after initial beat) */}
+
+
+
+
+ {/* Vault → container connector — appears as the chip starts its
+ flight, so the eye reads "the key in the vault BECOMES the
+ env var in the container." Without this the chip-flight
+ reads as "thing moves" rather than "vault feeds container". */}
+
+
+ {/* New beat: container outline + env-var injection */}
+ {containerIn > 0.02 && (
+
+ )}
+
+ {/* AI-view vs your-stack reveal — replaces the earlier "flicker
+ back" beat. Two compact callouts that frame the architectural
+ contrast: what the AI saw (just the prompt sentence), versus
+ what your stack holds (vault + container with the secret).
+ Both labelled, both readable. Appears late and stays until
+ scene-exit. */}
+
);
}
+function VaultContainerConnector({ alpha }: { alpha: number }) {
+ if (alpha < 0.01) return null;
+ // Vault sits at (1040–1860, ~350–730). Container sits at (720–1200,
+ // 720–920). Draw a dashed indigo curve from the vault's bottom-left
+ // (about 1100, 720) to the container's right-top env slot
+ // (about 1200, 850). Slight arc for visual interest.
+ return (
+
+ );
+}
+
+function AiViewVsStack({ localFrame }: { localFrame: number }) {
+ // Appears at FLICKER_PROMPT_AT (300) after the env-var has landed
+ // in the container — once both halves of the stack exist on screen,
+ // we can label them. Designed in v10 to be more visually emphatic
+ // than the previous compact card: literal viewfinder bracket corners
+ // around the prompt text frame the idea "this is everything the
+ // model can see," plus a stronger three-line "denied list" below.
+ const inT = clampLerp(localFrame, FLICKER_PROMPT_AT, FLICKER_PROMPT_AT + 22);
+ if (inT < 0.02) return null;
+ const fadeOut = 1 - clampLerp(localFrame, SCENE_LEN - 24, SCENE_LEN - 8);
+ const opacity = inT * fadeOut;
+
+ const promptShortened = '“Build me an MCP server that searches our Notion workspace.”';
+
+ // Bigger, more central. Width 680 (was 560), positioned so the
+ // viewfinder frame is the dominant left-side element.
+ const W = 680;
+ const LEFT = 60;
+ const TOP = 180;
+
+ return (
+
+ {/* Header — "what the AI sees" with eye icon for instant readability */}
+
+
+ what the AI sees
+
+
+ {/* Viewfinder frame: prompt text surrounded by four corner brackets
+ to read as "this is the entire field of view." */}
+
+
+ {promptShortened}
+
+
+ {/* Denied list — three explicit "not in view" lines so the
+ contrast with the stack on the right reads even on a quick
+ scrub. */}
+
+ );
+}
+
+function EyeIcon() {
+ return (
+
+ );
+}
+
+function ViewfinderCorners() {
+ // Four L-shaped brackets at the corners of the parent frame. SVG
+ // path d-attributes do NOT accept CSS calc(); instead each corner is
+ // a separate
sized in pixels with two borders showing through.
+ // Positioned absolutely to the frame's inside, 4 px from each edge.
+ const armLen = 18;
+ const stroke = 1.6;
+ const colour = C.fgSubtle;
+ const opacity = 0.75;
+ const inset = 4;
+ const cornerStyle = {
+ position: 'absolute' as const,
+ width: armLen,
+ height: armLen,
+ pointerEvents: 'none' as const,
+ opacity,
+ };
+ return (
+ <>
+ {/* top-left */}
+
+ {/* top-right */}
+
+ {/* bottom-left */}
+
+ {/* bottom-right */}
+
+ >
+ );
+}
+
+function DeniedDot() {
+ return (
+
+ );
+}
+
+// ------- Sub-components below -------
+
function PromptMiniPanel({ x, promptText }: { x: number; promptText: string }) {
- // A condensed version of Phase 1's input field. Same border / glow style
- // (accent active) but the cursor is gone and the text is full.
return (
+ )}
+ >
+ );
+}
diff --git a/remotion/voice text von audio.txt b/remotion/voice text von audio.txt
new file mode 100644
index 0000000..e4f1c1a
--- /dev/null
+++ b/remotion/voice text von audio.txt
@@ -0,0 +1,15 @@
+Code generation with AI is solved. What's left is hosting, oh-auth, domains, containers, secret injection — and keeping your keys out of the AI context.
+
+BuildMyMCPServer closes that gap. One sentence describes your tool. The AI generates the code — [emphasis] the prompt path and the secret path never cross.
+
+Your credentials live in a separate vault, encrypted with A-E-S two fifty six, isolated from the AI pipeline. Injected into your container as environment variables at runtime. [serious] The model only sees the description.
+
+We generate the TypeScript, run static checks, ship the container — under sixty seconds.
+
+Each server runs in its own hardened container. Read-only filesystem, dropped capabilities, no new privileges. Oh-auth two point one with pixie — no shared bearer tokens, no API keys in headers.
+
+Export the code anytime, or share it as a template. The code travels, your secrets stay.
+
+One sentence in. Live server out.
+
+BuildMyMCPServer dot com
\ No newline at end of file