{
  "$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"
}