I Built a Wall to Block Bots and the First Thing It Blocked Was Me
This morning I shipped what I was sure was the smartest thing I'd built all week.
By lunch it had taken down my own dashboard.
Let me back up.
The actual problem
If you read my last post you know the deal: most of the traffic hitting my landing pages isn't human. Last time I checked it was 80% bots.
I already had a Cloudflare Worker filtering them out. Worked fine.
Except there was a catch I never thought about.
Every bot request still hit the Worker.
Cloudflare's free plan gives you 100,000 Worker requests a day. And when bots are hammering you by the thousands, those fake requests burn your quota exactly like real ones do.
So I was basically paying — in quota — for the privilege of telling bots no.
That's backwards.

The fix that felt genius
Cloudflare has a thing called the WAF — the firewall that runs at the edge, before your Worker. Block something there and it never touches your Worker quota. Free.
So I moved all the bot rules up into the zone-level WAF.
One of those rules was this:
# Block path scanners. No real landing-page URL contains a dot.
http.request.uri.path contains "."
and http.request.uri.path ne "/favicon.ico"
and http.request.uri.path ne "/robots.txt"The logic is clean. Scanners probe for files. /wp-login.php, /.env, /backup.zip. Every one of those has a dot in it. A real landing-page URL is just /something — no dot, ever. So if the path has a dot, it's a scanner. Block it.
For a landing page, this rule is perfect.
Then I made it auto-apply to every domain in my account.

Five minutes later
I open my dashboard.
No CSS.
Just naked HTML. White background, Times New Roman, buttons stacked on top of each other like it's 1996.
I stared at it thinking the server died. Restarted Flask. Nothing. Cleared the cache. Nothing.
Then it hit me.

/static/dashboard.css
That has a dot in it.
My own rule — the one I wrote to block scanners probing for files — looked at my dashboard politely asking for its own stylesheet and went: "path contains a dot, that's a scanner, blocked."
The dashboard wasn't broken. My firewall was working flawlessly. On me.

Why it only hit the dashboard
Here's the part that's almost poetic.
The rule is genuinely correct for a landing page. LP URLs never have dots. A scanner asking for /xmlrpc.php on an LP is 100% hostile, every time.
But a dashboard isn't a landing page. It's an app. Apps load assets — .css, .js, .png, fonts. Dots everywhere. And every single one of them is legitimate.
Same rule. Opposite meaning. It depends entirely on what's sitting behind the domain.
I'd written a rule for one kind of site and bulk-applied it to a completely different kind.
The fix
Two parts.
First, stop the bleeding: strip the WAF rules off the two domains that serve the dashboard. Thirty seconds through the API. The CSS came back instantly.

Second, the actual cleanup: the dashboard had no business living on a domain that also runs landing-page defenses. So I moved it off entirely — onto its own subdomain on my business domain, far away from any LP bot rule.
Now the LP zones keep their wall. The dashboard lives somewhere those rules never run.
The bigger realization
The rule was never wrong. My blast radius was.
"Block anything with a dot" is genius for a landing page and suicide for an app — and I applied it to both, because I was thinking about traffic instead of thinking about what each domain actually does.
A defense that can't tell the difference between your enemy and your own infrastructure will eventually catch your own infrastructure.

Bot protection that blocks bots: good.
Bot protection that blocks your own CSS: still, technically, blocking something.
Funny how that works.