buildmymcpserver/apps/web/components/hero-video.tsx

152 lines
5.5 KiB
TypeScript
Raw Normal View History

feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
'use client';
import { Play, Volume2, VolumeX } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
/**
* Hero video player with two controls:
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
*
* 1. Big PLAY overlay shown while the video is paused. Browsers
* block autoplay for users with `prefers-reduced-motion`, on data
* saver, or with strict autoplay policies so the poster sits
* there forever and the visitor thinks the page is broken. The
* overlay gives them an explicit, unmissable affordance to start
* it. We also wire `onClick` on the <video> element itself so
* clicking anywhere on the frame plays / pauses, matching the
* universal YouTube / Vimeo pattern.
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
*
* 2. Frosted mute toggle pinned bottom-right. Always visible so the
* visitor can flip the voice-over on whether they hit play
* themselves or it autoplayed.
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
*
* Initial state is muted (browser autoplay requires it). On mount we
* attempt `.play()` defensively the promise resolves silently if
* autoplay was granted, rejects silently if blocked. Either way the
* `play` / `pause` event listeners keep our React state in sync with
* whatever the element is actually doing.
*
* On unmute we re-call `.play()` because mobile Safari pauses on a
* muted-property change mid-playback. Swallow the promise failure
* just means the user can hit play again, which the overlay already
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
* affords.
*/
export function HeroVideo() {
const videoRef = useRef<HTMLVideoElement>(null);
const [muted, setMuted] = useState(true);
const [playing, setPlaying] = useState(false);
useEffect(() => {
const v = videoRef.current;
if (!v) return;
// Sync React state with whatever the element actually does.
const onPlay = () => setPlaying(true);
const onPause = () => setPlaying(false);
v.addEventListener('play', onPlay);
v.addEventListener('pause', onPause);
// Best-effort autoplay. Promise rejection = user has to click play.
v.play().catch(() => undefined);
return () => {
v.removeEventListener('play', onPlay);
v.removeEventListener('pause', onPause);
};
}, []);
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
const togglePlay = useCallback(() => {
const v = videoRef.current;
if (!v) return;
if (v.paused) {
v.play().catch(() => undefined);
} else {
v.pause();
}
}, []);
const toggleMute = useCallback((e: React.MouseEvent) => {
// Stop propagation so clicking the mute pill doesn't also
// play/pause via the video's onClick handler.
e.stopPropagation();
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
const v = videoRef.current;
if (!v) return;
const next = !v.muted;
v.muted = next;
setMuted(next);
if (!next && v.paused) {
// Keep playback running after the user enables sound — mobile
// Safari pauses on muted-property change mid-playback.
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
v.play().catch(() => undefined);
}
}, []);
return (
<>
<video
ref={videoRef}
autoPlay
muted
loop
playsInline
preload="auto"
poster="/videos/hero-poster.jpg"
onClick={togglePlay}
className="size-full cursor-pointer object-cover"
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
aria-label="Animation: a prompt becomes a live MCP server, with secrets staying isolated from the AI pipeline"
>
<source src="/videos/hero.webm" type="video/webm" />
<source src="/videos/hero.mp4" type="video/mp4" />
</video>
{/* Centre PLAY button shown only while paused. Covers the
whole video so clicking anywhere starts playback; the inner
circle is the visual affordance. */}
{!playing && (
<button
type="button"
onClick={togglePlay}
aria-label="Play video"
className="group absolute inset-0 z-10 flex items-center justify-center"
style={{
backgroundColor: 'color-mix(in oklab, var(--color-bg) 30%, transparent)',
}}
>
<div
className="flex size-20 items-center justify-center rounded-full border backdrop-blur transition-transform duration-200 ease-out group-hover:scale-110"
style={{
backgroundColor:
'color-mix(in oklab, var(--color-bg-elevated) 80%, transparent)',
borderColor: 'var(--color-accent)',
boxShadow:
'0 0 32px rgba(99, 102, 241, 0.45), 0 12px 40px rgba(0,0,0,0.55)',
color: 'var(--color-accent)',
}}
>
{/* `translate-x-0.5` optically centres the play triangle
its visual centre of mass is left of its bounding box. */}
<Play size={32} fill="currentColor" className="translate-x-0.5" />
</div>
</button>
)}
{/* Mute toggle always visible, top of z-stack so it stays
clickable even when the play overlay is up. */}
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
<button
type="button"
onClick={toggleMute}
aria-label={muted ? 'Unmute video' : 'Mute video'}
aria-pressed={!muted}
className="absolute bottom-4 right-4 z-20 inline-flex size-10 items-center justify-center rounded-full border backdrop-blur transition-colors duration-150 hover:text-[--color-fg] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-accent]"
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
style={{
backgroundColor:
'color-mix(in oklab, var(--color-bg-elevated) 75%, transparent)',
feat(video): v10 hero video with mute toggle — voice + bg music Ships the long-form (71.5 s) hero video to the marketing /flow section along with the iteration trail of architectural visual fixes the owner worked through over the last sprint. ## Video composition (remotion/) Eight phases driven by the 71.47 s voice-over in `audio.mp3` plus the `Sub-bass Lullaby.wav` background music (ducked to 0.16 with fade in / fade out). Every scene was rebuilt for v10 with concrete fixes: - **HookScene** (12 s) — adds FloatingChaos overlay: a docker-compose excerpt, an oauth_callback.ts snippet, an .env file with a yellow squiggle warning ("in git history since v0.3.1"), and a live-ticking 502 retry toast. Tangle now reads as a developer's desktop right before they give up, not as four icons drifting. - **PromptScene** (12.2 s) — 6.5 s post-typing dead-zone replaced with the parse beat: three sequential highlights on the prompt text (MCP server / searches / Notion workspace), three chips below the input (intent / tool / secret → vault), three-stat summary panel (tools · 2, secrets · 1, targets · 3). At local frame 250 (≈ 21 s global, on the voice line "the prompt path and the secret path never cross") a mini two-rail diagram with an explicit X-marker ring lands, visualising the architectural promise the moment it's spoken. - **SecretsScene** (15.2 s) — kept the arrow-fork + AES-256 stamp + env-var injection beats; added the lock-snap flash at frame 66, pinned the vault at full opacity throughout, and added a dashed vault → container connector so the secret's provenance is visible. The "what the AI sees" panel is now 680 px wide with an eye icon, four corner viewfinder brackets around the prompt text, and three explicit denied lines (no secrets / no environment variables / no tokens). - **BuildScene** (7.2 s) — unchanged beats: streaming log, server card emerges with code + 🔒 NOTION_API_KEY slot pills, isolated- container caption, <60s countdown. - **IsolationScene** (14 s) — completely restructured. Orbit-and-dock chips that collided with the card and with the tokens-only badge are replaced by a clean vertical chip column at x=760: read-only filesystem · dropped capabilities · no new privileges · 512 MB memory cap · 0.5 CPU limit · ✓ your token only (last in green). A vault graphic now sits below the server card with a dashed arrow up into its env slot so the architecture story is complete in one frame. PKCE jargon removed: "OAuth 2.1 · PKCE" → "only your token gets in" with a small "oauth 2.1 · proof-key flow" subtitle for the curious. Handshake stages simplified to your client → verified → scoped token. Final settlement arrow in success-green curves from the scoped-token pill back into the card. - **LibraryScene** (7 s) — cards enlarged from 340×180 to 400×220 with 36 px gaps. The "templates carry code, not credentials" sub-caption was pulled (felt on-the-nose; the detached lock and empty NOTION_API_KEY=? slot carry the story visually). - **DiscoveryScene** (3 s) — the most-iterated scene. Earlier versions had a fake "1,200+ developers building" fork counter (pulled — solo-founder, hadn't earned). Replaced with a two-lane architecture diagram that visualises "no paths cross" literally: top lane prompt → AI → code, bottom lane vault → encrypted → env, both converging at the server box on the right. v10 refinements: all seven boxes visible from frame 0 (no late server arrival), a parallel glow tour walks across both lanes simultaneously, a dashed vertical divider with a "no shared node" chip pinned in the middle, and the closing line "One sentence in. Live server out." slides down from above and lands centred while the diagram fades to 0.12 opacity behind it — no overlap. - **LogoLockup** (1.7 s) — wordmark + fade-to-black for a clean loop seam. The Subtitle / CAPTIONS layer added in v7 was pulled wholesale — owner found the kinetic-typography overlay aggressive and noted that technical terms (PKCE etc.) created friction with no payoff. Scene visuals and voice now carry the whole story; the Subtitle component file is retained for possible future use. Render pipeline (`render:mp4` / `render:webm` / `render:poster` in remotion/package.json) is unchanged. The MP4 is post-processed to H.264 Main / yuv420p / TV-range with faststart + AAC audio. The WebM is re-encoded at VP9 CRF 38 / Opus 64k to stay under the 3 MB budget. Final artefacts in apps/web/public/videos/: 2.59 MB mp4, 2.99 MB webm, 62 KB poster. ## Web integration (apps/web/components/hero-video.tsx) New client component wraps the <video> element and pins a frosted- glass mute toggle bottom-right of the player. Why not native `controls`: the browser chrome fights the section's design vocabulary and we only need one affordance — unmute — so we render exactly that. The toggle's icon flips between VolumeX (currently muted) and Volume2 (currently unmuted), accent colour switches indigo when sound is on. Initial state is muted so autoplay still fires; on unmute we call .play() defensively because mobile Safari pauses on muted-property changes mid-playback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:31:10 +02:00
borderColor: 'var(--color-border)',
color: muted ? 'var(--color-fg-muted)' : 'var(--color-accent)',
}}
>
{muted ? <VolumeX size={18} /> : <Volume2 size={18} />}
</button>
</>
);
}