Image Description

Hello everyone,
Finally, I have some quiet time to write this post!
Let’s start from the beginning. 😄

I think you’ve got the idea behind all this—it’s all about writing, even if you feel like you have nothing to say.

I won’t hide it: you do need a bit of technical knowledge to make it happen, but it’s still quite simple.

This article is the first in a series of three articles describing how to set up an environment for creating blog posts in an automated way (note that I use this method to publish these articles!!).

By the way! There’s the manual way and the automated one. I’ll let you imagine which one is the best ;)

Before you can use the killer script (which I will provide later), you’ll need to install the necessary tools for it to work properly. That’s why, in this first post, we will go through the installation of Obsidian and Hugo, as well as their synchronization.

And remember, sooner or later you’re going to realize, just as I did, that there’s a difference between knowing the path and walking the path. #matrix #morpheus

Image Description

Step 1: Setting Up Obsidian for Writing#

Obsidian isn’t just a writing tool—it’s a creative companion that grows with your ideas.

Getting started is simple:

  1. Visit the Obsidian website and download the application for your operating system.
  2. Follow the installation prompts to set up the software on your device.
  3. Once installed, create your first “vault”—a folder where all your notes and files will be stored.
  4. Create a folder and give it a name (e.g., “Posts”).
  5. (optional) Right-click on the folder, select “Show in System Explorer”, and copy the folder’s path to save it for future use.

Step 2: Setting Up Hugo on Windows and Sync It with Obsidian#

Hugo is an excellent tool for static site generation, and when paired with Obsidian, it can streamline your blogging workflow. In this guide, we’ll walk through syncing Obsidian with Hugo, including how to copy posts from Obsidian to Hugo’s content folder and verify them.

1. Prerequisites#

a. Git:#
  • Download Git from git-scm.com and install it.
  • Verify installation:
git --version
b. Go (Golang):#
  • Download Go from golang.org and install it.
  • Verify installation:
go version

2. Download and Install Hugo#

- a. Download Hugo Binary:#
  • Go to the Hugo releases page and download the appropriate version for Windows (extended version recommended).

    Image Description

- b. Extract and Add Hugo to PATH:#
  • Extract the downloaded .zip file to a folder (e.g., C:\Hugo).
    • Add the folder to your system’s PATH:
      • Open Control Panel > System > Advanced System Settings > Environment Variables.
      • Under “System Variables,” select Path, click Edit, and add C:\Hugo.

Image Description

- c. Verify Installation:#
  • Open a terminal and run:
hugo version

You should see the installed version of Git, Go & Hugo :

Image Description

3. Create Your First Hugo Site#

Open a terminal and navigate to the folder where you want your site to reside:

cd C:\MyWebsites

Create a new Hugo site:

hugo new site my-first-site # Initialize a new project
cd my-first-site

Initialize a Git repository (optional but recommended):

git init # Initialize a local repository
git config --global user.name "Your Name" 
git config --global user.email "your.email@example.com"

4. Choose a Theme#

Browse Hugo themes at themes.gohugo.io Add a theme via Git:

Image Description

git submodule add https://github.com/<theme-repo>.git themes/<theme-name>
 echo 'theme = "<theme-name>"' >> hugo.toml

I chose this one :

Image Description

It looks like this :

Image Description

