NotebookLM's answers are read-only. You can't edit them in place, which is annoying when the AI gives you a great summary with one wrong sentence. So I built a small thing: pull the answer into my extension, edit it freely, export it as Markdown. An afternoon, I figured. It took three rewrites, and every one was the same mistake wearing a different hat.
The mistake was reaching for innerText.
Version one: grab the answer element, read .innerText, drop it in a textarea. Done. Except the text came out shredded. Every few words there'd be a lone number on its own line — "1", then a comma on the next line, then "2", then a period. The answer was readable in the browser and garbage in my box.
The cause: those little citation markers in the answer — the superscript numbers you click to see the source — aren't styled text. Each one is a real element. And innerText treats a button as its own block, so every citation number got its own line, dragging the punctuation around it along too. My clean paragraph became a ransom note.
Version two: fine, I'll delete the buttons first. Clone the node, querySelectorAll the citation markers, remove them, then read innerText. The numbers vanished. And so did every paragraph break. The whole answer — headings, bullet points, sections — collapsed into one unbroken wall of text. Removing those nodes had changed how the browser computed line breaks around them, and innerText, which infers newlines from layout, lost the plot entirely.
That was the moment I should have caught on. I was two hacks deep patching the output of a function that fundamentally throws away the thing I care about: structure. innerText gives you what the text looks like flattened, not what it means. I kept trying to un-flatten a pancake.
Version three, the actual fix: stop using innerText. Walk the DOM myself. A small recursive function that goes node by node — text nodes get their text, block elements (headings, paragraphs, list items) emit a newline, list items get a "- " prefix, bold elements get wrapped in **, and citation markers get skipped entirely instead of mangled. I control the structure because I'm building it, not inferring it.
And here's the part that made the whole detour worth it: once you're walking the DOM yourself, formatting is basically free. I'd been planning to skip bold/heading preservation as "too much work." But when you're already visiting every node, adding "if this is bold, wrap it in stars" is one line. The recursive walker didn't just fix the newlines — it gave me real Markdown export, with headings and bold and lists intact, that renders properly in Obsidian or Typora. The feature I'd deferred came for free the moment I stopped fighting innerText.
One honest wrinkle I left in: inside the textarea you now see the Markdown source — literal bold and ## heading and - list. Looks a bit like code. I added a line under the box explaining why: the box shows Markdown on purpose, so the exported .md keeps NotebookLM's formatting. Better to explain the seam than to pretend it isn't there.
The lesson I keep paying tuition on: innerText is a trap for anything with structure. It's perfect when you want a dumb string and nothing else. The second you care about headings, lists, emphasis, or precise line breaks, it will fight you, and you'll lose in ways that look like small bugs until you realize they're the same bug three times. Walking the DOM feels like more work up front. It's less work than three rounds of patching a function that was never going to give you what you needed.
What's your "I should have rewritten it two versions ago" story?
— building NotebookBloom in public, #9
Top comments (0)