Build a Blog with Hugo
2024-07-13
- OS: macOS Ventura 13.2.1
- Hugo site directory: ~/Desktop/blog
- Hugo theme: hugo-ivy
Hugo - getting started
-
Install Hugo from Homebrew
brew install hugo hugo version
-
Create a site skeleton
cd ~/Desktop hugo new site blog
-
Get a theme met your taste
cd blog git clone https://github.com/yihui/hugo-ivy themes/hugo-ivy
To view the exampleSite (if it exists) of your selected theme
hugo server --source themes/hugo-ivy/exampleSite --themesDir ../../
-
View and configure the site
- Copy the configuration file config.yaml (in my case) and the folder content from
themes/hugo-ivy/exampleSite to the Hugo site directory (Ref1, Ref2)
rm hugo.toml \cp -r themes/hugo-ivy/exampleSite/config.yaml themes/hugo-ivy/exampleSite/content ./
- Nevigate the address http://localhost:1313/ in your browser after
running1
hugo server -D -F --navigateToChanged
- Play with the config.yaml to see what would happen in your site
- Copy the configuration file config.yaml (in my case) and the folder content from
themes/hugo-ivy/exampleSite to the Hugo site directory (Ref1, Ref2)
-
Add new pages
Play with the Markdown files in the content directory
-
Publish the site using Github
- Create a new repository in Github with name <user>.github.io (in my case, dwla.github.io)
- Change the baseurl in config.yaml with value <user>.github.io
- Create the entire static site in the public directory
hugo
- Deploy it to Github (in your case, change dwla to <user>)
cd public git init git add . git commit -m "first commit" git branch -M main git remote add origin git@github.com:dwla/dwla.github.io.git git push -u origin main
Useful shortcodes excluded in hugo-ivy
-
Add “copy to clipboard” buttons to code blocks (Ref1, Ref2)
- Store this script in themes/hugo-ivy/static/js/clipboard.js
const svgCopy = '<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true"><path fill-rule="evenodd" d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"></path><path fill-rule="evenodd" d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z"></path></svg>'; const svgCheck = '<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true"><path fill-rule="evenodd" fill="rgb(63, 185, 80)" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>'; const addCopyButtons = (clipboard) => { // 1. Look for pre > code elements in the DOM document.querySelectorAll("pre > code").forEach((codeBlock) => { // 2. Create a button that will trigger a copy operation const button = document.createElement("button"); button.className = "clipboard-button"; button.type = "button"; button.innerHTML = svgCopy; button.addEventListener("click", () => { clipboard.writeText(codeBlock.innerText).then( () => { button.blur(); button.innerHTML = svgCheck; setTimeout(() => (button.innerHTML = svgCopy), 2000); }, (error) => (button.innerHTML = "Error") ); }); // 3. Append the button directly before the pre tag const pre = codeBlock.parentNode; pre.parentNode.insertBefore(button, pre); }); }; if (navigator && navigator.clipboard) { addCopyButtons(navigator.clipboard); } else { const script = document.createElement("script"); script.src = "https://cdnjs.cloudflare.com/ajax/libs/clipboard-polyfill/2.7.0/clipboard-polyfill.promise.js"; script.integrity = "sha256-waClS2re9NUbXRsryKoof+F9qc1gjjIhc2eT7ZbIv94="; script.crossOrigin = "anonymous"; script.onload = () => addCopyButtons(clipboard); document.body.appendChild(script); }
- Store this script in themes/hugo-ivy/static/css/clipboard.css
.clipboard-button { position: absolute; right: 0; /* padding: 2px 7px 5px 7px; */ padding: 2px 5px 2px 5px; margin: 5px; /* color: #767676; */ color: white; border-color: #767676; background-color: #ededed; border: 1px solid; border-radius: 6px; font-size: 0.8em; z-index: 1; opacity: 0; transition: 0.1s; } .clipboard-button > svg { fill: #767676; } .clipboard-button:hover { cursor: pointer; border-color: #696969; background-color: #e0e0e0; } .clipboard-button:hover > svg { fill: #696969; } .clipboard-button:focus { outline: 0; } .highlight { position: relative; } .highlight:hover > .clipboard-button { opacity: 1; transition: 0.2s; }
- Add this script to themes/hugo-ivy/layouts/partials/head_custom.html
{{ if (findRE "<pre" .Content 1) }} <link rel="stylesheet" href="/css/clipboard.css"> {{ end }}
- Add this script to themes/hugo-ivy/layouts/partials/head_custom.html
{{ if (findRE "<pre" .Content 1) }} <script src="/js/clipboard.js"></script> {{ end }}
- Store this script in themes/hugo-ivy/static/js/clipboard.js
-
Display nice notice (Ref1, Ref2)
-
Store this script in layouts/shortcodes/notice.html
{{- $noticeType := .Get 0 -}} {{- $raw := (markdownify .Inner | chomp) -}} {{- $block := findRE "(?is)^<(?:address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h(?:1|2|3|4|5|6)|header|hgroup|hr|li|main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video)\\b" $raw 1 -}} {{ $icon := (replace (index $.Site.Data.SVG $noticeType) "icon" "icon notice-icon") }} <div class="notice {{ $noticeType }}" {{ if len .Params | eq 2 }} id="{{ .Get 1 }}" {{ end }}> <div class="notice-title">{{ $icon | safeHTML }}</div> {{- if or $block (not $raw) }}{{ $raw }}{{ else }}<p>{{ $raw }}</p>{{ end -}} </div>
-
Store this script in static/css/notice.css
.notice { position: relative; padding: 1em 1em 1em 2.5em; margin: 1em 0; /* border-radius: 4px; */ } .notice p:last-child { margin: 0; } .notice .notice-title { position: absolute; left: 0.8em; } .notice .notice-title .notice-icon { width: 1.2em; height: 1.2em; } .notice.notice-warning { background: hsla(0, 65%, 65%, 0.15); border-left: 5px solid hsl(0, 65%, 65%); } .notice.notice-warning .notice-title { fill: hsl(0, 65%, 65%); } .notice.notice-info { background: hsla(30, 80%, 70%, 0.15); border-left: 5px solid hsl(30, 80%, 70%); } .notice.notice-info .notice-title { fill: hsl(30, 80%, 70%); } .notice.notice-note { background: hsla(200, 65%, 65%, 0.15); border-left: 5px solid hsl(200, 65%, 65%); } .notice.notice-note .notice-title { fill: hsl(200, 65%, 65%); } .notice.notice-tip { background: hsla(140, 65%, 65%, 0.15); border-left: 5px solid hsl(140, 65%, 65%); } .notice.notice-tip .notice-title { fill: hsl(140, 65%, 65%); }
-
Store this script in data/SVG.toml
# Notice Icon notice-warning = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 576 512"><path d="M570 440c18 32-5 72-42 72H48c-37 0-60-40-42-72L246 24c19-32 65-32 84 0l240 416zm-282-86a46 46 0 100 92 46 46 0 000-92zm-44-165l8 136c0 6 5 11 12 11h48c7 0 12-5 12-11l8-136c0-7-5-13-12-13h-64c-7 0-12 6-12 13z"/></svg>' notice-info = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M256 8a248 248 0 100 496 248 248 0 000-496zm0 110a42 42 0 110 84 42 42 0 010-84zm56 254c0 7-5 12-12 12h-88c-7 0-12-5-12-12v-24c0-7 5-12 12-12h12v-64h-12c-7 0-12-5-12-12v-24c0-7 5-12 12-12h64c7 0 12 5 12 12v100h12c7 0 12 5 12 12v24z"/></svg>' notice-note = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zm-248 50a46 46 0 100 92 46 46 0 000-92zm-44-165l8 136c0 6 5 11 12 11h48c7 0 12-5 12-11l8-136c0-7-5-13-12-13h-64c-7 0-12 6-12 13z"/></svg>' notice-tip = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zM227 387l184-184c7-6 7-16 0-22l-22-23c-7-6-17-6-23 0L216 308l-70-70c-6-6-16-6-23 0l-22 23c-7 6-7 16 0 22l104 104c6 7 16 7 22 0z"/></svg>'
-
Example in the .md file
{{< notice notice-warning >}} Perhaps the most valuable result of all education is the ability to make yourself do the thing you have to do, when it ought to be done, whether you like it or not. It is the first lesson that ought to be learned and however early a man's training begins, it is probably the last lesson that he learns thoroughly. --- Thomas Henry Huxley {{< /notice >}}
“Perhaps the most valuable result of all education is the ability to make yourself do the thing you have to do, when it ought to be done, whether you like it or not. It is the first lesson that ought to be learned and however early a man’s training begins, it is probably the last lesson that he learns thoroughly.” — Thomas Henry Huxley
“Perhaps the most valuable result of all education is the ability to make yourself do the thing you have to do, when it ought to be done, whether you like it or not. It is the first lesson that ought to be learned and however early a man’s training begins, it is probably the last lesson that he learns thoroughly.” — Thomas Henry Huxley
“Perhaps the most valuable result of all education is the ability to make yourself do the thing you have to do, when it ought to be done, whether you like it or not. It is the first lesson that ought to be learned and however early a man’s training begins, it is probably the last lesson that he learns thoroughly.” — Thomas Henry Huxley
“Perhaps the most valuable result of all education is the ability to make yourself do the thing you have to do, when it ought to be done, whether you like it or not. It is the first lesson that ought to be learned and however early a man’s training begins, it is probably the last lesson that he learns thoroughly.” — Thomas Henry Huxley
-