Skip to main content

Image Hosting Migration: From Yuque to GitHub, Hand-Held Tutorial

⚠️ Maintenance status: historical reference

This tutorial was published in July 2025; tool interfaces and free quotas may have changed, and the flow is for reference only. For building a site today, we recommend 👉 AllinCMS. For topic ideas after the site is up, see Out of Ideas? Ask AI.

Continued from: for content and topic strategy after building a site, see Out of Ideas? Ask AI; today's recommended site builder is 👉 AllinCMS (the early tutorials are now historical reference).

In content creation and migration, we often hit a thorny problem: content exported from Yuque, Notion, and other note-taking platforms has image links protected by "hotlink protection". The moment you publish that content on your own site or blog, the images all break — you get the ugly "broken image" icon.

This article gives you the ultimate fix: use the powerful Markdown editor Story-Writer, paired with free and reliable GitHub as your image host, to bulk-migrate those protected image links in one click. The tutorial covers software installation, image host configuration, and live conversion — with detailed walkthroughs and screenshots for every pit beginners commonly hit. Follow along step by step and you'll get there.


1. Preparation: Download & Install

First, download and install Story-Writer. Pick the version for your OS.

Download links:

【Special note for macOS M-series chip users】 If you're on an ARM Mac (M1/M2/M3), download the osxarm version. If it won't launch, open Terminal and run:

# Assuming you put the extracted folder in Downloads
cd /Users/your-username/Downloads/Story-writer-osxarm
xattr -cr ./Story-writter.app

This command removes the macOS quarantine attribute and lets the app run. The rest of the install is the same as any other app — skipping the details.


2. Basic Setup: Optimize Your Editing Experience

To make it easier to observe Markdown source and preview side-by-side, we recommend disabling Story-Writer's default WYSIWYG mode.

  1. Open Story-Writer. In the status bar at the bottom of the editor, find and click "Modify editor config".

    Story-Writer editor with the bottom popup menu highlighting Modify Editor Config, switching to code on the left and preview on the right

  2. In the config popup, uncheck "WYSIWYG".

    Story-Writer editor config panel highlighting the unchecked WYSIWYG option while the right pane still previews

Now your editor shows Markdown source on the left and live preview on the right — the classic layout. This helps a lot when checking whether image links got correctly replaced.


3. Core Configuration: Binding the GitHub Image Host

This is the most critical — and most error-prone — step in the whole flow. We'll set up GitHub step by step, then bind it into Story-Writer.

Step 1: Open the Story-Writer Binding Settings

  1. Click the gear icon in the bottom left of Story-Writer to open Settings.

    Story-Writer main screen with the upper-left logo circled and an arrow pointing to it for opening the options

  2. In the settings menu, go to "Storage" → "Bind".

    Story-Writer settings panel with the Bind entry circled in the left menu

  3. In the image hosts list, find and click githubimg to configure.

    Story-Writer third-party binding panel with the image-host service area circled, listing Aliyun OSS, githubimg, imgur, Tencent Cloud OSS and more, with githubimg selected as the example

Step 2: Get a GitHub Access Token

The Token is like a password for Story-Writer to access your GitHub repo — keep it safe.

  1. On the githubimg config screen, click the link next to token — it takes you to GitHub's Token generation page.

    Story-Writer GitHub image-host binding form with name, token, repository, and branch fields, an arrow pointing to the apply-for-token link at the bottom

  2. Log into your GitHub account (Google sign-in supported).

    GitHub sign-in page with email and password filled and the green Sign in button (account masked)

  3. On the "New personal access token" page, configure as follows:

    • Note: name this Token for easy identification, e.g. storywriter-token.
    • Expiration: set validity. Recommended "No expiration" or a long duration.
    • Select scopes: most important step! You must check repo, which automatically includes all sub-permissions.

    GitHub new personal access token page with the note filled as Story-Writer, expiration set to No expiration, and the repo scope checked

  4. Scroll to the bottom, click "Generate token".

    Bottom of the GitHub token scope list with the green Generate token button

  5. Copy and save the generated Token immediately! It's shown only once — once you leave the page, you can't see it again.

    GitHub token created page with the ghp_ token circled (masked) and a prompt to copy and save it immediately

