Do you write blog posts in Obsidian and want a seamless way to publish them using Hugo? With this AutoHotkey script, you can automate the process in just a few clicks!
This guide will help you:
- Sync Obsidian markdown files to Hugo.
- Convert image links automatically.
- Preview your site locally with Hugo before pushing changes to your live site
- Commit and push changes via Git.
Let’s get started!
Quick Setup
- Save the following code as
ObsidianHugoSync.ahk
:
#Requires AutoHotkey v2.0
ObsidianToHugo() {
; Update these paths to match your setup!
paths := {
obsidianBlog: A_MyDocuments "\Obsidian\\blog", ; Obsidian blog folder
hugoContent: A_MyDocuments "\Hugo\content\posts", ; Hugo posts folder
attachments: A_MyDocuments "\Obsidian\blog\attachments", ; Obsidian attachments folder
hugoImages: A_MyDocuments "\Hugo\static\images", ; Hugo images folder
hugoRoot: A_MyDocuments "\Hugo" ; Hugo project root folder
}
; 1. Sync markdown files (excluding the attachments folder)
RunWait(Format('robocopy "{1}" "{2}" /MIR /XD "{3}" /Z /W:5 /R:3', paths.obsidianBlog, paths.hugoContent, paths.attachments), , "Hide")
; 2. Process each markdown file in Hugo content folder
loop files paths.hugoContent "\\*.md" {
content := FileRead(A_LoopFileFullPath, "UTF-8")
newContent := content
; Find and process image links like [Image](/images/image.png)
pos := 1
while pos := RegExMatch(content, "\\[\\[([^\\]]*\\.(?:png|jpe?g|gif))\\]\\]", &match, pos) {
imageName := match[1]
baseName := StrSplit(imageName, "/")[-1]
; Copy image to Hugo static/images folder
sourceImage := paths.attachments "\\" baseName
if FileExist(sourceImage)
FileCopy(sourceImage, paths.hugoImages "\\" baseName, 1)
; Update markdown link format
newContent := StrReplace(newContent, "[[" imageName "]]", "[Image](/images/" StrReplace(baseName, " ", "%20") ")")
pos += match.Len
}
; Save changes if markdown content was updated
if (newContent != content) {
FileDelete(A_LoopFileFullPath)
FileAppend(newContent, A_LoopFileFullPath, "UTF-8")
}
}
; 3. Preview the site with Hugo
RunWait("hugo server -D", paths.hugoRoot)
msg := MsgBox("Do you want to push changes to git?", "Push changes", "YesNo")
if (msg = "No")
return
; 4. Commit and push changes with Git
RunWait("git add .", paths.hugoRoot)
RunWait('git commit -m "Update: Sync from Obsidian"', paths.hugoRoot)
RunWait("git push", paths.hugoRoot)
}
F1:: ObsidianToHugo()
How to Use
- Update Paths: Edit the
paths
section in the script to match your local directories. - Run the Script: Save the script as
ObsidianHugoSync.ahk
and execute it. - Use the Shortcut: Press
F1
to start “Sync to Hugo”
Example Directory Structure
Here’s what your file structure should look like for this script to work:
📁 Documents
├── 📁 Obsidian
│ └── 📁 blog
│ ├── 📄 post1.md
│ └── 📁 attachments
│ └── 🖼️ image1.png
└── 📁 Hugo
├── 📁 content
│ └── 📁 posts
│ └── 📄 post1.md
└── 📁 static
└── 📁 images
└── 🖼️ image1.png
Automating Deployment with GitHub Actions
For automated deployment, add the following .yml
file to .github/workflows/
in your Hugo repository:
name: github pages
on:
push:
branches:
- main # Set a branch to deploy
pull_request:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
# extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
Benefits of This Workflow
- Streamlined Process: Write in Obsidian, sync effortlessly to Hugo, and deploy to your live site.
- Automation: Reduce repetitive tasks like copying files or fixing image links.
- Preview First: Test locally with Hugo’s server before committing changes.
Conclusion
This AutoHotkey script and GitHub Actions workflow simplify your blogging workflow by integrating Obsidian with Hugo. Whether you’re a casual writer or a tech-savvy blogger, this setup ensures a smooth and efficient publishing experience.
Happy blogging! 🚀