Plain text won. I migrated my notes from Notion to Markdown and lost more than I expected
A 48-page school notebook is basically indestructible. You can get it wet, fold it, drop it, lend it, take it to another country, open it 30 years later. It doesn't need WiFi, it doesn't ask you to upgrade your plan, it doesn't silently "migrate" your data to a new format without telling you. And if someone steals it, you know exactly what you lost.
Plain text is that. A .md file is a notebook. Notion is a smart building with sensors on every door.
The Hacker News thread "Plain text has been around for decades and it's here to stay" hit 99 points last week and triggered a discomfort I couldn't name right away. Not because I disagree — I mostly agree. But because I had 1,847 pages in Notion and hadn't moved a finger.
So I did it. Three days. My own script. Uncomfortable result.
Migrating Notion to plain text Markdown: the real process, no romanticizing
Notion has an official export feature. You export everything as Markdown + CSV, it downloads a .zip, done. In theory.
In practice, the zip I downloaded had this structure:
My Workspace/
├── Projects 2024 abc123def456/
│ ├── Backend Railway abc789/
│ │ └── Deploy notes abc789.md
│ └── ...
├── Technical Snippets bcd234/
│ └── ...
└── ...
Every folder with a UUID glued to the name. Every .md file with broken property blocks, images referenced as Untitled abc123.png, and internal links pointing to https://www.notion.so/long-UUID — meaning dead links if you're not logged in.
I wrote a script to clean that up:
#!/bin/bash
# clean-notion-export.sh
# Renames folders by stripping Notion UUIDs
# and normalizes names to kebab-case
find . -type d | while read dir; do
# Pattern: name with UUID at the end (32 hex chars)
new=$(echo "$dir" | sed 's/ [a-f0-9]\{32\}$//' | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
if [ "$dir" != "$new" ]; then
mv "$dir" "$new" 2>/dev/null
fi
done
# Clean orphaned image references in .md files
find . -name "*.md" -exec sed -i \
'/!\[.*\](Untitled.*\.png)/d' {} \;
echo "Done. Manually review internal links."
That last echo is the honest part of the script. Internal links — references between Notion pages — are unrecoverable automatically. You either fix them by hand or lose them.
I had 214 internal links. I manually recovered 31. The other 183 became plain text pointing nowhere.
What I actually lost (it wasn't what I thought)
Before I started, I assumed I'd miss the databases, the calendars, the kanban views. I was partly right. But what hurt most was something dumber.
1. The relationship graph
In Notion I had a projects database related to a code snippets database related to an architecture decisions database. Each row could have a Relation to another table. It was my private knowledge graph.
In Markdown, that graph doesn't exist. You can simulate relations with [[double bracket]] links if you use Obsidian. But if you use Zed, VSCode, or just cat, those links are text. The graph only exists if the editor reads it.
My thesis on this: I didn't lose the graph — I never had it. Notion had it. I was a user of something Notion built on top of my data.
2. Version history
Notion saves history. Pure Markdown doesn't. For version history in plain text you need Git — which is technically superior but adds brutal friction for quick 11pm notes.
I ended up with this:
# alias in my .zshrc to save notes fast
# without thinking about commit messages
alias note-save='cd ~/notes && git add -A && git commit -m "$(date +%Y-%m-%d\ %H:%M)" && cd -'
It works. But it's friction that Notion was absorbing silently. Honest take: what I lost here was convenience, not capability.
3. Third-party embedded images
I had screenshots pasted directly into Notion. Architecture diagrams built with the internal editor. Complex tables with formulas.
Tables export as Markdown tables — fine. Formulas, not fine: they export as plain text with the value calculated at the moment of export, not as a live formula.
Embedded screenshots survive if you uploaded them yourself. If you used copy-paste directly from the clipboard — and I did it all the time — Notion saved them on their CDN with URLs that are now private. I lost around 40 images.
What I did NOT lose and expected to:
- Writing speed — same or better in
nvim - Search —
grep -r "term" ~/notes/is faster than Notion search - Offline access — infinitely better
- Privacy — my own data, my own server, zero telemetry
And here's where the real discomfort starts.
My thesis: plain text is the right answer to the wrong question
The HN post celebrates plain text like it's an ideological victory. I get the impulse — especially after what Notion exposed with editor emails on public pages a few weeks ago, the migration feels obvious.
But I noticed something during those three days of migrating: I was using Notion mainly to feel organized, not to be organized.
The pretty dashboard, the kanban views, the emoji icons per page — they were a productivity interface that gave me a sense of control. When I moved to Markdown, that feeling disappeared. But the projects kept moving forward exactly the same.
So the right question isn't "plain text or Notion?" The question is: what are you actually using your note system for?
If you use it as a technical knowledge base with search, versioning, and offline access: plain text wins without argument.
If you use it as a collaboration tool with a team, relational databases, and shared forms: Notion is still superior.
If you use it to feel organized: the problem isn't the tool.
I was falling into all three categories at the same time. The migration forced me to separate those layers.
Common mistakes when migrating Notion to Markdown
Mistake 1: Exporting everything and assuming it's clean
Notion's export is a starting point, not a destination. The UUIDs in folder names, the broken links, the orphaned images — that's unavoidable manual work. No script fixes all of it.
Mistake 2: Replicating Notion's structure in folders
Notion tempts you into deep hierarchies: Work > Projects > Backend > 2025 > Q2 > Sprint 3. In plain text that becomes a navigation nightmare. The alternative that worked for me: flat structure + tags in YAML frontmatter + grep.
---
# frontmatter in each note - indexable with grep or fzf
tags: [backend, railway, deploy]
date: 2025-07-14
project: api-gateway
---
## Deploy on Railway — issue with environment variables
...
With grep -r "railway" ~/notes/ --include="*.md" -l you find everything in under a second.
Mistake 3: Chasing "Obsidian vs pure plain text" on day one
Obsidian adds a layer of features on top of .md files. It's the most popular solution. But diving into its plugin ecosystem on day one of the migration is noise. I used nvim for two weeks before deciding if I needed anything more. The answer was: almost nothing.
Mistake 4: Ignoring repository security
My notes have config snippets, architecture decisions, internal service names. Putting them in a private Git repo on GitHub is fine — but it's your own data on someone else's infrastructure, same as Notion. If privacy is your reason for migrating, the repo needs to be local or on your own VPS. This connects directly to the trust surface problems I analyzed in the post on supply chain attacks: the weak link isn't always the software, sometimes it's where the data lives.
Mistake 5: Migrating everything at once
I migrated 1,847 pages in one shot. That was a mistake. 60% of those pages I hadn't opened in the past year. The right strategy: export what's active first, see if the workflow holds up, then decide what's worth pulling from the archive.
FAQ: Migrating Notion to plain text Markdown
Can I migrate Notion to Markdown without losing anything?
No. Notion's official export preserves text and basic tables, but internal links between pages, images pasted from clipboard, database formulas, and table relations have no direct equivalent in plain Markdown. You can recover most of the textual content, but the relationship graph and database functionality are gone. The honest question is whether you were actually using those features or they were just sitting there.
What tool do I use to read Markdown after migrating?
Depends on what you need. For technical writing and speed: nvim with the render-markdown.nvim plugin that renders in terminal. For something more visual with a link graph: Obsidian. For integration with development workflows: VSCode or Zed have native preview. I ended up with nvim for 90% of things and Obsidian when I need to see connections in the graph.
Is it worth migrating if I work in a team?
Probably not, or not entirely. Plain text shines as a personal and technical knowledge base. For real-time collaboration, shared forms, and databases with per-user permissions, Notion or Confluence are still more practical. What is worth doing: separating personal notes (plain text) from collaborative documentation (Notion/Confluence). They're not mutually exclusive.
How do I handle versioning without Notion's history?
Git. No excuses. A git commit with a date and time as the message is enough for personal notes. If you want something friendlier, git-journal or the alias I showed earlier work fine. The cost is upfront friction; the benefit is offline history, branching for experiments, and readable diffs. Notion charged for history on higher plans; with Git it's free and more powerful.
Where do I store images and attachments?
Depends on volume. For a few files: an /assets folder next to each note or section. For many: your own storage (Cloudflare R2, Backblaze B2, or just a directory on a VPS) with relative paths or your own URLs. What I don't recommend: staying dependent on Notion CDN URLs — those URLs are private and expire or change without notice.
What about Notion databases — is there a plain text equivalent?
There's no exact equivalent. The closest thing is YAML frontmatter in each file plus a script that indexes them. With fzf, ripgrep, and a bash script that parses the YAML you can build something functional in an afternoon. Projects like nb or zk formalize that pattern. But if your Notion database usage was heavy — cross-table relations, rollups, forms — you're going to miss it. No way to sugarcoat that.
Conclusion: I stayed with plain text, but with eyes open
Three weeks after the migration, my technical notes live in ~/notes/, versioned with Git, edited in nvim, searched with ripgrep. The workflow is faster for writing and searching. The privacy is real, not promised.
But I'm not going to romanticize it: I lost things. I lost 183 internal links. I lost 40 images. I lost the relationship graph that Notion was maintaining. I lost the feeling of having a pretty dashboard.
What I gained was clarity about what I was actually using and what was productivity decoration.
My final position, no softening: plain text is the right infrastructure for personal technical knowledge. It's to notes what Docker is to deployment — portable, predictable, no hidden dependencies. I've written about how async agents create observability problems that are invisible until you measure them (here's the analysis of my logs); the same principle applies here: if you can't read your data with cat, you don't really know what you have.
What plain text is not: the answer to whether you're organized. That's a different conversation, and it has nothing to do with the file format.
If Notion is making you uncomfortable after what we've seen with the privacy issues, migrate. But do it with realistic expectations, not with the fantasy that plain text fixes the root problem. The root problem is you and what you want to do with that knowledge.
Same thing that happened to me with TypeScript back in 2018: the resistance was mine, not the language's. But once you adopt it for the right reasons, you don't go back.
Are you in the middle of a similar migration? Or convinced that Notion is worth every cent? I want to know what you lost — or what you found on the other side.
This article was originally published on juanchi.dev
Top comments (0)