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
:
1#Requires AutoHotkey v2.0
2
3ObsidianToHugo() {
4 ; Update these paths to match your setup!
5 paths := {
6 obsidianBlog: A_MyDocuments "\Obsidian\\blog", ; Obsidian blog folder
7 hugoContent: A_MyDocuments "\Hugo\content\posts", ; Hugo posts folder
8 attachments: A_MyDocuments "\Obsidian\blog\attachments", ; Obsidian attachments folder
9 hugoImages: A_MyDocuments "\Hugo\static\images", ; Hugo images folder
10 hugoRoot: A_MyDocuments "\Hugo" ; Hugo project root folder
11 }
12
13 ; 1. Sync markdown files (excluding the attachments folder)
14 RunWait(Format('robocopy "{1}" "{2}" /MIR /XD "{3}" /Z /W:5 /R:3', paths.obsidianBlog, paths.hugoContent, paths.attachments), , "Hide")
15
16 ; 2. Process each markdown file in Hugo content folder
17 loop files paths.hugoContent "\\*.md" {
18 content := FileRead(A_LoopFileFullPath, "UTF-8")
19 newContent := content
20
21 ; Find and process image links like [Image](/images/image.png)
22 pos := 1
23 while pos := RegExMatch(content, "\\[\\[([^\\]]*\\.(?:png|jpe?g|gif))\\]\\]", &match, pos) {
24 imageName := match[1]
25 baseName := StrSplit(imageName, "/")[-1]
26
27 ; Copy image to Hugo static/images folder
28 sourceImage := paths.attachments "\\" baseName
29 if FileExist(sourceImage)
30 FileCopy(sourceImage, paths.hugoImages "\\" baseName, 1)
31
32 ; Update markdown link format
33 newContent := StrReplace(newContent, "[[" imageName "]]", "[Image](/images/" StrReplace(baseName, " ", "%20") ")")
34
35 pos += match.Len
36 }
37
38 ; Save changes if markdown content was updated
39 if (newContent != content) {
40 FileDelete(A_LoopFileFullPath)
41 FileAppend(newContent, A_LoopFileFullPath, "UTF-8")
42 }
43 }
44
45 ; 3. Preview the site with Hugo
46 RunWait("hugo server -D", paths.hugoRoot)
47
48 msg := MsgBox("Do you want to push changes to git?", "Push changes", "YesNo")
49 if (msg = "No")
50 return
51
52 ; 4. Commit and push changes with Git
53 RunWait("git add .", paths.hugoRoot)
54 RunWait('git commit -m "Update: Sync from Obsidian"', paths.hugoRoot)
55 RunWait("git push", paths.hugoRoot)
56
57}
58
59F1:: 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:
1name: github pages
2
3on:
4 push:
5 branches:
6 - main # Set a branch to deploy
7 pull_request:
8 workflow_dispatch:
9
10jobs:
11 deploy:
12 runs-on: ubuntu-20.04
13 steps:
14 - uses: actions/checkout@v2
15 with:
16 submodules: true # Fetch Hugo themes (true OR recursive)
17 fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
18
19 - name: Setup Hugo
20 uses: peaceiris/actions-hugo@v2
21 with:
22 hugo-version: 'latest'
23 # extended: true
24
25 - name: Build
26 run: hugo --minify
27
28 - name: Deploy
29 uses: peaceiris/actions-gh-pages@v3
30 if: github.ref == 'refs/heads/main'
31 with:
32 github_token: ${{ secrets.GITHUB_TOKEN }}
33 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! 🚀