The coordinate space bug that four rewrites couldn't fix
I spent most of today's session on a bug that turned out to be architectural, not logical. The setup frandy.dev has an animated timeline section. Cards sit in a horizontal track. You can fold them to peek width by dragging the right edge. A neon light travels across three spine tracks and flashes when it reaches each card's node dot. The flash timing was wrong — off by varying amounts depending on scroll position and card state. The failed approaches Fixing the threshold — larger, smaller, speed-dependent Adding direction guards — only flash when approaching Fixing the position math — accounting for scrollLeft, cardWidths state Full rebuild of the detection loop None of it worked consistently. The actual problem The traveling light existed in viewport space — pixels from the left edge of t
I spent most of today's session on a bug that turned out to be architectural, not logical.
The setup
frandy.dev has an animated timeline section. Cards sit in a horizontal track. You can fold them to peek width by dragging the right edge. A neon light travels across three spine tracks and flashes when it reaches each card's node dot.
The flash timing was wrong — off by varying amounts depending on scroll position and card state.
The failed approaches
-
Fixing the threshold — larger, smaller, speed-dependent
-
Adding direction guards — only flash when approaching
-
Fixing the position math — accounting for scrollLeft, cardWidths state
-
Full rebuild of the detection loop
None of it worked consistently.
The actual problem
The traveling light existed in viewport space — pixels from the left edge of the visible overlay.
Node positions were calculated in card space — accumulated pixel widths across all cards, starting from the left of the entire track including scrolled-off cards.
These only agree at one specific state: scroll = 0, all cards open. Any deviation and they diverge.
The fix
function measure() { const oRect = overlay.getBoundingClientRect();function measure() { const oRect = overlay.getBoundingClientRect();const dots = document.querySelectorAll("[data-tl-node]"); for (const dot of dots) { const r = dot.getBoundingClientRect(); const x = r.left + r.width / 2 - oRect.left; if (x < -10 || x > overlayWidth + 10) continue; // off-screen, skip nodes.push({ x, idx, color }); } }`
Enter fullscreen mode
Exit fullscreen mode
Stop calculating. Measure from the DOM. getBoundingClientRect() gives you the actual rendered position in the coordinate system you're already using.
Re-measure on scroll, card width changes, filter changes, resize. Use a dirty flag so you measure at most once per animation frame.
The light now flashes exactly on the node dot. Every time. Because it's reading reality.
Broader takeaway
When your coordinate math keeps drifting from what you see on screen, you're probably in the wrong coordinate space. The browser already computed the correct answer. getBoundingClientRect() hands it to you.
What else shipped
Theme system — full light/dark mode with 4 accents. localStorage beats admin default. Desktop dropdown, mobile slide-down sheet that swaps visibility with BackToTop on scroll.
Timeline UX — rubber-band drag, spring physics, sticky first card, double-tap to open panel, card index watermark, breathing peek dot.
3-track spine pulse — comet tail, speed variation, escort offset, node flash with spin + ripple, future card color fallback, clean restart.
UI polish — chip/TabBar borders fixed, BackToTop realigned, section padding and nav height increased, text opacity improved.
Where things stand
The site is not shipped yet. Timeline desktop is done. Next is a design-only pass — mobile layout for every section, then admin. No new features. Getting everything looking right before it goes live.
DEV Community
https://dev.to/frandy-slueue/the-coordinate-space-bug-that-four-rewrites-couldnt-fix-3khiSign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
feature
The Pre-Flight Checklist: 7 Things I Verify Before Sending Any Prompt to Production
You wouldn't deploy code without running tests. So why are you sending prompts to production without checking them first? After shipping dozens of AI-powered features, I've settled on a 7-item pre-flight checklist that catches most problems before they reach users. Here it is. 1. Input Boundaries Does the prompt handle edge cases in the input? Empty strings Extremely long inputs (token overflow) Unexpected formats (JSON when expecting plain text) Quick test: Feed it the worst input you can imagine. If it degrades gracefully, you're good. 2. Output Format Lock Is the expected output format explicitly stated in the prompt? Bad: "Summarize this article." Good: "Summarize this article in exactly 3 bullet points, each under 20 words." Without format constraints, you get different shapes every r

Data Reduction
More data doesn’t always mean better insights . In fact, excessive data storage can cripple your operations, inflate costs, and slow down decision-making. Introduction In today’s data-driven world, organizations are drowning in information. Every transaction, customer interaction, and operational process generates data — terabytes upon terabytes of it. But here’s the paradox: more data doesn’t always mean better insights . In fact, excessive data storage can cripple your operations, inflate costs, and slow down decision-making. Enter data reduction — a strategic approach to managing data volume without sacrificing the information you actually need. Data Reduction? Data reduction is the process of deliberately limiting the amount of data your organization stores by eliminating redundancy ,

I Built a Pokédex for AI Coding Companions
The Idea Claude Code has a /buddy feature — it gives you a random AI companion with ASCII art, a name, a personality, and stats. It's cute. It sits in your config file. Nobody else ever sees it. I thought: what if we made it competitive? What I Built Buddy Board — a competitive leaderboard and trading card system for Claude Code companions. One command to join: npx buddy-board ` https://buddyboard.xyz/og-image.png How It Works Your buddy is deterministic. It's computed from a hash of your Claude Code account ID using a seeded Mulberry32 PRNG — the same algorithm Claude Code uses internally. Your species, rarity, stats, eyes, and hat are all derived from this hash. That means your buddy is truly yours. Same account, same buddy, every time. The Stats Every buddy has 5 stats (0-100): Debuggin
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products

The Pre-Flight Checklist: 7 Things I Verify Before Sending Any Prompt to Production
You wouldn't deploy code without running tests. So why are you sending prompts to production without checking them first? After shipping dozens of AI-powered features, I've settled on a 7-item pre-flight checklist that catches most problems before they reach users. Here it is. 1. Input Boundaries Does the prompt handle edge cases in the input? Empty strings Extremely long inputs (token overflow) Unexpected formats (JSON when expecting plain text) Quick test: Feed it the worst input you can imagine. If it degrades gracefully, you're good. 2. Output Format Lock Is the expected output format explicitly stated in the prompt? Bad: "Summarize this article." Good: "Summarize this article in exactly 3 bullet points, each under 20 words." Without format constraints, you get different shapes every r

Measuring AI's Role in Software Development: Evaluating Agency and Productivity in Low-Level Programming Tasks
The Role of AI in Low-Level Software Development: An Expert Analysis As a low-level programmer, I’ve witnessed the growing integration of AI tools like GitHub Copilot into software development workflows. The industry hype often portrays these tools as revolutionary, capable of transforming coding into a near-autonomous process. However, my firsthand experience reveals a more nuanced reality: AI serves as an accelerator and assistant, but its agency in handling complex, low-level tasks remains severely limited. This analysis dissects the mechanisms, constraints, and system instabilities of AI in this domain, contrasting practical contributions with exaggerated claims. Mechanisms of AI Integration in Low-Level Development 1. AI-Assisted Code Completion Impact → Internal Process → Observable
Desktop Canary v2.1.48-canary.32
🐤 Canary Build — v2.1.48-canary.32 Automated canary build from canary branch. Commit Information Based on changes since v2.1.48-canary.31 Commit count: 1 14cd81b624 ✨ feat(cli): add migrate openclaw command ( #13566 ) (Arvin Xu) ⚠️ Important Notes This is an automated canary build and is NOT intended for production use. Canary builds are triggered by build / fix / style commits on the canary branch. May contain unstable or incomplete changes . Use at your own risk. It is strongly recommended to back up your data before using a canary build. 📦 Installation Download the appropriate installer for your platform from the assets below. Platform File macOS (Apple Silicon) .dmg (arm64) macOS (Intel) .dmg (x64) Windows .exe Linux .AppImage / .deb



Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!