Step 3: Create and Initialize a GitHub Repo

This repo will be your online image storage.

  1. On GitHub, click the "+" in the top right, choose "New repository", or go directly to github.com/new.

    GitHub token page with New repository circled in the plus menu for creating a repository

  2. Set the repo info:

    • Repository name: name the repo, e.g. nibaba.
    • Public/Private: must select Public, otherwise the images can't be accessed externally.
    • Click "Create repository".

    GitHub new-repository page with the name set to nibaba, visibility set to Public, and Create repository at the bottom

  3. Repo created successfully.

    GitHub repository home showing apan-tony/nibaba with a Public badge, confirming creation

  4. 【Critical pit-avoidance】Initialize the repo. A newly created empty repo can't be used directly — Story-Writer will error. We must create a file in it to initialize. The simplest way is to create a README.md.

    • Click "creating a new file" or "Add a README file" on the page.

    GitHub empty-repository page with the README link circled in the Quick setup area, prompting to create a README file

    • The filename defaults to README.md — no need to change. Click "Commit changes..." top right, then click "Commit changes" again in the popup.

    GitHub README editor with the filename prefilled, committed via Commit changes

  5. Initialization complete. Note: the repo's default branch is now main.

    GitHub repository file list showing README.md with its commit, confirming the repository is initialized

Step 4: Finish Configuration in Story-Writer

Now back to Story-Writer's githubimg config screen, fill in the info you've prepared.

Story-Writer GitHub binding form filled in: token masked, repository nibaba, branch master, and the filename rule changed to /img/

  • token: paste the Token you just generated on GitHub (usually starts with ghp_).
  • Repo: fill in your repo name, e.g. nibaba.
  • Filename generation rule: recommend /img/{{filename}} — all images will go into the img directory in the repo, easier to manage. Avoid Chinese paths.
  • 【Critical pit-avoidance】Corresponding branch: change the default master to main, matching the branch name you see on GitHub.

Step 5: Common Issues & Fixes

If you hit errors during config or testing, 99% of the time it's one of these two causes:

  • Error 1: Repo not initialized (409 Conflict Error) If you skipped repo initialization, you'll see a 409 error during testing:

    {"path":"/repos/apan-tony/nibaba/git/refs/heads","request":{"dataType":"json"},"error":409}

    Story-Writer binding form showing a 409 error popup about an uninitialized repository, requiring README initialization first Fix: go back to GitHub, follow Step 3 to create a README.md in the repo.

  • Error 2: Branch name mismatch If your branch is main but you filled master in Story-Writer, you'll see this error: Story-Writer binding form erroring that branch master cannot be found, with the branch field circled and a note that the real branch is main Fix: in Story-Writer's githubimg config, change "Corresponding branch" from master to main.

Step 6: Activate & Test the Image Host

  1. Once config is clean, go back to "Bind" page, check githubimg to make it the current default image host.

    Story-Writer image-host list with the github host row checked as the default host and other services disabled

  2. Close settings and return to the main editor view.

    Close the binding window with the X button, then click the red-boxed area to return to the editor

  3. Test paste-upload: take any screenshot, then in Story-Writer's editor press Ctrl+V (or Cmd+V) to paste. If the image link auto-converts to a raw.githubusercontent.com URL — congrats, image hosting is configured!

    Three-step Story-Writer test: take any screenshot, paste with Ctrl+V to get a GitHub link, and a successful right-side preview confirms the setup


4. The Real Deal: One-Click Bulk Migration

Everything's ready — let's execute the final conversion.

Step 1: Find the "Image Host Transfer" Feature

  1. First, paste the full Markdown you copied from Yuque (or wherever) — the one with the old image links — into Story-Writer's editor.

  2. In the editor's top menu bar, find and click "Image Host Transfer".

    Story-Writer top toolbar with the Image Host Transfer button circled

    【Tip】 If you don't see this menu bar, you may be in "tab mode". Click "Toggle tab mode" in the top left.

    Story-Writer top Toggle tab mode button circled; click it when the editing menu is not visible

    Once toggled, you should see the "Image Host Transfer" button on the right.

    Toolbar in tab mode with the toggle circled on the left and the Image Host Transfer button circled on the right

