From 33bbd7b0bcca5291593814376d20681825f5e6eb Mon Sep 17 00:00:00 2001
From: cevheri
Date: Tue, 25 Aug 2026 22:33:53 +0300
Subject: [PATCH] feat(home): swap the promo video for the interactive
walkthrough
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The home page led with a click-to-load YouTube facade. It now leads with
the demo itself: two self-contained bundles in public/demo/ — a 16:9
editor clip and a portrait phone clip — picked by viewport and played
when they scroll into view. React, fonts and screenshots are inlined, so
this keeps the facade's property of making no third-party request, and
adds nothing to our own bundle.
Two things the bundles do not agree on, both handled in the component:
- They listen for different messages and each ignores the other's — the
desktop clip wants the string 'libredb-demo:play', the phone clip wants
{type: 'om-demo-play'}. Both forms go out; the loaded clip picks up its
own.
- The desktop clip's 'play' does not resume a paused run, it starts
another timeline on top of it, so a second animated cursor drifts
across the frame after the first scroll-away-and-back (a third after
the next). It is played once per document and a re-entry reloads it.
The phone clip resumes properly and just continues.
The frame takes the full container width rather than the video's
max-w-3xl: the clip renders a whole IDE at 16:9, and the extra ~250px is
the difference between readable SQL and a thumbnail. Below md the phone
clip is readable at 390px, which the scaled-down desktop clip was not.
PromoVideo stays — /get-started still uses it.
Co-Authored-By: Claude Opus 5 (1M context)
---
public/demo/libredb-studio-demo-mobile.html | 398 ++++++++++++++++++++
public/demo/libredb-studio-demo.html | 385 +++++++++++++++++++
src/components/sections/HomeSection.astro | 13 +-
src/components/sections/LibreDBDemo.astro | 130 +++++++
4 files changed, 921 insertions(+), 5 deletions(-)
create mode 100644 public/demo/libredb-studio-demo-mobile.html
create mode 100644 public/demo/libredb-studio-demo.html
create mode 100644 src/components/sections/LibreDBDemo.astro
diff --git a/public/demo/libredb-studio-demo-mobile.html b/public/demo/libredb-studio-demo-mobile.html
new file mode 100644
index 0000000..a941e47
--- /dev/null
+++ b/public/demo/libredb-studio-demo-mobile.html
@@ -0,0 +1,398 @@
+
+
+
+
+ Bundled Page
+
+
+
+
+
+
+
+
Unpacking...
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/demo/libredb-studio-demo.html b/public/demo/libredb-studio-demo.html
new file mode 100644
index 0000000..91fa002
--- /dev/null
+++ b/public/demo/libredb-studio-demo.html
@@ -0,0 +1,385 @@
+
+
+
+
+ Bundled Page
+
+
+
+
+
+
Unpacking...
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/sections/HomeSection.astro b/src/components/sections/HomeSection.astro
index 4f2c4f0..c95f7f7 100644
--- a/src/components/sections/HomeSection.astro
+++ b/src/components/sections/HomeSection.astro
@@ -1,5 +1,5 @@
---
-import PromoVideo from './PromoVideo.astro';
+import LibreDBDemo from './LibreDBDemo.astro';
import { ENGINES } from '../../data/engines';
import { sectionById } from '../../data/sections';
@@ -80,11 +80,14 @@ const flagship = [
-
-
-
+
+
+
- -- 60s demo: the whole IDE, in motion.
+ -- the whole IDE, in motion.
diff --git a/src/components/sections/LibreDBDemo.astro b/src/components/sections/LibreDBDemo.astro
new file mode 100644
index 0000000..ebfbbe8
--- /dev/null
+++ b/src/components/sections/LibreDBDemo.astro
@@ -0,0 +1,130 @@
+---
+// The interactive editor walkthrough, embedded in an iframe — a desktop clip
+// and a portrait phone clip, picked by viewport.
+//
+// Each bundle in public/demo/ is one self-contained file: React, fonts and
+// screenshots are all inlined, so there is no third-party request, no React in
+// our bundle, and no CSS or font leaking in either direction.
+//
+// Both load with ?autoplay=0 and are told to play when they scroll into view,
+// so a visitor never arrives after the walkthrough has already finished. Tab
+// clicks and the Replay button work inside the frame.
+//
+// The markup carries the desktop clip so it still renders without JS; the
+// script swaps in the phone clip below md. That runs at parse time, well before
+// a lazy iframe this far down the page starts fetching, so a phone never pulls
+// the desktop bundle.
+interface Props {
+ class?: string;
+}
+const { class: className = '' } = Astro.props;
+---
+
+