2. Building an Obsidian -> Hugo GO Daemon
2. Building an Obsidian → Hugo Go Daemon
Imagine if your website had autosave. You jot down notes in Obsidian, and whenever you tag one with publish: true
or simply add #publish
, that note magically appears—beautifully formatted—on your public Lotus‑Docs site. Remove the tag, and the page vanishes. Nothing goes live instantly; every change waits patiently in a “draft” branch, giving you a chance to review before publishing. No command-line gymnastics, no tedious copy-pasting—just write, tag, and merge when you’re ready.
What Problems Does This Solve?
- Zero manual exporting: Your Obsidian workspace becomes the single source of truth for both private notes and public docs.
- No broken links: Internal links are only converted if the target note is also published, keeping your site tidy.
- Safety net: Every change is queued in a GitHub pull request, so you always approve updates before they go live.
- Automatic clean-up: Unpublish a note, and its page (plus any now-empty section) disappears automatically.
Building the Daemon
I decided to “vibe code” this project—spinning up Cursor AI and starting a new repo. I wrote a for Cursor to follow, then fed it to Claude in max mode for extra context. (Obsidian → Hugo Sync Daemon (Go) PRD) Impressively, the AI got about 90% right on the first try. The code worked with only a few bugs.
One early hiccup: every note was being sent to a pull request. A quick prompt tweak fixed that. We settled on a simple approach: the daemon copies notes marked as published in Obsidian over to Hugo, and then we decide when to push from the local dev repo. This keeps commit tracking clean and simple.
Another snag: a function was copying the entire vault path instead of just the relevant folder into content/docs
. Once we ironed that out, everything clicked.
A word of caution: This is “vibe coded”—I haven’t done a thorough code review. Use it at your own risk, and always back up your vault. You can find the code here: https://github.com/jacoblindqvist/obsidian-hugo-sync.
Running the Daemon as a Service
I want this daemon running quietly in the background, starting up automatically with my computer. Since I’m on Linux Mint, I’ll set it up as a systemd service.
First, place your compiled Go daemon in /usr/bin
:
sudo cp obsidian-hugo-sync /usr/bin/
Next, create the service file:
sudo nano /etc/systemd/system/obsidian-hugo-sync.service
Paste in the following:
[Unit]
Description=Obsidian Hugo Sync
After=basic.target
[Service]
ExecStart=/usr/bin/obsidian-hugo-sync --vault /home/joakim/vault/vault --repo /home/joakim/jacoblindqvist/
Restart=always
User=joakim
[Install]
WantedBy=multi-user.target
Save and exit (Ctrl + O
, then Ctrl + X
).
Reload systemd and enable the service:
sudo systemctl daemon-reload
sudo systemctl enable obsidian-hugo-sync
sudo systemctl start obsidian-hugo-sync
Check that it’s running:
sudo systemctl status obsidian-hugo-sync
And tail the logs if you want to monitor activity:
journalctl -u obsidian-hugo-sync -f
Final Thoughts (and a Warning)
While writing this post, I discovered a pretty serious bug—a race condition that caused a file to be deleted instead of published or unpublished. Not great! I’ve patched it, but this is a reminder: don’t trust this code blindly, and always back up your vault before experimenting.
I’ll keep updating the repo as I find and fix more bugs. Happy publishing!
Let me know if you’d like to expand or clarify any section further!