perf(vibe): stop building a plasma and reading the library on a phone

Two things made the Vibe page crawl on mobile.

The ambient aura pushed three counter-rotating layers through an SVG
turbulence and displacement pass whose noise field was animated in SMIL.
SVG filters rasterise on the CPU, so that regenerated the whole field
every frame, under a blur, across a 420x380 element. Below the
breakpoint the filter is no longer mounted and the layers churn behind a
plain blur instead. A phone gets the motion, not the noise pass.

The start screen read all 5,000 tracks to show fifty of them. The sample
is now drawn in the database, which keeps Surprise me uniform over the
whole library while sending only what is on screen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KENqSChfyqWnor6ud2WWH6
This commit is contained in:
kami
2026-08-10 14:00:19 +04:00
parent 0a01085ed0
commit 5a019bd35c
8 changed files with 157 additions and 47 deletions
+38 -25
View File
@@ -1,4 +1,5 @@
import type { CSSProperties } from 'react';
import { useMediaQuery } from '../hooks/useMediaQuery';
export interface VibeProfile {
energy?: number;
@@ -19,6 +20,9 @@ function describeProfile(energy: number, novelty: number) {
/** An ambient representation of the live recommendation profile. */
export function VibeAura({ profile, ambient = false }: { profile: VibeProfile; ambient?: boolean }) {
// The displacement pass is desktop-only; see the comment in the ambient
// branch below. Same breakpoint the layout already uses for this element.
const plasma = useMediaQuery('(min-width: 640px)');
const energy = clamp(profile.energy, 0.5);
const novelty = clamp(profile.noveltyHunger ?? profile.explorationCoefficient, 0.3);
const { energyLabel, discoveryLabel } = describeProfile(energy, novelty);
@@ -58,6 +62,13 @@ export function VibeAura({ profile, ambient = false }: { profile: VibeProfile; a
// Displacing clean gradients by animated fractal noise is what separates a
// plasma from a blurred blob. baseFrequency is animated in SMIL rather than
// CSS because no CSS property reaches inside an SVG filter primitive.
//
// That pass is also why the Vibe page crawled on a phone. An SVG filter is
// rasterised on the CPU, and animating baseFrequency regenerates the whole
// turbulence field every frame — for a 420x380 element, under a blur, over
// three counter-rotating layers. Below the breakpoint the filter is not
// mounted at all and the same layers churn behind a plain blur, which is
// the difference between a heavy effect and a scrolling page.
return (
<div
className="vibe-aura-blob pointer-events-none absolute z-0 h-[380px] w-[420px] -translate-x-1/2 -translate-y-1/2 opacity-85 mix-blend-screen sm:h-[560px] sm:w-[660px] sm:opacity-95"
@@ -65,32 +76,34 @@ export function VibeAura({ profile, ambient = false }: { profile: VibeProfile; a
role="img"
aria-label={`Current Vibe: ${energyLabel} energy and ${discoveryLabel} discovery`}
>
<svg aria-hidden className="absolute h-0 w-0">
<filter id="vibe-plasma" x="-30%" y="-30%" width="160%" height="160%">
<feTurbulence
type="fractalNoise"
baseFrequency="0.009 0.014"
numOctaves={3}
seed={7}
result="noise"
>
<animate
attributeName="baseFrequency"
dur={`${(18 - energy * 8).toFixed(1)}s`}
values="0.009 0.014; 0.021 0.007; 0.009 0.014"
repeatCount="indefinite"
{plasma && (
<svg aria-hidden className="absolute h-0 w-0">
<filter id="vibe-plasma" x="-30%" y="-30%" width="160%" height="160%">
<feTurbulence
type="fractalNoise"
baseFrequency="0.009 0.014"
numOctaves={3}
seed={7}
result="noise"
>
<animate
attributeName="baseFrequency"
dur={`${(18 - energy * 8).toFixed(1)}s`}
values="0.009 0.014; 0.021 0.007; 0.009 0.014"
repeatCount="indefinite"
/>
</feTurbulence>
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale={String(Math.round(46 + energy * 70))}
xChannelSelector="R"
yChannelSelector="G"
/>
</feTurbulence>
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale={String(Math.round(46 + energy * 70))}
xChannelSelector="R"
yChannelSelector="G"
/>
</filter>
</svg>
<div className="vibe-aura-stack">
</filter>
</svg>
)}
<div className={plasma ? 'vibe-aura-stack vibe-aura-stack-plasma' : 'vibe-aura-stack'}>
<div className="vibe-aura-layer vibe-aura-rays-layer" />
<div className="vibe-aura-layer vibe-aura-swirl-layer" />
<div className="vibe-aura-layer vibe-aura-core-layer" />