Someone smart left me a comment months ago: the killer feature isn't the citations, it's page-level citations. NotebookLM hands you a chunk of a PDF, not a page. Map that chunk back to "page 23" while everyone else just says "somewhere in a 40-page pdf," and that's the thing researchers actually pay for. He called it the moat.
He was right that it'd be a moat. He was also, it turns out, describing something I couldn't build. Here's the week I spent finding that out, and why I think finding it out was the actual work.
I started convinced it was a scraping problem. NotebookLM shows you the source when you click a citation, so the page number must be in there somewhere, right? I just had to find the right element. Classic.
First I hovered a citation and a little card popped up with the exact quote from the PDF. No page number on it, but fine — maybe it's in the data behind the card. So I watched the network tab while clicking citations. The request that fired was 140 bytes. A hundred and forty. That's not a page number payload, that's a "user clicked citation 4" analytics ping. Dead end.
Then I thought: maybe the page number is in the big document-load response, just not shown in the UI. So I exported the full network log — 26 separate backend calls — and wrote a script to search every single response for anything that smelled like a page: pageNumber, pageSpan, numPages, boundingBox, all of it. Zero hits. Not one. What I did find, everywhere, was character offsets — "this quote starts at character 14037." That's how NotebookLM locates things internally. It flattened the PDF into one long string of text and threw the page boundaries away. The page number wasn't hidden from me. It doesn't exist on their side at all.
So the only way to get a real page number is to do it myself: get the user's original PDF, run it through pdf.js page by page, and match the quote text to find which page it landed on. Which sounds doable until you hit two walls. One, I'm not sure I can even get the original PDF — the user uploaded it to Google, not to me. Two, even if I could, the quote NotebookLM gives back is reworded, not word-for-word from the source, so my matching could confidently point at the wrong page. And "confidently wrong" is worse than "honestly vague" for the exact researchers I'm trying to win. Nothing kills a precision feature faster than it being imprecise.
That's the moment the honest move was to stop. Not because it's technically impossible forever, but because the cost is high, the payoff is uncertain, and — the part that actually matters — nobody is asking me for it yet. The commenter was giving me a strategy, not a bug report from a user. Building a hard, fragile feature for a demand that hasn't shown up is how solo devs disappear for three months and ship to silence.
So I built the version that was actually reachable. Click a citation, NotebookLM highlights the source passage on the left, and my extension grabs that passage — the quote, the source title, the character offset — and saves it as a citation you can export to APA, MLA, BibTeX, with the original text attached so you can verify it later. Not page-level. Passage-level. It does the thing researchers actually need most day to day — "did the AI make this up, or is it really in the source" — without the part I can't do reliably.
And there was a small, humbling bug in even that. My first version grabbed the hover card. Worked great in my head. Except the hover card vanishes the instant you move the mouse toward my panel to click Import. I'd written code for a flow that physically cannot happen. Only when I actually tried to use it, like a user, did I see it. Switched to grabbing the highlight that stays put after a click. Lesson I keep re-learning: test the gesture, not just the function.
I logged the page-number path in my roadmap with the full autopsy — why it's blocked, what I'd need, when it'd be worth revisiting. If a real researcher ever emails me "I need the page," I've already done the hard thinking and I'll know exactly what to try. Until then it stays a documented no, not a half-built maybe rotting in the codebase.
Is proving a feature can't be built a waste of a week? I don't think so. I now know exactly where the ceiling is, I shipped the useful 80% underneath it, and I didn't burn a month chasing the 20% nobody's asked for. Knowing what not to build might be the most underrated skill in this whole thing.
What's a feature you were sure you wanted, until you actually dug into what it'd cost?
— building NotebookBloom in public, #8
Top comments (0)