At this stage, you need to copy the script from [here](https://themes.gohugo.io/themes/hugo-theme-terminal/#how-to-configure to the hugo.toml and then modify it (if you wish). _Note : Please make sure to not to copy this part of the script :

Image Description

5. Customizing Hugo Settings#

You can modify the configuration file by running notepad hugo.toml. From there, you can customize the color scheme, enable or disable the centerTheme option, and modify the about and showcase URL’s in the main menu.

baseurl = "/"
languageCode = "en-us"
# Add it only if you keep the theme in the `themes` directory.
# Remove it if you use the theme as a remote Hugo Module.
theme = "re-terminal"
paginate = 5

[params]
  # dir name of your main content (default is `content/posts`).
  # the list of set content will show up on your index page (baseurl).
  contentTypeName = "posts"

  # ["orange", "blue", "red", "green", "pink"]
  themeColor = "orange"

  # if you set this to 0, only submenu trigger will be visible
  showMenuItems = 2

  # show selector to switch language
  showLanguageSelector = false

  # set theme to full screen width
  fullWidthTheme = false

  # center theme with default width
  centerTheme = true

  # if your resource directory contains an image called `cover.(jpg|png|webp)`,
  # then the file will be used as a cover automatically.
  # With this option you don't have to put the `cover` param in a front-matter.
  autoCover = true

  # set post to show the last updated
  # If you use git, you can set `enableGitInfo` to `true` and then post will automatically get the last updated
  showLastUpdated = false

[params.twitter]
  # set Twitter handles for Twitter cards
  # see https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started#card-and-content-attribution
  # do not include @
  creator = ""
  site = ""

[languages]
  [languages.en.params]
    languageName = "English"
    title = "re-Terminal"
    subtitle = "A simple, retro theme for Hugo"
    owner = ""
    keywords = ""
    copyright = ""
    menuMore = "Show more"
    readMore = "Read more"
    readOtherPosts = "Read other posts"
    newerPosts = "Newer posts"
    olderPosts = "Older posts"
    missingContentMessage = "Page not found..."
    missingBackButtonLabel = "Back to home page"
    minuteReadingTime = "min read"
    words = "words"

    [languages.en.params.logo]
      logoText = "re-Terminal"
      logoHomeLink = "/"

    [languages.en.menu]
      [[languages.en.menu.main]]
        identifier = "about"
        name = "About"
        url = "/about"
      [[languages.en.menu.main]]
        identifier = "showcase"
        name = "Showcase"
        url = "/showcase"

6. Prepare Your Hugo Site for Obsidian Integration#

Open the Hugo site folder in your terminal.

cd C:\MyWebsites\my-first-site

Locate the content folder inside your Hugo site directory. This is where Hugo looks for content.

7. Syncing Obsidian with Hugo#

To sync Obsidian notes with Hugo, you’ll manually or automatically copy Markdown files from your Obsidian vault to Hugo’s content folder.

a.Manual Method#
  1. In Obsidian, right-click the folder containing your blog posts and choose “Show in system explorer”.

    Image Description

  2. Copy the Markdown files you want to publish.

  3. Paste the files into the Hugo content folder:

C:\MyWebsites\my-first-site\content\posts
b. Automated Method with Scripts#

Create a .bat file (e.g., sync_posts.bat) with the following content:

robocopy "C:\Path\To\ObsidianVault\Posts" "C:\MyWebsites\my-first-site\content\posts" *.md /mir

Save the .bat file and double-click it whenever you want to sync your posts.

8. Verify Posts in Hugo#

Start the Hugo server to preview your synced content:

hugo server 

Visit http://localhost:1313 in your browser to ensure the posts appear correctly.

So far, we have seen how to take text that we have written in Obsidian and convert it into HTML code using Hugo, but what about images? If I want to capture an image and add it to my posts, how do I do that? Fortunately, I found this Python script (that I optimized to take into consideration the gif and jpeg images) on the YouTube channel NetworkChuck:

You’ll also need to install Python/Python3 :) Go to the official Python website: https://www.python.org/downloads/

Copy this code, save it as a file with a .py extension, and ensure it is placed within the directory structure of your Hugo site.

import os
import re
import shutil

# Paths (using raw strings to handle Windows backslashes correctly)
posts_dir = r"C:\Path\To\ObsidianVault\content\posts"
attachments_dir = r"C:\Path\To\ObsidianVault\"
static_images_dir = r"C:\MyWebsites\my-first-site\static\images"

# Step 1: Process each markdown file in the posts directory
for filename in os.listdir(posts_dir):
    if filename.endswith(".md"):
        filepath = os.path.join(posts_dir, filename)
        
        with open(filepath, "r", encoding="utf-8") as file:
            content = file.read()
        
        # Step 2: Find all image links in the format ![Image Description](/images/Pasted%20image%20...%20.png)
        images = re.findall(r'\[\[([^]]*\.(?:png|jpe?g|gif))\]\]', content)
        
        # Step 3: Replace image links and ensure URLs are correctly formatted
        for image in images:
            # Prepare the Markdown-compatible link with %20 replacing spaces
            markdown_image = f"[Image Description](/images/{image.replace(' ', '%20')})"
            content = content.replace(f"[[{image}]]", markdown_image)
            
            # Step 4: Copy the image to the Hugo static/images directory if it exists
            image_source = os.path.join(attachments_dir, image)
            if os.path.exists(image_source):
                shutil.copy(image_source, static_images_dir)

        # Step 5: Write the updated content back to the markdown file
        with open(filepath, "w", encoding="utf-8") as file:
            file.write(content)

print("Markdown files processed and images copied successfully.")

Make sure to change the paths according to your installation.

Conslusion#

Voilà, That’s it for today! I know it’s a lot of information, but it’s a necessary. In the second part, we will discuss the interaction between Hugo and GitHub to publish Hugo’s public folder to GitHub so that it can later be retrieved from the hosting site (for my part, I use Hostinger).

Have you ever struggled with managing your blog efficiently? This workflow saved me hours and might just do the same for you!

I hope you found this informative. If you have any comments, feel free to let me know by sending an email to: nazim@amfdigitalroute.com.