How I Built a No-Code PKM Stack That Mostly Works
1. Getting Notion and Readwise to Actually Talk Reliably
This looked good on paper. Readwise syncs your highlights, Notion accepts blocks, and there’s a “Sync to Notion” checkbox in Readwise that suggests it’ll just work. It doesn’t. Or more specifically: it sort of half works, half the time, and often ends in a pile of red error text that disappears if you reload the page.
I had my Kindle notes flowing fine, but Twitter highlights just wouldn’t show up. Turns out Readwise sends those separately in a batch, and if you hit a Notion rate limit (which isn’t surfaced anywhere), they silently fail. You have to go back to Readwise, toggle a specific Tweet off and on again, and then requeue the sync. Not intuitive.
A more stable solution: ditch the built-in Notion sync and use Zapier to pull highlights via the Readwise API into a controlled Notion database. Readwise’s API gives you publication type and URL, so you can tag highlights based on source — article, book, tweet — and assign them to separate databases. Bonus: you can filter out all your “highlighted the author’s name by accident because I sneezed” entries.
The biggest win was setting the Notion page creation to delay by 10 seconds in Zapier. Readwise sometimes sends incomplete metadata right away, then updates later. If your zap fires too fast, you get pages with missing titles that never fix themselves.
2. Tagging is useless until you pick one tagging logic and enforce it
I used to brainstorm tag hierarchies like “Topics > Subtopics > Sources” or “Project > Context > Sentiment”. It felt like progress. It wasn’t. Two weeks in, I had three separate tags for ‘GPT-4’, one in a field called ‘AI Tool’, another under ‘Tech Stack’, and a third as a raw inline #gpt4 tag.
The fix? I stole a practice from Obsidian — which encourages file-level thinking — and applied it in Notion using rollups and select fields. For any note coming in, I force one designated Topic select field to be chosen. No multi-tagging here. Either it’s about prompt engineering, or it isn’t. If it crosses into two topics? I make a second note.
Also: ban open-text tag fields. That’s how you end up with ‘machine-learning’, ‘machinelearning’, and ‘ml’ all pointing to different places. Notion databases choke on ambiguity.
Aha moment: When I added a Zap that auto-created a missing Select tag in Notion, it broke the schema silently. Turns out Notion’s API allows creating new options on the fly, but the GUI didn’t surface them — and my filtered views stopped working because the new tags weren’t valid filter options. Once I locked all tag options to a pre-defined list (updated manually), the views stopped disappearing every week.
3. Can you actually find your notes without using the search bar
The real test of a personal knowledge system isn’t how pretty the dashboard is — it’s whether you can land on a past idea without keyword search. This completely broke my initial system.
I had all notes flowing into a chronological inbox, which I then processed into ‘Projects’, ‘Topics’, or ‘Literature Notes’. But when I tried to find an old idea about interface patterns for AI writing assistants, I had no idea where it went. It wasn’t a project. It wasn’t tagged. It just… existed. Somewhere.
I ended up rebuilding around entry points instead. Each was a page with:
- A callout box with 3–5 anchor links
- A filtered linked database block showing tagged notes
- A note-to-self field (checkbox) for “Ready to present”
- And a non-filtered inline table so I could see what I was ignoring
This kind of visual redundancy helped a lot. When a new note got added and didn’t show up anywhere visible, it instantly felt off. Like I’d dropped it behind the cabinet instead of filing it.
Tiny bug: if you duplicate a filtered linked database view, Notion keeps the filter visible, but changes the backend query source. One of my topic dashboards ended up showing unrelated entries that technically weren’t assigned that topic — and I didn’t catch it until I saw a finance tip in my GPT tag page.
4. Handling duplicate notes and half-written outlines cleanly
There’s a subtle problem once you start clipping content from everywhere: multiple nearly-identical pages cobbled from the same source. One from Instapaper, another from Readwise, and a third created by hand when I thought I “just read something about this”.
Nothing got fully written, because I forgot I’d already started. These dupe notes don’t show up as duplicates unless you look closely. That’s why I built an automation in Make.com that reads recent Notion pages and checks their content blocks for similar headlines or URLs. It’s loose — trigram string matches — but good enough to warn me if two different pages both talk about “how prompt chaining handles hallucination control”.
Small side effect: got warned about duplicates every time I typed “AI” into anything. Fixed that by raising the dupe threshold and ignoring short words. Had to whitelist things like “GPT” and “LLM” because they triggered false flags constantly.
Also started using a “status” field for clarity, because the chaos was real. These were my options:
- Raw clip
- Summarized
- Rewritten
- Quoted in post
- Archived
Once a note hit “Rewritten”, I stopped editing it in place and created a separate page for longform. If that didn’t happen, I’d keep tweaking the same note forever and accidentally delete a line I needed 3 days later.
5. Why Airtable wasn’t the right interface even though it was faster
Airtable is fast. Reflection isn’t. I tried using Airtable as my main PKM hub because the filters were snappier than Notion, and the forms are slick. But I found myself writing shorter, less thoughtful notes — more like database entries than ideas. I’d forget a quote because I didn’t expand the field enough to remember how it felt to read that paragraph.
Actual click behavior mattered: in Notion, a full-width toggle callout can sit inline with your commentary. In Airtable, I’d have to open the cell in a modal, read the excerpt, close it again, then write.
So now Airtable is just metadata. I use it to track whether a note has been used in a workflow, post, or project. But the content lives in Notion — even if it’s slower — because editing inside the note lets things stick.
As a weird Airtable edge case: creating linked records via Zapier doesn’t let you apply a sorting preference on the fly, so newly-created child notes would clog the top of rollup fields with junk. I had to build a manual “sort on submit” trigger using a button field and Airtable automation to reorganize child entries chronologically.
6. What to do when browser extensions accidentally override formatting
I lost an entire day of highlighting because my Grammarly extension rewrote HTML tags coming from a Readwise clip before the content hit Notion. The code blocks came in wrapped in extra divs, broke line spacing, and ruined my database views. Nothing looked wrong until I tried to search by snippet — and every quote rendered as a single, long unbreakable line.
It took stupid-long to realize what broke it. I only caught it when I clipped the same article on a different browser and got a clean entry. The diff? My main browser used Grammarly and Momentum. Both of those injected scripts into my Readwise page and fiddled with invisible content.
Now I have a clipping browser: Brave, no extensions, and a profile named “PKM-only”. That’s where I import or approve anything before syncing it across platforms. I kept the clip-cleaner script inside a Make.com webhook that sanitizes Readwise clips before pushing them through. It rewrites quotes longer than 600 characters into nested callouts, to avoid the Notion “bug” where large blocks occasionally render empty preview text in gallery view.
“Why are half my highlights blank?” → because Notion can’t show preview text from deeply nested list items unless you manually un-nest them.
7. Automating inbox triage for incoming notes that explode your database
The inbox filled up faster than I could tag it, mostly because of forgotten automations. One day, a trigger misfired and pulled in around 40 old Kindle highlights from a book I’d already archived. They got added because I flipped Readwise’s sync status to ‘On’ for Kindle again — forgetting that this also re-queued archived entries.
Fixed by adding a state-check script in Make.com that checks for ‘last edited time’ in Notion before creating new entries. If the highlight already exists and hasn’t changed in two days, skip it. Also made a ‘Sync history’ log database with date stamps for each trigger so I could trace backward when something unwanted popped in.
Also started queuing daily review tasks with toggles: one for ‘Untagged entries’, one for ‘Review before writing’, and one that cracks open any note with a checked “Needs Readability Fix” field. Helped surface the weird ones like this:
Title: “Untitled Block”
Tags: ‘None’
Body:
““…that’s it. A floating quote mark. No idea where it came from, probably a misfired shortcut. Deleted with extreme prejudice.
8. Preventing link rot and blank embeds inside Notion references
After about three months, I had five or six notes whose embedded pages or webclip references turned into blank boxes. Not broken links — just inert. Turns out Notion strips iframe previews after a while if the embed source doesn’t declare CORS headers correctly. Linked tweets, especially, would go grayscale or vanish entirely once the original post was deleted.
The workaround I settled on was this:
- When adding a source, generate a plaintext backup using Zapier and store it in a separate ‘Archive’ property
- Grab the favicon and title manually if the embed fails
- If an embed dies, replace it with a native Notion bookmark block linking the archive note
That way, nothing just disappears. At worst it breaks pretty, not structurally. Also started adding a ‘Last seen valid’ date field to any embed. If it goes blank after that? I know exactly when it stopped working.
This only became necessary after I noticed a favorite LangChain article turned into a 404 a month after I’d clipped it — and all that remained in my database was a “connect to the internet to preview” message.