fix(intro): splash always honors App's decision + video streams 3x lighter

- SplashScreen no longer re-checks neode_intro_seen itself: it silently
  skipped the whole logo-tap/typing sequence for any browser that had
  seen the intro before, even when App.vue explicitly requested it (demo
  fresh visits, Replay Intro). App.vue is the single decision point.
- Intro video re-encoded 12.7MB/12.6Mbps → 4.3MB/4.2Mbps (1920x1080 CRF23
  faststart, muted track dropped) — visually identical on this
  illustrated content; cache-buster bumped to v=8.
- Video is <link rel=preload>ed the moment the splash is scheduled (the
  <video> element only mounts ~20s in, so cold caches used to start the
  download mid-sequence and stutter).
- nginx demo cache regex now covers mp4/webm/mp3/webp/woff2 so repeat
  visits play from browser cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-07-15 11:53:14 +01:00
co-authored by Claude Fable 5
parent 0c591a997e
commit efd1ae41de
5 changed files with 23 additions and 21 deletions
+8 -18
View File
@@ -14,7 +14,7 @@
preload="auto"
poster="/assets/img/bg-intro.jpg"
>
<source src="/assets/video/video-intro.mp4?v=7" type="video/mp4">
<source src="/assets/video/video-intro.mp4?v=8" type="video/mp4">
<!-- Fallback to image if video fails -->
<div
class="absolute inset-0"
@@ -266,16 +266,12 @@ watch([showWelcome, showLogo], ([welcome, logo]) => {
}
})
// Check if user has seen intro
// Also detect returning users who cleared cache: if we're on a /dashboard route,
// the backend session is still active so the user has been here before.
const storedSeenIntro = localStorage.getItem('neode_intro_seen') === '1'
const isOnDashboard = window.location.pathname.startsWith('/dashboard')
const seenIntro = storedSeenIntro || isOnDashboard
// Persist the flag so subsequent loads don't re-check
if (!storedSeenIntro && isOnDashboard) {
localStorage.setItem('neode_intro_seen', '1')
}
// NOTE: whether the intro should play is decided ONCE by App.vue
// (shouldShowIntroSplash) — this component is only mounted when the answer was
// yes, so it must not re-check neode_intro_seen itself. The old internal
// re-check silently skipped the whole sequence for any browser that had seen
// the intro before, even when App.vue explicitly asked for a replay (demo
// fresh visits, the Replay Intro link).
function handleEnterKey(e: KeyboardEvent) {
if (e.key === 'Enter' && showTapToStart.value && !tapStartTransitioning.value) {
@@ -468,13 +464,7 @@ function startAlienIntro() {
}
onMounted(() => {
if (seenIntro) {
showSplash.value = false
document.body.classList.add('splash-complete')
emit('complete')
} else {
window.addEventListener('keydown', handleEnterKey)
}
window.addEventListener('keydown', handleEnterKey)
})
onBeforeUnmount(() => {