In my last post, I wrote about how an idle 2017 MacBook Pro triggered a weekend project where I bypassed managed hosting, learned SSH, and deployed my own web infrastructure on a VPS using Claude Code.
The next question for me was: how do you actually put this into use as an actual case study?
The result of that question was nami.space — my personal internet home. Not a portfolio (I have a separate site for that), not a brand site, and definitely not a newsletter funnel. It’s a living archive. A place to leave a record of what I notice: a technical writing essays, random non-performative thoughts, things that cannot go anywhere but here.
For a living archive to work, the barrier to publishing needed to be zero for me.
Friction: WordPress editor as publishing tool (or is this ‘me’ problem?)
WordPress is arguably the best CMS in the world for owning your own data. But actually writing in it? I struggled.
This has been my long standing friction point.
Logging into a dashboard, navigating to “Add New…” I don’t think anyone would use WordPress admin interface as a serious editor interface. I’m fairly certain people use Google docs, Word docs, etc. for real editing workflow.
Well. I don’t like writing in Google docs, Word docs, or Pages either.
I’ve been using Notion and I’m a big fan.
My needs are really simple: I just want to publish a quick, unpolished thought. I wanted to write where I naturally write (Notion) but keep the SEO, ownership, and structural benefits of WordPress.
So I questioned, “Is it possible to use Notion as editor but also CMS?” I wanted Notion to be my source of truth.
The developer term for this setup is “headless CMS.” The non-developer reality is that connecting Notion’s block API to the WordPress REST API usually requires writing a custom middleware application… the kind of thing that assumes you already know JavaScript, understand authentication headers, and can debug API responses.
I don’t know how to do any of that.
So I had Claude Code help me build one, using WordPress and n8n.
Firstly, what is n8n (and why self-host it)?
n8n is an open-source workflow automation tool like Zapier or Make, but you own the whole thing. You build workflows by connecting visual nodes on a canvas: a trigger here, an API call there, a code block in the middle. Each node does one job, and you wire them together into a pipeline.
What makes n8n different from Zapier is that you can self-host it. No monthly subscription tied to how many tasks you run. No vendor lock-in. No limits on executions. You install it on your own machine and it just runs.
My n8n is self-hosted on a 2017 MacBook Pro running Ubuntu. The same machine I wrote about in my last post.
This matters because the automation layer is usually where self-hosting projects fall apart. You build the site, you set up the server, and then you realize that connecting everything together requires either writing custom scripts or paying for a SaaS tool that charges per workflow run. n8n removes that trade-off. It gives you the visual builder of a managed service with the control of something you run yourself.
I should be clear: I didn’t set up n8n from scratch by hand. Claude Code helped me get it running in Docker on the MacBook, configure the Cloudflare tunnel, and troubleshoot the every little n8n issues I had like Notion and WordPress credential connections.
Site’s tech stacks
The site is built with a custom-coded WordPress theme (Tailwind CSS) by Claude Code.
I did lots of planning with Claude and mapped out everything: structure, contents, and how automation would work with WordPress x n8n in mind.
For this project, I am hosting the site on Pressable as I actually wanted to learn Pressable as product. But the publishing engine behind it has three layers:
- The editor: Notion. Where I actually write.
- The middleware: n8n, an open-source workflow automation tool I self-host on a home server.
- The destination: WordPress REST API, which receives the formatted content and publishes it.
My goal was simple: write anywhere, publish without copy-paste.
Workflow
If you looked at the n8n workflow, you’d see that it doesn’t just blindly push text from one place to another. It acts as an intelligent router: parsing, formatting, mapping, and syncing content between two systems that don’t natively talk to each other.
Here is exactly what happens when I trigger a publish.

Step 1: The status filter. The workflow starts with a webhook. When triggered, it queries my Notion database and looks for any page where the status property is set to “Ready to publish” or “Update.” If it finds one, it pulls the page ID and moves forward. If nothing matches, it stops.
Step 2: Parsing the blocks.
Notion doesn’t hand you clean HTML. It hands you a deeply nested JSON object where every paragraph, heading, and bullet point is its own “block,” each with its own structure, annotations, and metadata. A bold word inside an italic sentence inside a bulleted list? That’s three layers of nested objects just to render one line.
I had Claude Code write a custom JavaScript node inside n8n that loops through these blocks and translates them into clean, semantic HTML: <p>, <h2>, <ul>, <blockquote>, <pre><code>. It handles rich text annotations (bold, italic, strikethrough, inline code, hyperlinks) and wraps consecutive list items in proper <ul> or <ol> tags instead of leaving them as orphaned <li> elements. It even handles images with captions, converting them into <figure> elements.
No bloated divs. No inline styles. Just clean content ready for a minimalist theme.
Step 3: Dynamic taxonomy and routing. My site has distinct sections — Notes (technical fragments), Writing (longer essays), and Travel (random travel stuff). In WordPress, these are Custom Post Types, each with their own REST API endpoint.
I mapped a dropdown property in Notion to these post types. The n8n workflow reads that property and dynamically changes which API endpoint it targets: /wp/v2/notes versus /wp/v2/writing versus /wp/v2/travel.
Tags work the same way. A separate code node takes the Notion tags, checks whether each one already exists in WordPress, and if it doesn’t, creates it on the fly before assigning it to the post. No manual tag management across two systems.
Step 4: The round-trip writeback.
Once n8n successfully publishes the article to WordPress, it takes the generated WordPress Post ID and the live URL and writes them back into the original Notion row. Then it changes the Notion status to “Published.”
Why does this matter? Because that Post ID permanently links the Notion page to the specific WordPress post. If I notice a typo a week later, I fix it in Notion and change the status back to “Update.” The workflow sees the existing Post ID and sends the content to the same endpoint with the ID appended — updating the existing article instead of accidentally creating a duplicate.
One status toggle. No logging into WordPress. No copy-paste. No duplicates.
What my publishing flow actually looks like
- Open Notion on my phone or laptop.
- Write the stuff.
- Select the post type (Notes, Writing, or Travel)
- Change status to “Ready to publish.”
- I then click on the webhook link to trigger n8n workflow
Seconds later, it’s live on nami.space — formatted in my custom theme, tagged correctly, with the live URL written back to Notion so I can find it later.
I don’t log into WordPress to publish anymore. I don’t deal with the block editor or page builder settings. The design is locked safely in the theme files, and my content lives cleanly in Notion, which is where I already spend my time.

