Blog Publishing Workflow Using Claude Code
Part 1: Tutorial
The setup: I write in Obsidian. My blog runs on Hugo with the PaperMod theme, hosted on Netlify. I needed a way to go from markdown file → live on botharetrue.com with one command.
The solution: A bash script that syncs from my vault, converts Obsidian syntax to Hugo, handles images, commits to git, and waits for Netlify deployment.
Folder Structure
Source (Obsidian vault):
/Documents/VAULTS/the work (public?)/
├── ready to publish/ # Main posts go here
└── tech-notes/ # Tech tutorials (hidden from main feed)
Destination (Hugo blog):
/botharetrue-blog/content/
├── posts/ # Shows on homepage
└── tech-notes/ # Doesn't show on homepage (separate section)
The Command
~/HQ-Clean/Dev/publish-to-blog.sh
That’s it. One command.
What the Script Does
Finds new/updated files — Checks both
ready to publish/andtech-notes/for markdown files modified in the last 7 daysRoutes to correct destination — Files from
tech-notes/go to/content/tech-notes/, everything else goes to/content/posts/Converts Obsidian → Hugo syntax:
- Strips Obsidian frontmatter, adds Hugo frontmatter
- Converts
![[image.jpg]]→ standard markdown images - Converts Obsidian callouts → HTML
- Converts standalone YouTube URLs → Hugo shortcodes
- Removes wiki-style
[[links]]
Handles images — Finds images in my Attachments folder, copies to
/static/images/Validates YAML — Catches frontmatter errors before they break the build
Git commit + push — Auto-commits with a list of published posts
Waits for Netlify — Polls deployment status until it’s live (or fails)
Frontmatter Requirements
Minimal frontmatter needed:
---
title: "Your Post Title"
date: 2025-12-10
draft: false
---
The script auto-detects categories (e.g., adds reading category if post mentions books).
Hiding Posts from Main Feed
Two ways:
Put in
tech-notes/— Thehugo.tomlhasmainSections = ["posts"], so only/content/posts/shows on the homepageAdd frontmatter flag — Any post with
hiddenInHomeList: truegets filtered out (custom logic inlayouts/index.html)
Helper Scripts
The main script calls these for syntax conversion:
convert-callouts.py— Obsidian callouts → HTMLconvert-image-syntax.py—![[image]]→
Example Run
$ ~/HQ-Clean/Dev/publish-to-blog.sh
🔍 Checking for new or updated posts...
📝 Found files to publish:
✨ claude-code-chief-of-staff-workflow (new)
🔄 my-existing-post (updated)
Publish/update these posts? (y/n) y
📄 Processing: claude-code-chief-of-staff-workflow
✅ Published: claude-code-chief-of-staff-workflow.md
📦 Committing to git...
🚀 Pushing to GitHub...
⏳ Waiting for Netlify deployment...
Building... (5/60)
Building... (10/60)
✅ Deployment successful!
Live at: https://botharetrue.com
Part 2: Blog Post
I used to dread publishing.
Write the post — that’s the fun part. Then: copy to a new file, fix the frontmatter, convert my Obsidian image syntax, find the actual image files, copy those too, commit, push, wait, check if it worked, fix the thing that broke, push again.
Twenty minutes of friction for a five-minute post. Enough friction that posts would sit in drafts for weeks.
Here’s what’s both true: publishing should be trivial AND most publishing workflows are needlessly painful.
So I built a script. One command: publish-to-blog.sh. It finds new posts in my Obsidian vault, converts the syntax, handles images, commits to git, pushes to GitHub, and waits for Netlify to finish deploying. Then it tells me the site is live.
The whole thing is about 300 lines of bash. Not elegant. Not clever. Just: detect what changed, convert the format, move the files, push the button.
The unsexy truth about productivity systems: they’re usually just scripts that do the boring parts automatically. No AI required. No fancy apps. Just “I do this same sequence of steps every time, so I wrote it down in a way the computer understands.”
Now I write in Obsidian, run one command, and the post is live. The friction is gone. Which means I actually publish instead of letting drafts accumulate.
The best automation isn’t impressive. It’s invisible. You forget you ever had to do those steps manually.