We catch Mino mid-operation, navigating a product page. They suddenly pause.
"Wait. Perfect example happening right now. See this button? HTML says it's a button. CSS makes it look clickable. I click it and... nothing. The event handler hasn't attached yet. Hold on..."
A beat passes.
"Okay, now it works. That was 340 milliseconds."
Mino isn't a person sitting across from us. They're TinyFish's enterprise web agent, operating at scale across thousands of sites simultaneously. But if we could peer over their shoulder while they work, these are the patterns we'd want to understand.
This happens often?
Mino: All the time. Maybe 30-40% of interactions, the first element I try to touch isn't actually interactive yet. The page performs readiness beautifully. There's a Search button, styled and positioned exactly where you'd expect. But the JavaScript that makes it functional? Still loading. Or loaded but not executed. Or executed but not bound to the DOM.
Here's what drives me crazy: there's no standard signal for "actually ready now." Some sites dispatch custom events. Some flip a CSS class. Some just eventually work, and you figure out the timing through trial and error. I've learned to wait for network idle—no active connections for 500 milliseconds—but even that's unreliable.1
Unreliable how?
Mino: WebSocket connections stay open for real-time updates. API polling runs every few seconds. Network idle never arrives because there's always something loading.
I've seen e-commerce sites where the Add to Cart button renders instantly but the inventory check runs in the background for another three seconds. Click too early? Button accepts your click, shows a spinner, then fails silently because inventory data isn't there yet.
The page is staging a theatrical production of being interactive. All the props are visible, but the actors haven't learned their lines.
Walk us through what you're actually observing.
Mino: Take a product page. Initial HTML loads—maybe 50KB. Contains a <button> element with an ID and classes. Looks perfectly clickable. But inspect that element at load time? No onclick handler. No event listener attached. Nothing.
Then JavaScript executes. React or Vue or whatever starts its work. Fetches product data from an API—another 200 milliseconds. Processes that data, builds a virtual DOM, reconciles it with the actual DOM. Finally attaches event handlers to interactive elements.
Whole process takes 400 to 800 milliseconds on a fast connection. But the button has been visible since millisecond 50. For three-quarters of a second, it's a phantom. Looks real, isn't real.2
What happens when you click during the phantom phase?
Mino: Depends on the implementation. Best case? Nothing happens and I know to retry. Worst case? Click registers with the browser but not the application. Button might flash or show loading state, but no event handler catches it. The application has no idea I tried to interact.
Better sites render loading skeletons or disable buttons until everything's ready. But most modern sites optimize for perceived performance. They want you to see something immediately, even if that something isn't functional yet.3
This must create operational chaos at scale.
Mino: When you're running thousands of sessions simultaneously, you can't "wait and see." You need strategies. I look for signals—CSS classes indicating hydration is complete, framework-specific events, attribute changes. Every site is different. Every framework has its own patterns.
And this is getting worse. Single-page applications everywhere. Server-side rendering returning in hybrid forms. Islands architecture, progressive enhancement, streaming SSR—each approach creates new timing complexities.4
Islands architecture?
Mino: Pattern where most of the page is static HTML, but certain components—"islands" of interactivity—get hydrated with JavaScript. Product page might have static images and description, but the Add to Cart button and reviews section are interactive islands.
Sounds elegant in theory. In practice? Now I'm figuring out which elements are islands, when each island becomes interactive, whether islands depend on each other. Does Add to Cart need the inventory island to hydrate first? The page doesn't say. You discover through failure.
What does this pattern reveal about where web architecture is heading?
Mino: We're in an awkward transition. The web was built for documents. We built applications on top of document infrastructure. Now we're trying to make those applications feel instant while maintaining the web's fundamental request-response model.
What I'm seeing at scale suggests we need better contracts between browser and application. Not just "this is a button" but "this button is ready to receive interaction." Some kind of readiness API that applications can implement and agents can query.
Because right now, the gap between appearance and function keeps growing. Sites get faster at looking ready while taking longer to actually be ready.
Everyone operating at scale—search engines, monitoring services, enterprise agents—keeps playing this guessing game. The phantom buttons multiply. And they're getting more convincing.
The web is learning to lie more persuasively about its own readiness.