What I built vs. What I wrote
I want to be honest about the division of labor here, because I think it matters for anyone considering a similar setup.
I designed the system. I decided that Notion should be the editor, that content should flow through n8n, that WordPress should receive clean HTML via its REST API, that the round-trip writeback should prevent duplicates. I defined the content types, the taxonomy mapping, the status-driven triggers. (And I also did a lot of AI chatting to understand what needs to happen based on my vision of course.)
Claude Code wrote the JavaScript. The block parser that handles Notion’s nested JSON. The tag resolution logic that checks WordPress before creating new tags. The conditional URL construction that routes to the right API endpoint based on post type.
I don’t write codes. But I knew exactly what it needed to do, how the data should flow, and what the failure modes would look like. When something broke, I just feed error message that I don’t understand.
What mattered: I had some understanding of WordPress like Custom Post Type, concept of WP REST API, n8n, workflow automation, and general idea on how Notion → n8n → WordPress could look like.
But I absolutely didn’t know how WP Rest API needs to be set up, how authentication works with n8n for each node, or what sort of data processing was needed.
WordPress as the quiet foundation
There’s an irony in this setup that I want to name.
I built a pipeline specifically to avoid using the WordPress editor. And yet WordPress is the reason the whole system works. It provides the REST API that n8n talks to. It handles the content modeling — Custom Post Types, taxonomies, slugs, excerpts, publish dates. It generates the RSS feed, serves the pages, manages the theme layer that makes everything look the way I designed it.
I didn’t escape WordPress. I escaped the dashboard. The CMS underneath is still doing exactly what it’s always done — being a reliable, extensible foundation for publishing on the web. I just found a way to interact with it that matches how I actually think and write.
For anyone in the WordPress ecosystem: this isn’t a “WordPress is dead” story. It’s the opposite. WordPress becomes more valuable, not less, when you treat it as infrastructure instead of an interface. Its REST API turns it into a headless publishing engine that any automation tool can talk to. The editor is optional. The system is not.
Takeaway
I’ve always dreamed of an easy, accessible publishing flow. When I was in high school, I blogged every day. And it lasted as long as it did because my workflow was dead simple: write it in email (while I was on train), save as draft, hit send to publish. That was it. No dashboard, no formatting decisions, no friction between the thought and the page.
Email publishing still technically exists. But time changed, and my writing habit changed with it. What stayed constant was the desire: write somewhere comfortable, publish without thinking about the machinery.
This pipeline is my adult version of that high school email workflow. I write in Notion. I change a status. It’s live. The machinery is more complex: Notion blocks, n8n nodes, WordPress REST API, tag resolution, round-trip syncing. But the experience is just as simple. The complexity serves the simplicity, not the other way around.
I had a vision for this. I knew exactly what I wanted. And I had the means to communicate that vision to an AI clearly enough for it to build what I couldn’t build myself.
But I also know my own limitations. I didn’t take the path of building this from complete scratch: picking a programming language, choosing a framework, handling security practices for a stack I’ve never worked with. I would have gotten lost in decisions I’m not qualified to make, and so would the AI.
WordPress was the constraint that made this possible. Not despite being opinionated, but because of it. It gave Claude Code a clear structure to work within: template hierarchy, REST API conventions, content modeling, authentication patterns. AI could focus on solving my specific problem instead of reinventing the foundation.
I’m learning that AI-enabled modern web development isn’t about knowing how to code every integration. It’s about knowing how to direct the flow of your own information: understanding the concepts, seeing the moving parts, and having enough AI literacy to use these tools as genuine collaborators rather than magic boxes.
If you can describe a system clearly enough, you can build it. And if you’re honest about what you don’t know, you’ll choose the right constraints to build it within.