Hi there, a few months ago I decided, I would want to go to a form of webspace where I dont have to spend money. Although it’s only a few bucks, I thought it would be time to move on… this is basically a tutorial to move over to github pages…
Edit from 20-04-2025: Previously I had a Makefile-based approach, but this was not the ideal way, so now I changed it to utilize github actions instead
We start of with a tree view here to show how the pieces are screwed together:
sven@debian:~/development/hugo$ tree -L 2 . ├── config.toml ├── content │ ├── de │ └── en ├── public │ ├── 404.html │ ├── about │ ├── About _ Interdependent_files │ ├── agenda.png │ ├── book.min.a638a97f489029f3eda833b0905717d5a2da0b571423db855dd7ce4336238e77.css │ ├── categories │ ├── de │ ├── de.search-data.min.cc10ee5d6f454883af3d2c31576a2ad90ef1ecae0a79fd2f36e9af9fb3ff3c84.json │ ├── de.search.min.2adf38a9a0cb592541f5b8f227b9091ac117d1667e43dca86a4d336f453b4606.js │ ├── docs │ ├── drafts │ ├── en │ ├── en.search-data.min.b083db226cd7541947b6dd0fdf7a563f455a790763f341883dc37963899504c8.json │ ├── en.search.min.004100e27f248b7e46aef29f1b0ae4e8d53aed5c868e797c8696fa00f834cd5f.js │ ├── favicon.png │ ├── favicon.svg │ ├── flexsearch.min.js │ ├── fonts │ ├── index.html │ ├── index.xml │ ├── katex │ ├── Makefile │ ├── manifest.json │ ├── mermaid.min.js │ ├── pages │ ├── posts │ ├── sitemap.xml │ ├── svg │ └── tags ├── resources │ └── _gen └── themes └── hugo-book
As can be seen the public directory here is shown after the population, foremost we have config.toml (could also be just a .yaml, but somehow i started with toml, whatever it doesnt matter), then we see the content directory housing the different languages (here german, english) . then there is a resources directory containing generated assets. And last but not lrast, there is the themes dirctory, here including the hugo-book theme…
We start with the workflow file deploy.yml . My new setup looks like the following:
name: Build and Deploy Hugo Site on: push: branches: - main workflow_dispatch: permissions: contents: write jobs: build-and-deploy: runs-on: ubuntu-latest env: HUGO_VERSION: 0.146.6 TZ: Europe/Berlin steps: - name: Checkout repository (with submodules) uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 3 - name: Install Hugo run: | wget -O hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb sudo dpkg -i hugo.deb - name: Install Asciidoctor run: | sudo apt update sudo apt install -y ruby sudo gem install asciidoctor - name: Build Hugo site run: | hugo --gc --minify --cleanDestinationDir --config content/config.toml echo "--- Built site files ---" find public -type f | sort - name: Deploy to gh_pages branch uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh_pages publish_dir: public force_orphan: true user_name: wehrend user_email: sven.wehrend@gmail.com
and here for reasons of completeness the config.toml residing in the content directory…
baseURL = "http://wehrend.uber.space/" languageCode = "en-us" title = "Bits & pieces - Sven Wehrend" publishDir = "wehrend.github.io" [module] [[module.imports]] path = "github.com/alex-shpak/hugo-book" [languages.en] languageName = "English" contentDir = "content/en" weight = 1 [languages.de] languageName = "Deutsch" contentDir = "content/de" weight = 2 [[languages.en.menu.before]] name = "Web-Blog" url = "/posts/web/" weight = 10 [[languages.en.menu.before]] name = "Synth-Blog" url = "/tags/synth/" weight = 20 [[languages.en.menu.before]] name = "" url = "/docs/" weight = 10 [[languages.en.menu.before]] name = "Electronics 101" url = "/pages/prequel-short-introduction-to-electronics" weight = 26 [[languages.en.menu.before]] name = "Electronics 102" url = "/pages/short-introduction-to-electronics-102" weight = 27 [[languages.en.menu.after]] name = "Digital Logic 1 (Overview)" url = "/pages/overview/" weight = 20 [[languages.en.menu.before]] name = "Digital Logic 2 (Overview)" url = "/pages/overview2/" weight = 25 [[languages.en.menu.before]] name = "Synthesizer-DIY" url = "/posts/synth/25_build_your_own_modules/" weight = 26 [[languages.de.menu.before]] name = "Web-Blog" url = "/posts/web/" weight = 10 [[languages.de.menu.before]] name = "Synth-Blog" url = "/tags/synth/" weight = 20 [[languages.de.menu.before]] name = "" url = "/docs/" weight = 10 [[languages.de.menu.before]] name = "Elektronik 101" url = "/de/pages/prequel-short-introduction-to-electronics" weight = 26 [[languages.de.menu.before]] name = "Elektronik 102" url = "/de/pages/short-introduction-to-electronics-102" weight = 27 [[languages.de.menu.after]] name = "Digitale Logik 1 (Übersicht)" url = "/de/pages/overview/" weight = 20 [[languages.de.menu.before]] name = "Digitale Logik 2 (Übersicht)" url = "/de/pages/overview2/" weight = 25 [[languages.de.menu.before]] name = "Synthesizer-DIY" url = "/de/posts/synth/25_build_your_own_modules/" weight = 26 [params] date_format = "2006-01-02" # (Optional, default light) Sets color theme: light, dark or auto. # Theme 'auto' switches between dark and light modes based on browser/os preferences BookTheme = 'light' # (Optional, default true) Controls table of contents visibility on right side of pages. # Start and end levels can be controlled with markup.tableOfContents setting. # You can also specify this parameter per page in front matter. BookToC = false [security] enableInlineShortcodes = false [security.exec] allow = ['^dart-sass-embedded$', '^go$', '^npx$', '^postcss$', '^asciidoctor$'] osEnv = ['(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$'] [markup.asciidocext] extensions = ["asciidoctor"] workingFolderCurrent = true trace = true verbose = true [languages.en.markup] [languages.en.markup.goldmark] [languages.en.markup.goldmark.renderer] unsafe = true [languages.de.markup] [languages.de.markup.goldmark] [languages.de.markup.goldmark.renderer] unsafe = true [frontmatter.handlers] adoc = "yaml"
Thanks to the github-token documented here we even do not need to setup a key or token by using the default github_token which do not need any configuration, in case the github pages stem from the same repository. So I decided to ease my setup and throw away the parent directory respectively added the parent directory to the repository
With this setup you should be able to let hugo create the publishDir <user>.github.io AKA public folder which gets populated in the branch gh-pages.
If we commit and push our changes the build-and-deploy pipeline immediately begins to work and churn out the website for you in the background…
Congratulations, you just learned a way to contribute to the community and build a cornerstone on the shoulders of giants.