May 8, 2026 at 12:00:00 AM UTC
Timeline Scroll Reveal Fix
websitetooling
The problem
The devlog launched with 94 posts and showed none of them. Data was fine, build was fine — the scroll reveal was broken.
Entries start at opacity: 0 and get a revealed class from an IntersectionObserver when they enter the viewport. The observer variable was declared as $state, and the $effect that sets it up reads it in a guard:
let observer: IntersectionObserver | undefined = $state();
$effect(() => {
if (!timelineEl || observer) return;
observer = new IntersectionObserver(...);
});
Reading $state inside $effect creates a reactive dependency. Setting observer triggers a re-run — which fires the cleanup (observer.disconnect()) before the observer's async callback had a chance to run. Every entry stayed invisible.
Fix
let observer: IntersectionObserver | undefined;
observer is internal to the effect and not read anywhere in the template. It didn't need to be reactive.
all entries