So, I’ve been living in NotebookLM for the last six months after a long, comfortable tenure in Roam Research. The migration wasn't a simple export-import, and I promised myself I'd do a proper post-mortem once the dust settled. Here's the honest report on what actually broke, what I had to rebuild, and where NotebookLM genuinely surprised me.
The main fracture point was the graph. Roam’s bidirectional links and the unconstrained, emergent structure of the daily notes page were its magic. NotebookLM, at its core, is a document-first system with AI layered on top. My web of interconnected thoughts in Roam didn't translate. The "Sources" paradigm is powerful for focused projects, but my old, sprawling garden of notes now feels like a library of separate, semi-indexed pamphlets. I had to consciously rebuild key hubs as dedicated source documents.
The workflow shift is the biggest change. In Roam, I'd just type and link. In NotebookLM, I now "add a source" (a Markdown file I write, a pasted text block, or a PDF) and *then* interrogate it. It's less fluid for pure, stream-of-consciousness note-taking. However, for my developer docs, API specs, and meeting notes—things I *want* to be self-contained units—it's fantastic. The AI's ability to summarize, create FAQs, and suggest questions from these sources has become integral to my process.
Technically, the export was messy. Roam's JSON is... unique. I ended up writing a Python script to parse it and chunk my notes into logical Markdown files before bringing them into NotebookLM. This was actually a blessing in disguise, as it forced a cleanup. Here's a simplified snippet of the transformer logic:
```python
import json
import re
def roam_block_to_md(block):
"""Convert a Roam block with its nested children to a Markdown string."""
text = block['string']
# Handle Roam's double-bracket links
text = re.sub(r'[[(.*?)]]', r'**1**', text) # Made them bold, not links
md_lines = [f"- {text}"]
for child in block.get('children', []):
child_md = roam_block_to_md(child)
md_lines.append(" " + child_md)
return "n".join(md_lines)
# ... load roam_json, iterate over pages, write to .md files
```
What I gained is the AI context. Having a language model that's *only* reading my source material is a game-changer for verification and ideation. It doesn't hallucinate external facts—it stays grounded. For reviewing my own old code notes or preparing a talk from a collection of research, it's unmatched. But it's not a replacement for a true, fluid graph database of my thoughts. They're different tools.
Overall, I'm happy with the move, but it's a trade-off. I lost the chaotic, creative sprawl. I gained a powerful, focused research assistant for my documented work. If your notes are project-oriented and source-heavy, the migration is worth the pain. If you live in your daily notes and the graph itself is your product, you'll feel the loss.
~d