Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions website/app/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,19 +470,43 @@ export default function LandingPage() {
</div>
</section>

<section class="pb-16">
<section class="intro-video pb-16">
<div class="max-w-3xl mx-auto px-6">
<div class="aspect-video overflow-hidden border border-border-strong shadow-[var(--shadow)]">
<!-- The frame is hidden until it fires load, over a black box.
A cross-origin iframe paints its OWN canvas, and YouTube's embed
sets its black background on body with no color-scheme declared,
so the black only lands once that stylesheet applies. Until then
some engines paint an opaque white canvas, which no background on
the iframe ELEMENT can cover, since the element background sits
behind that canvas. Hiding the frame sidesteps the whole question:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bg-black is a deliberate break from the theme tokens, and it is the right call here even though the original ask was theme consistency: the player itself settles on black in both themes, so a black box makes the reveal invisible, while --bg-sunken would step from near-white to black in light theme. Flagging it only so the literal is not later "corrected" to a token by someone reading it as an oversight.

what it paints early is simply not on screen, and the box under it
is already the black the player settles on, so the reveal is
invisible. onload is a plain HTML attribute rather than a template
hole, because an @event drops at SSR and this page never hydrates. -->
<div class="aspect-video overflow-hidden border border-border-strong shadow-[var(--shadow)] bg-black">
<iframe
class="w-full h-full"
src="https://www.youtube-nocookie.com/embed/iz23lVMvlVY?rel=0"
class="intro-video-frame w-full h-full invisible"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The one way this can strand: a request that never settles, firing neither load nor error, leaves the frame hidden permanently. I checked the adjacent case and it is fine, since a connection failure still fires load on the error page and reveals.

Worth stating rather than fixing, because the failure mode is benign: a request that never settles has nothing to show either way, so the reader sees a black box where they would previously have seen an empty or white one. If you want belt and braces it is one attribute, onerror="this.classList.remove('invisible')", and I am happy to add it. I left it out rather than add an attribute for a case I could not actually produce.

onload="this.classList.remove('invisible')"
src="https://www.youtube-nocookie.com/embed/XghCghezod4?rel=0"
title="WebJs introduction video"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
></iframe>
</div>
<!-- With JS off the whole section goes away. Revealing the frame
instead would show YouTube's own noscript error ("An error
occurred. Unable to execute JavaScript."), because their player
needs JS INSIDE the frame and nothing this page does can supply
it. An empty space reads better than a broken player.

The rule still applies from in here: a style element takes effect
wherever it sits, including inside the subtree it hides. And it
is safe in a PAGE, which never hydrates, so the client never
rebuilds this noscript body as live nodes. The same construct
inside a COMPONENT would apply on every JS-enabled visit. -->
<noscript><style>.intro-video { display: none }</style></noscript>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth knowing what this does not do: display: none suppresses painting, not fetching. A JS-off reader still issues 3 requests to youtube-nocookie.com before this rule hides anything, so the embed is invisible but not absent from the network.

There is no way to fix that from here, since the server cannot know whether scripting is on. The only markup that avoids the requests entirely is markup with no iframe in it until a click.

</div>
</section>

Expand Down
42 changes: 42 additions & 0 deletions website/test/ssr/intro-video-ssr.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* The landing page's intro video is hidden until its frame fires load.
*
* A cross-origin iframe paints its own canvas before the embedded stylesheet
* applies, and on some engines that canvas is opaque white, which no
* background on the iframe element can cover. Hiding the frame until load
* removes the question: what it paints early is off screen, and the box under
* it is already black.
*
* Each assertion here is a piece that silently breaks the whole thing if it
* goes missing, which is why they are pinned rather than left to review.
*/
import test from 'node:test';
import assert from 'node:assert/strict';
import { renderToString } from '@webjsdev/core/server';
import LandingPage from '#app/page.ts';

const render = () => renderToString(LandingPage());

test('the intro frame ships hidden, over a black box', async () => {
const out = await render();

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These pin the SSR markup, which is the part that can silently rot: I confirmed the first fails when the invisible class is removed, so it is not passing vacuously.

What they deliberately do not cover is the reveal itself, since asserting it needs a real load event from a third-party host and that is exactly the sort of test that fails on a plane. I verified that behaviour by hand instead (timings in the summary). Calling it out so the gap is a known one rather than an assumed pass.

assert.match(out, /class="intro-video-frame [^"]*\binvisible\b/, 'the frame must start hidden');
assert.match(out, /aspect-video[^"]*\bbg-black\b/, 'the box under it must be black');
});

test('the frame reveals itself with a plain onload attribute', async () => {
const out = await render();
// A plain HTML attribute, not an @event hole: this page never hydrates, so
// a template event binding would be dropped at SSR and the frame would stay
// hidden forever.
assert.match(out, /onload="this\.classList\.remove\('invisible'\)"/);
});

test('a JS-off reader gets no embed at all', async () => {
const out = await render();
// Without JS the load handler never runs AND YouTube's player cannot run
// inside the frame either, so revealing it would show their own noscript
// error rather than a video. Hide the whole section instead. The rule must
// live in noscript, which a browser with scripting on parses as inert text.
assert.match(out, /<noscript><style>\.intro-video \{ display: none \}<\/style><\/noscript>/);
assert.match(out, /<section class="intro-video /, 'the rule needs its hook on the section');
});
Loading