🎤 Speaking at KubeCon EU 2026 Lessons Learned Orchestrating Multi-Tenant GPUs on OpenShift AI View Session
Luca Berton
AI Engineering

ProteinLens: I Had 4,481,293 Lines of Code… Until I Stopped Counting node_modules

Luca Berton
#cloc#metrics#javascript#typescript#node-modules#monorepo#devops#cicd#vibecoding#copilot

I ran cloc . on ProteinLens and got the kind of number that makes you sit up straighter in your chair:

Line count, exceeded timeout: ./frontend/node_modules/playwright-core/lib/server/fetch.js

Nothing like a single dependency file timing out your line counter to remind you: you’re not measuring your product. You’re measuring the ecosystem.

So I reran it with the grown-up filter:

cloc . --exclude-dir=node_modules,dist,build,.next,out,coverage,.turbo,.cache

And suddenly the truth showed up:

Same repo. Same project. Two completely different realities.

This is a post-mortem about what those two numbers actually mean — and why they map perfectly to the experience of building an AI MVP on Azure with “weekend vibes” and production ambitions.


Two cloc runs, two stories

Story #1: “I built a monster”

The first run is the dopamine hit:

And it’s heavily dominated by JavaScript:

It’s also slow: 103 seconds and a timeout inside Playwright’s vendored code.

This is the “modern web app as a shipping container full of other shipping containers” experience.

Story #2: “Okay… here’s what I actually own”

The second run is what you should put in a blog post without lying to yourself:

And the language mix flips into something much more informative:

That’s the real system footprint. That’s the part where decisions matter.


What ProteinLens does (and why these numbers aren’t just vanity)

ProteinLens is simple on the surface:

Photo → recognition → estimated protein → structured result

But the goal wasn’t “it works once on my laptop.” The goal was: build an MVP that looks like a product:

Which is why the line count switch matters: it tells you whether you’re looking at your work, or your dependencies’ work.


Azure infrastructure overview

Current stack:

On paper, the services scale.

In practice, what scales (or fails) is the system you assembled out of them.


The first cloc run is what “vibe coding” feels like

When you build fast with modern tooling, everything expands:

That’s how you end up with:

It’s not bad. It’s just… not your product.

And it creates a very specific failure mode:

You start mistaking repo weight for engineering maturity

Bigger repo → feels serious → you relax Then the first real load shows up and reminds you: seriousness is retries, queues, observability, and guardrails — not LOC.


The second cloc run is what “product-shaped” actually looks like

After excluding the usual suspects (node_modules, build outputs, caches), the repo becomes readable:

That JSON number is the real “huh” moment.

Usually that means some combination of:

It’s not automatically wrong — but it’s the kind of thing that quietly drives:


A tiny Playwright timeout taught me a real lesson: metrics need boundaries

That first run failed on:

./frontend/node_modules/playwright-core/lib/server/fetch.js

Which is hilarious, but also perfect.

Because every engineering metric needs a scope:

If you don’t define the metric, the repo defines it for you.

And the repo will happily count 3.2 million lines of JavaScript you didn’t write.


What I learned (the honest version)

← Back to Blog