← All posts28 September 2026claude-codeside-projectpaymentsdebugging

My buy button was broken for 62 days and I had no idea

372 people signed up for my free guide, 4 bought the paid one, and for the first 62 days the buy button did nothing when you clicked it.

✓ Verified against own codebase + HubSpot data on 2026-09-28

You click "Buy". Nothing happens. No error, no checkout, no spinner. You shrug and close the tab.

That was my sales page for 62 days, from the day I launched The Claude Code Playbook on 5 May until I fixed it on 6 July.

The numbers that made me look

372 people have signed up for my free Claude Code cheat sheet. 4 people have bought the Playbook.

That gap bothered me enough that I finally sat down today and went through the whole funnel. The dead button wasn't news — I fixed it back in July — but I'd never connected it to the numbers. Plenty of those signups came in May and June, which is exactly when the button didn't work.

I'll never know how many sales it cost me. Maybe none. Maybe most of them. That's the annoying part about a silent bug: it leaves no trace.

What was actually broken

The checkout pops up in an overlay from Lemon Squeezy. Their script sets itself up when the page finishes loading.

My site is built with Next.js, and I had it loading that script after the page finished loading. So the script arrived late, missed its cue, and never set itself up. The button was wired to call something that didn't exist. And because the code politely checked "does this exist?" before calling it, it didn't crash. It just did nothing.

No error in the console that I ever saw. No failed payment in my dashboard. Nothing in my inbox. A dead button doesn't complain.

The only way anyone could buy during those 62 days was the checkout link inside my follow-up emails, which skips the button entirely.

The fix

Two changes in one component:

  1. Tell the script to set itself up the moment it loads, instead of waiting for a cue it already missed:
<Script
  src="https://app.lemonsqueezy.com/js/lemon.js"
  strategy="afterInteractive"
  onLoad={() => window.createLemonSqueezy?.()}
/>
  1. A fallback, so if the overlay still isn't there the button opens checkout in a new tab instead of doing nothing:
if (window.LemonSqueezy?.Url?.Open) {
  window.LemonSqueezy.Url.Open(url)
} else {
  window.open(url, '_blank', 'noopener')
}

The second one is the one that matters. A buy button should never be able to fail silently. If the fancy version breaks, the boring version should still take the money.

The habit that would have caught it

Click your own buy button. On the live site. After every deploy.

Not on localhost — the timing that broke mine only showed up in production. And not once at launch — every deploy can break it again.

If you're building with Claude Code, you can hand it the job:

Open my live site in a browser, click the buy button,
and tell me whether the checkout actually opens.

It takes a minute. I skipped it for 62 days.

What I did about it

Today I emailed everyone on my list. No clever subject line — "Sorry, the buy button was broken." I told them what happened, sent the working link, and asked the people who aren't interested to reply and tell me what they're stuck on instead.

I don't have results yet. If you signed up in May or June and tried to buy — sorry. It works now.

Watch instead

This one's also a 60-second video on TikTok →

More fixes like this, before they hit the blog

Free field guide

Fix problems before you hit them

The cheat sheet covers the commands, settings, and guardrails that prevent most of what this blog debugs. Free PDF, weekly tutorials after.