Lawtee News

Writing Hugo Blogs with StackEdit

Featured image of post Writing Hugo Blogs with StackEdit

Last year, I wrote an article titled Publishing Hugo Blogs on Mobile Using StackEdit. However, I haven’t used it much since then, mainly because I rarely update my blog on my phone. Additionally, I found another excellent solution called PageCMS (see: Using Pages CMS as a Hugo Blog Backend). That said, updating a blog smoothly on mobile remains quite troublesome, so some adjustments to the original method are necessary.


Previous Main Issues

  1. StackEdit Problems:

    • The primary issue was with image uploads. Hugo’s default directory structure places images in the same folder as the index.md file, but StackEdit defaults to a gallery mode, requiring images to be uploaded to a single designated folder. This often led to a messy directory structure.
    • Additionally, StackEdit operates on a local cache + online sync model. During synchronization, many cache files would appear in the target repository by default, and the high sync frequency put unnecessary strain on repository management.
  2. PageCMS Problems:

    • The editor’s support for touchscreen operations was poor. Both the rich-text and Markdown editors were prone to malfunctions.
    • Since PageCMS adapts to Hugo’s directory structure by modifying Hugo’s template image hooks, the uploaded image paths didn’t match the paths Hugo actually rendered. As a result, images often appeared as broken links (X) in the backend editor.
  3. VSCode Problems:

    • I previously used the web version of VSCode for writing, but its biggest drawback was also its poor touchscreen support. Text editing was particularly cumbersome—basic actions like copy and paste were difficult to perform on mobile.

Improvements

For mobile writing, the usability of the Markdown editor is paramount. In this regard, StackEdit naturally outperforms the other options. As for the earlier issues, I’ve reconsidered and believe they can be mitigated.

Setting Up Repository Sync

Instead of directly opening the Hugo repository in StackEdit, I switched to using Rsync to synchronize a specified directory.

For example, in the following workflow, I configured StackEdit to automatically sync files to the Hugo articles directory only when commits contain the message “new article.” This ensures that random edits in StackEdit won’t cause unexpected issues in the Hugo directory—effectively making it a manual commit process.

1. Create a Personal Access Token

In GitHub Settings → Developer settings → Personal access tokens:

  • Generate a new token (check repo and workflow permissions).
  • Note the token value (it will be needed later).

2. Add Secrets to the Source Repository

Go to the source repository stackedit-app-data → Settings → Secrets:

  • Add TARGET_REPO_TOKEN and enter the token generated earlier.

3. Configure GitHub Action in the Source Repository

Add the following sync code to .github/workflows/sync.yml in the source repository:

View Workflow Sync Code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
name: Conditional Sync Editor Content

on:
 push:
 branches: [master]
 paths:
 - 'content/editor/**'
 workflow_dispatch: # Allows manual triggering of the workflow 

jobs:
 sync:
 if: contains(github.event.head_commit.message, 'new article')
 runs-on: ubuntu-latest

 steps:
 - name: Checkout source repo
 uses: actions/checkout@v4
 with:
 path: 'src' # Explicitly specify the checkout directory 

 - name: Prepare target repo
 env:
 TARGET_TOKEN: ${{ secrets.TARGET_REPO_TOKEN }}
 run: |
 git config --global user.name "xx" # Replace with your main account 
 git config --global user.email "xx@live.com" # Replace with a verified email 
 git clone "https://oauth2:${TARGET_TOKEN}@github.com/h2dcc/lawtee.github.io.git" target-repo
 cd target-repo
 git pull origin master

 - name: Debug directory structure
 run: |
 echo "==== Source Directory ===="
 ls -lR $GITHUB_WORKSPACE/src/content/editor
 echo "==== Target Directory ===="
 ls -lR $GITHUB_WORKSPACE/target-repo/content

 - name: Sync files with rsync
 run: |
 rsync -av --delete \ 
 --exclude='.git' \ 
 --exclude='.github' \ 
 $GITHUB_WORKSPACE/src/content/editor/ \ 
 $GITHUB_WORKSPACE/target-repo/content/editor/

 - name: Commit & Push
 run: |
 cd target-repo
 git config --local user.name "xx" # Replace with your main account 
 git config --local user.email "xx@live.com" # Replace with a verified email 
 git add -A
 git diff --quiet && git diff --staged --quiet || (git commit -m "Auto-sync: ${{ github.event.head_commit.message }}" && git push origin master)

Handling Image Paths

Dealing with images in StackEdit is admittedly a bit cumbersome because the editor only displays Markdown files—other files are invisible. When I first tested it last year, I didn’t even know where the uploaded images went.

However, once you understand the logic, it’s straightforward:

  1. While writing a blog post, copy the path of the md file.
  2. When uploading images for the article, upload them to the same path.
  3. During upload, the images are temporarily stored in the browser. You need to manually remove the prefix path, leaving only the image filename. For example, after uploading, the editor might display:
    ![Input image description](/content/editor/2025-05-08-sync-hugo-by-stackedit/j8iIBbPM2YN4gs54.webp)
    This should be edited to:
    ![Input image description](j8iIBbPM2YN4gs54.webp)

Copy file path

Upload images to the same directory as the md file