{
"$type": "site.standard.document",
"canonicalUrl": "https://devlog.croft.click/2026/05/08/timeline-observer-fix",
"description": "Every devlog entry was invisible on load — $state on an IntersectionObserver variable caused the effect to disconnect it before it could fire.",
"path": "/2026/05/08/timeline-observer-fix",
"publishedAt": "2026-05-08T19:35:53.000Z",
"site": "at://did:plc:ofrbh253gwicbkc5nktqepol/site.standard.publication/3mlen2qhzrt2s",
"tags": [
"website",
"tooling"
],
"textContent": "The problem\n\nThe devlog launched with 94 posts and showed none of them. Data was fine, build was fine — the scroll reveal was broken.\n\nEntries 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:\n\nReading $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.\n\nFix\n\nobserver is internal to the effect and not read anywhere in the template. It didn't need to be reactive.",
"title": "Timeline Scroll Reveal Fix"
}