Step 2: Execute the Conversion

We'll use this snippet with Yuque image links (cdn.nlark.com) as an example:

![Amber two-compartment rectangular glass food container with a diagonal divider](https://cos.files.maozhishi.com/data/web/web-files/img/1753201459682-632743aa-d982-4443-a0d9-de48452e33c3.png)
<font style="color:#FF0000;">Product code HY-001</font>
![Rectangular two-compartment amber glass food container (1040ML)](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460043-e8373b48-adbc-4c52-ad29-f1f3835d5dae.png)<font style="color:#FF0000;">Product name: Rectangular glass food container (2 compartments) (1040ML)</font>
<font style="color:#FF0000;">Capacity: 1040ML</font>
![Amber three-compartment rectangular glass food container](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460403-cdc4a3bf-925a-4d33-a61a-d17e5f569df9.png)
<font style="color:#FF0000;">Product code HY-003</font>
<font style="color:#FF0000;">Product code HY-004</font>
![Round amber glass food container (960ML) with a diagonal divider](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460699-9fc9706a-dcf9-40cd-a381-1f88dab442e8.png)<font style="color:#FF0000;">Product name: Round glass food container (2 compartments) (960ML)</font>
<font style="color:#FF0000;">Capacity: 960ML</font>
  1. Paste this into Story-Writer, click "Image Host Transfer".

    Story-Writer editor with Yuque-hosted content pasted in and the Image Host Transfer button circled in the toolbar

  2. In the "Network Image Address Conversion" popup, check "Select all" in the top right, then click "Convert" at the bottom. The "Converted address" column is empty for now.

    Conversion popup with all images checked, the image host set to github, and the Convert button highlighted

  3. Wait patiently. Story-Writer will start downloading the original images and uploading them to your GitHub repo — the popup shows "Processing...". Don't do anything during this process.

    Conversion window showing Processing (1/4) progress with a note not to operate during processing

Step 3: Verify the Results

  1. Once conversion completes, the "Converted address" column fills in with new GitHub URLs. Click "Confirm".

    Conversion complete with a new-host URL generated for every image; click Confirm to apply the replacement

  2. Back in the editor, you'll see every image link in the body has been successfully replaced!

    Editor body with all image links replaced by the new host address and the right pane previewing correctly

The converted content looks like this — image links now point to stable, hotlink-free GitHub URLs:

![Amber two-compartment rectangular glass food container with a diagonal divider](https://cos.files.maozhishi.com/data/web/web-files/img/1753201459682-632743aa-d982-4443-a0d9-de48452e33c3.png)
<font style="color:#FF0000;">Product code HY-001</font>
![Rectangular two-compartment amber glass food container (1040ML)](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460043-e8373b48-adbc-4c52-ad29-f1f3835d5dae.png)<font style="color:#FF0000;">Product name: Rectangular glass food container (2 compartments) (1040ML)</font>
<font style="color:#FF0000;">Capacity: 1040ML</font>
![Amber three-compartment rectangular glass food container](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460403-cdc4a3bf-925a-4d33-a61a-d17e5f569df9.png)
<font style="color:#FF0000;">Product code HY-003</font>
<font style="color:#FF0000;">Product code HY-004</font>
![Round amber glass food container (960ML) with a diagonal divider](https://cos.files.maozhishi.com/data/web/web-files/img/1753201460699-9fc9706a-dcf9-40cd-a381-1f88dab442e8.png)<font style="color:#FF0000;">Product name: Round glass food container (2 compartments) (960ML)</font>
<font style="color:#FF0000;">Capacity: 960ML</font>

That's it — you've migrated every image to your own image host. This polished Markdown "raw material" is now safe to hand to AI for further polishing, or to publish directly to your site and blog.