- Install Hugo
- Create a Hugo site with the hugo-scroll theme
- Get the zjedi/hugo-scroll website
- Customize
- Deploy
- Set up a custom domain
- Bonus. The More You Know
Install Hugo
https://gohugo.io/getting-started/quick-start/#prerequisites
Linux
https://gohugo.io/installation/linux/
Download the latest .deb
package from Hugo’s GitHub releases, then
install it and check version.
Edit vers
below to the version you want to install.
vers=0.148.0
package=hugo_extended_"$vers"_linux-amd64.deb
URL="https://github.com/gohugoio/hugo/releases/download/v$vers/$package"
cd ~/Downloads && \
wget "$URL" && \
sudo dpkg -i "$package" && \
rm -v "$package" && \
hugo version
To remove run sudo apt-get purge hugo
.
Windows
Install Git
https://git-scm.com/downloads/win
# Open Powershell as admin, run:
winget install --id Git.Git -e --source winget
# Show installed files
dir "C:\Program Files\Git\cmd"
# Check version
& "C:\Program Files\Git\cmd\git.exe" --version # outputs for example: git version 2.50.1.windows.1
# Check path
echo $env:Path
$env:Path -match "git"
# If False ("git" not in $PATH), add it
$env:Path += ";C:\Program Files\Git\cmd" # temporal
[Environment]::SetEnvironmentVariable("Path", ([Environment]::GetEnvironmentVariable("Path", "User") + ";C:\Program Files\Git\cmd"), "User") # persistent
git --version # outputs for example: git version 2.50.1.windows.1
Install Go
Windows 10 or later, Intel 64-bit processor download for example go1.24.5.windows-amd64.msi
.
Either
- Double-click the downloaded
.msi
file and follow the on-screen instructions to complete the installation. The default settings are suitable for most users. - Or
cd $HOME/Downloads
Get-ChildItem | Where-Object { $_.Name -match "msi" } # shows go1.24.5.windows-amd64.msi
# Install
Start-Process 'msiexec.exe' -ArgumentList '/i', 'go1.24.5.windows-amd64.msi', '/qn', '/norestart', '/l*v', 'go_install.log' -Wait
# Check version
& "C:\Program Files\Go\bin\go.exe" version # outputs for example: go version go1.24.5 windows/amd64
# Check path
echo $env:Path
$env:Path -match "go"
# If False ("go" not in $PATH), add it
$env:Path += ";C:\Program Files\Go\bin" # temporal
[Environment]::SetEnvironmentVariable("Path", ([Environment]::GetEnvironmentVariable("Path", "User") + ";C:\Program Files\Go\bin"), "User") # persistent
go version # outputs for example: go version go1.24.5 windows/amd64
Install Dash
Download the dart-sass-1.89.2-windows-x64.zip
or alike of https://github.com/sass/dart-sass/releases
Either
- Double-click the downloaded
.zip
file and extract it intoC:\dart-ass
- Or
cd $HOME/Downloads
Get-ChildItem | Where-Object { $_.Name -match "zip" } # shows dart-sass-1.89.2-windows-x64.zip
# Unzip
Expand-Archive -LiteralPath .\dart-sass-1.89.2-windows-x64.zip -DestinationPath .\dart-sass
# Move the extracted folder
Move-Item .\dart-sass\* C:\dart-sass
# Check path
echo $env:Path
$env:Path -match "dart"
# If False ("dart-sass" not in $PATH), add it
$env:Path += ";C:\dart-sass" # temporal
[Environment]::SetEnvironmentVariable("Path", ([Environment]::GetEnvironmentVariable("Path", "User") + ";C:\dart-sass"), "User") # persistent
sass --version # 1.89.2
Install Hugo
https://gohugo.io/installation/windows/#prebuilt-binaries
Download the extended edition, for example hugo_extended_0.148.1_windows-amd64.zip
from Hugo’s GitHub releases, then
Either
- Double-click the downloaded
.zip
file and extract it intoC:\hugo
- Or
cd $HOME/Downloads
Get-ChildItem | Where-Object { $_.Name -match "zip" } # shows hugo_extended_0.148.1_windows-amd64.zip
# Unzip
Expand-Archive -LiteralPath .\hugo_extended_0.148.1_windows-amd64.zip -DestinationPath .\hugo
# Move the extracted folder
Move-Item .\hugo C:\hugo
# Check path
echo $env:Path
$env:Path -match "hugo"
# If False ("hugo" not in $PATH), add it
$env:Path += ";C:\hugo" # temporal
[Environment]::SetEnvironmentVariable("Path", ([Environment]::GetEnvironmentVariable("Path", "User") + ";C:\hugo"), "User") # persistent
hugo version # hugo v0.148.1-...+extended windows/amd64 BuildDate=2025-07-11T12:56:21Z VendorInfo=gohugoio
# make sure its EXTENDED !
Test a Hugo repo
cd $HOME/Downloads
git clone https://github.com/juanMarinero/juanmarinero.github.io
cd juanmarinero.github.io
git submodule update --init --recursive # Important!
hugo server
…which outputs:
Watching for changes in C:\Users\UserName\Downloads\juanmarinero.github.io\{archetypes,assets,content,layouts,static,themes}
Watching for config changes in C:\Users\UserName\Downloads\juanmarinero.github.io\hugo.toml
Start building sites …
hugo v0.148.1-98ba786f2f5dca0866f47ab79f394370bcb77d2f+extended windows/amd64 BuildDate=2025-07-11T12:56:21Z VendorInfo=gohugoio
│ ES
──────────────────┼─────
Pages │ 7
Paginator pages │ 0
Non-page files │ 0
Static files │ 110
Processed images │ 8
Aliases │ 0
Cleaned │ 0
Built in 23132 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
Current date: Monday, July 14, 2025, 11:50 AM CEST
Open in browser http://localhost:1313/
In future just run:
cd $HOME/Downloads/juanmarinero.github.io
hugo server
Create a Hugo site with the hugo-scroll theme
Follow quickstart - commands applaying hugo-scroll theme
cd ~/Downloads
hugo new site quickstart
cd quickstart
git init
git submodule add https://github.com/zjedi/hugo-scroll.git themes/hugo-scroll
echo "theme = 'hugo-scroll'" >> hugo.toml
hugo server
This should output like
> hugo server
Watching for changes in <path>/quickstart/{archetypes,assets,content,data,i18n,layouts,static,themes}
Watching for config changes in <path>/quickstart/hugo.toml
Start building sites …
hugo v0.148.0-c0d9bebacc6bf42a91a74d8bb0de7bc775c8e573+extended linux/amd64 BuildDate=2025-07-08T13:34:49Z VendorInfo=gohugoio
│ EN
──────────────────┼─────
Pages │ 6
Paginator pages │ 0
Non-page files │ 0
Static files │ 108
Processed images │ 0
Aliases │ 0
Cleaned │ 0
Built in 25 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
Now, open in browser http://localhost:1313/
Notice the browser tab name My New Hugo Site but the site is empty.
Let’s stop the server Ctrl+C
and add some content.
Get the zjedi/hugo-scroll website
https://github.com/zjedi/hugo-scroll#-installation says:
If you are starting fresh, simply copy over the contents of the
exampleSite
-directory included in this theme to your source directory. That should give you a good idea about how things work, and then you can go on from there to make the site your own.
cd ~/Downloads/quickstart
hugo_scroll_dir=$HOME/Downloads/hugo-scroll
git clone --depth 1 https://github.com/zjedi/hugo-scroll.git "$hugo_scroll_dir"
cp -r "$hugo_scroll_dir"/exampleSite/* .
hugo server
This should output like
Watching for changes in <path>/quickstart/{archetypes,assets,content,data,i18n,layouts,static,themes}
Watching for config changes in <path>/quickstart/hugo.toml
Start building sites …
hugo v0.148.0-c0d9bebacc6bf42a91a74d8bb0de7bc775c8e573+extended linux/amd64 BuildDate=2025-07-08T13:34:49Z VendorInfo=gohugoio
│ EN │ DE
──────────────────┼─────┼─────
Pages │ 15 │ 14
Paginator pages │ 0 │ 0
Non-page files │ 1 │ 0
Static files │ 114 │ 114
Processed images │ 8 │ 0
Aliases │ 1 │ 0
Cleaned │ 0 │ 0
Built in 4793 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
And the local website http://localhost:1313/ should be like this.
Customize
Remove git dirs
The easiest way is to edit little by little the content of the zjedi/hugo-scroll repo to your needs.
rm -rf .git .github exampleSite images CHANGELOG.md contributing.md LICENSE package.json package-lock.json README.md .prettierignore .prettierrc.json theme.toml netlify.toml
git init
And check that hugo server
still works.
Order of markdowns
The website sections are sorted by the weight
metadata.
- E.g. next has weight 99 to appear last exampleSite/content/en/homepage/credits.md
- Next weight 3 to appear the 3rd at top exampleSite/content/en/homepage/about-me.md
Lets check them all!
- Create a script like cat_by_weight.sh
- Run it on the content directory
chmod +x cat_by_weight.sh
./cat_by_weight.sh content/en/homepage head -n 5
Note. You can pass another catter like cat
or tail
. The default is bat --line-range=1:10
to get:
weight | file |
---|---|
1 | content/en/homepage/opener.md |
3 | content/en/homepage/about-me.de.md |
3 | content/en/homepage/about-me.md |
4 | content/en/homepage/contact.md |
98 | content/en/homepage/legal-brief.md |
99 | content/en/homepage/credits.md |
99 | content/en/homepage/external.md |
--- content/en/homepage/opener.md (weight: 1) ---
---
title: "Welcome"
weight: 1
---
--- content/en/homepage/about-me.de.md (weight: 3) ---
---
title: "Über mich (shared folder)"
weight: 3
header_menu: true
---
--- content/en/homepage/about-me.md (weight: 3) ---
---
title: "About Me"
weight: 3
header_menu: true
---
--- content/en/homepage/contact.md (weight: 4) ---
---
title: "Contact"
weight: 4
header_menu: true
---
--- content/en/homepage/legal-brief.md (weight: 98) ---
---
title: "Brief Legal Information"
weight: 98
header_menu_title: "Legal"
navigation_menu_title: "Legal stuff"
--- content/en/homepage/credits.md (weight: 99) ---
---
title: "Credits"
weight: 99
header_menu: true
---
--- content/en/homepage/external.md (weight: 99) ---
---
title: "GitHub"
weight: 99
header_menu: true
external: https://github.com/zjedi/hugo-scroll
--- content/en/homepage/index.md (no weight) ---
---
headless: true
---
--- content/en/homepage/license.md (no weight) ---
---
footer_menu_title: License
footer_menu: true
detailed_page_path: /license/
detailed_page_homepage_content: false
--- content/en/homepage/services.md (no weight) ---
---
title: "The Services I Offer"
header_menu_title: "Services"
navigation_menu_title: "My Services"
weight: 2
hugo.toml
Open with your favorit editor "$EDITOR" hugo.toml
and edit, among other:
baseURL
replace with your domain, or withhttps://<username>.github.io
, for examplehttps://juanmarinero.github.io
defaultContentLanguage = "en"
edit if needed, but this requires to, if noten
norde
to- edit end of page
[languages]
- and add a directory like
contentDir = "content/es"
for español (Spanish)
- edit end of page
- The browser tab name
title = "..."
- set
title_guard
totrue
if title not legible because color contrast - set
language_menu
andshow_current_lang
tofalse
if just one language website invertSectionColors = false
set to true and check if it likes you more- set
showContactIcons
totrue
to share email/phone in footnote - edit
params.meta
andparams.contacts
Favicons, header-logo and cover-image
Replace
assets/images/cover-image.jpg
with for example https://www.freepik.com/search?format=search&last_filter=selection&last_value=1&query=Zen+Background&selection=1.assets/images/favicon.png
with for example https://www.flaticon.com/free-icons/zen. Convert it to andassets/images/apple-touch-icon.png
of 180x180px via:
cd assets/images/
sudo apt update && sudo apt install imagemagick optipng -y
convert favicon.png -resize 180x180 apple-touch-icon.png
- Same for
public/images/favicon-16x16.png
andpublic/images/favicon-32x32.png
. Also forstatic/images/
andassets/favicon.ico
cd <repo-path>
convert assets/images/favicon.png -resize 16x16 public/images/favicon-16x16.png
convert assets/images/favicon.png -resize 32x32 public/images/favicon-32x32.png
convert assets/images/favicon.png -resize 16x16 static/images/favicon-16x16.png
convert assets/images/favicon.png -resize 32x32 static/images/favicon-32x32.png
convert assets/images/favicon.png -define icon:auto-resize=64,48,32,16 assets/favicon.ico
assets/images/chef-hat.png
renamed toheader-logo.png
with for example https://www.flaticon.com/search?word=massage. Also rename that file incontent/en/_index.md
with your favorit editor:"$EDITOR" content/en/_index.md
To change the background image to a video hugo.toml
says
# These "images" are used for the structured data templates. This will show up, when
# ...
# NOT the actual header background image, go to _index.md instead
images = ["images/cover-image.jpg"]
Thus, check if content/en/_index.md
sets a fixed image:
# When set true, uses video from custom_header_video.html partial, instead of header_image
header_use_video: false
Toggle it to true
, add the video (for example from pexels) to assets/cover/
, and edit the video name in layouts/partials/custom_header_video.html
.
Tip, set video speed there directly in that html
file with:
<video id="portfolioVideo" ...
{{ $videoResource := resources.Get "cover/video_name.mp4" }}
<source src="{{ $videoResource.RelPermalink }}" type="video/mp4">
</video>
<script>
// Slow down video to 50% speed
document.getElementById('portfolioVideo').playbackRate = 0.5;
</script>
Edit a mainpage section
For example edit content/en/homepage/services.md
title: "The Services I Offer"
is the title of that section of the website.header_menu_title: "Services"
is text of a link to this website section, this link is displayed in the cover section or hero section., i.e.content/en/_index.md
section, i.e. in at start of the mainpage.navigation_menu_title: "My Services"
is the text of a link to this website section, this link is displayed at the cover menu (the navigation bar at the top showing links to sections of the main page, it keeps there even while one scrolls)… as long asheader_menu
istrue
in the webseite section.
In contrast content/en/homepage/opener.md
has no header_menu_title
nor navigation_menu_title
. And therefore this website section does not appear in the cover section nor in the cover menu. As its content stated
here:
By the way this welcome section won’t show in the cover menu.
Edit a not mainpage
For example https://zjedi.github.io/hugo-scroll/services/
has the content of https://github.com/zjedi/hugo-scroll/blob/master/exampleSite/content/en/services.md (not to confuse with https://github.com/zjedi/hugo-scroll/blob/master/exampleSite/content/en/homepage/services.md)
https://github.com/zjedi/hugo-scroll/blob/master/exampleSite/content/en/homepage/opener.md?plain=1, i.e. the mainpage, links to this not-mainpage via [dedicated pages](services)
of:
You can also delegate lengthier, less important or more sizeable content to [dedicated pages](services).
In the language directory, for example public/en/
edit the sitemap.xml
file.
CSS
layouts/partials/custom_head.html
shows how to add CSS code:
- directly in that file, just below comment line
Custom CSS via inline styles
add anstyle
tag not commented (not wrapped inside<!--
--->
) for example<style>fontsize=1.2</style>
to increase every text size a 20% - and/or via a css file, read commentes in the file
Check original CSS style in themes/hugo-scroll/assets/css/
.
For example to change background colors of odd sections edit themes/hugo-scroll/assets/css/variables.scss
, its --section-dark-bg-color
.
Note, I should not directly edit themes/hugo-scroll
since its a submodule not of my property, thus I cannot push it.
Instead in layouts/partials/custom_head.html
write:
<style>
:root {
--section-dark-bg-color: #c1cdaa;
}
</style>
Raw HTML
{{< rawhtml >}}<div class="html-content">
and
</div>{{< /rawhtml >}}
.
For more info read
layouts/shortcodes/rawhtml.html
from the official Hugo-scroll repo.
Example usage in the TL;DR of my Nerd Fonts and more blog.Alternative but NOT recommended. Add this to your config.toml
(or equivalent in YAML/JSON)
[markup.goldmark.renderer]
unsafe = true
Read
Deploy
References
- https://gohugo.io/host-and-deploy/host-on-github-pages/
- https://www.testingwithmarie.com/posts/20241126-create-a-static-blog-with-hugo/
Create a GitHub repository
Create a new public repository named username.github.io
, where username
is your GitHub username.
But use lowercase letters even if your username has capitals.
For example, for mdcruz it is mdcruz.github.io.
And push your local repository to GitHub.
Note, content from submodules of third people must not be edited. I.e. do not edit themes/hugo-scroll/
submodule.
Host on GitHub
Follow steps of https://gohugo.io/host-and-deploy/host-on-github-pages/
Under
Settings/Pages/Source
changeDeploy from a branch
toGithub Actions
.$EDITOR hugo.toml
and add
[caches]
[caches.images]
dir = ':cacheDir/images'
- Create a file named
hugo.yaml
in a directory named.github/workflows
mkdir -p .github/workflows
touch .github/workflows/hugo.yaml
$EDITOR .github/workflows/hugo.yaml
and copy and paste the YAML below into the file you created. Change the branch name and Hugo version as needed.
# Sample workflow for building and deploying a Hugo site to GitHub Pages
name: Deploy Hugo site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
# Default to bash
defaults:
run:
# GitHub-hosted runners automatically enable `set -eo pipefail` for Bash shells.
shell: bash
jobs:
# Build job
build:
runs-on: ubuntu-latest
env:
DART_SASS_VERSION: 1.89.2
HUGO_VERSION: 0.148.0
HUGO_ENVIRONMENT: production
TZ: America/Los_Angeles
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install Dart Sass
run: |
wget -O ${{ runner.temp }}/dart-sass.tar.gz https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
tar -xf ${{ runner.temp }}/dart-sass.tar.gz --directory ${{ runner.temp }}
mv ${{ runner.temp }}/dart-sass/ /usr/local/bin
echo "/usr/local/bin/dart-sass" >> $GITHUB_PATH
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Install Node.js dependencies
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: Cache Restore
id: cache-restore
uses: actions/cache/restore@v4
with:
path: |
${{ runner.temp }}/hugo_cache
key: hugo-${{ github.run_id }}
restore-keys:
hugo-
- name: Configure Git
run: git config core.quotepath false
- name: Build with Hugo
run: |
hugo \
--gc \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/" \
--cacheDir "${{ runner.temp }}/hugo_cache"
- name: Cache Save
id: cache-save
uses: actions/cache/save@v4
with:
path: |
${{ runner.temp }}/hugo_cache
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
For example check and edit if needed:
DART_SASS_VERSION: 1.89.2
HUGO_VERSION: 0.148.0
TZ: America/Los_Angeles
Commit and push the change to your GitHub repository.
git add -A
git commit -m "Create hugo.yaml"
git push
Wait for Github pages to be ready
Go to Actions
tab, for example, and check the status of the deployment, wait until Build and deploy job
is green.
Now click on the link with same content as last commit message, Create hugo.yaml
for example, this will show the link to your live site, like https://mdcruz.github.io (for this repo).
Rebuild before pushing
After every change remember to rebuild the site by running the following command: hugo server --disableFastRender
For example, if I modify projects.md
then git status --short
just shows:
M content/en/homepage/projects.md
instead of the neccesary:
M content/en/homepage/projects.md
M public/index.html
Therefore, if I just commit and push it then I will see no changes in the live site, instead one must:
- Rebuild the website (
public/index.html
) withhugo server --disableFastRender
, - Check locally the changes on http://localhost:1313/,
- And if the result is satisfactory proceed to stage, commit and push.
Removing public
related files is also a good idea. This way Hugo will re-build just the neccesary files, and the no longer needed files can be commited.
For example, for my blogs (content/en/blogs
) I run:
rm -rf public/blogs
hugo server --disableFastRender
Then I check it in the browser.
Finally I make sure that all needed is rebuilt previous to push:
tree -L 2 public/blogs
hugo list all
Set up a custom domain
Buy a domain
- Check if available at https://lookup.icann.org/whois/
- Buy it at https://www.namecheap.com/domains/ for example. Note, you do not need Additional Hosting since GitHub Pages offers free static hosting.
Manage the DNS records for your domain
Read
Remove both the ALIAS
and CNAME
records you currently have set.
The A records
For the A
record, set the following values:
185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153
For example in Porkbun’s DNS management add these four A
records (one for each GitHub IP). Like this:
Type: A
Host: @ (or leave empty)
Answer/Value: 185.199.108.153
TTL: 600
The CNAME records
- The DNS-CNAME-record tells the internet where to find your site.
- The GitHub-CNAME-file tells GitHub which domain(s) are allowed to show your site.
Next steps varies in each domain provider.
- Flexible Providers (e.g., Porkbun, Cloudflare):
- Use synthetic records (
ALIAS
,ANAME
) that mimicCNAME
behavior at the root but technically resolve toA
records. - These bypass DNS standards, making GitHub verification “work” even though it’s not a true
CNAME
.
- Use synthetic records (
- Strict Providers (e.g., EuroDNS, AWS Route 53):
- Enforce pure RFC compliance.
- Block
CNAME
at the apex entirely → GitHub can’t verify the domain unless you useA
records.
For example, for my.euroDNS.com just remove every CNAME
and that’s it. You can jump to the next step.
For Porkbun’s DNS management and alike, add a CNAME
with the value <username>.github.io
.
Type: CNAME
Host: www
Answer/Value: juanmarinero.github.io
TTL: 600
This is because Porkbun-alike domain providers let you set an ALIAS
(not true CNAME
) for root, this works like A
records.
This is confirmed in the testingwithmarie.com post,
where the screenshot shows CNAME (Aliases)
instead of plain CNAME
.
Set your domain on Github
Read https://www.testingwithmarie.com/posts/20241126-create-a-static-blog-with-hugo/#set-up-custom-domain
Add your domain to GitHub Pages settings
In the Github repo, go to Settings > Pages
and add your domain under the Custom domain
field.
For example add juan-marinero.info
, or www.juan-marinero.info
.
Wait for up to 24 hours to see the site to your custom domain. So, from now on, you can either:
- Visit the
github.io
Gihtub Page, for example https://juanmarinero.github.io - Visit your custom domain, like https://juan-marinero.info or with the
www
subdomain like https://www.juan-marinero.info
All these URLs will:
- serve the site from your repository, the
<username>.github.io
Github repo, namely https://github.com/juanMarinero/juanmarinero.github.io. - redirect and serve at the non-
www
domain, like https://juan-marinero.info. To serve at thewww
subdomain, like https://www.juan-marinero.info, read next section.
Add your domain to a CNAME file
To serve your site at the wwww
subdomain (e.g. http(s)://www.juan-marinero.info
) and redirect the root domain (juan-marinero.info
) to this www
address:
- Make sure your DNS is configured properly, as described earlier.
- Add a
CNAME
file to your<username>.github.io
repo, as Marie’s page did here. You can do this with the following commands:
cd <repo-path>
echo "www.juan-marinero.info" > CNAME # edit !!
git add CNAME
git commit -m "add CNAME with www.juan-marinero.info"
git push
Enforce HTTPS
HTTPS
protocol because I
enforced HTTPS for my GitHub Pages site
.This is not mandatory, but recommended.
Bonus. The More You Know
Apex Domains and the www subdomain
Github Pages docs states
- An apex domain is a custom domain that does not contain a subdomain, such as example.com.
- Apex domains are also known as base, bare, naked, root apex, or zone apex domains.
- If you are using an apex domain as your custom domain, we recommend also setting up a
www
subdomain.
Notice we followed this advice in previous sections, where the CNAME
record has www
as host.
Understanding CNAME Restrictions on Apex Domains
- DNS Standards (RFC 1034):
- The apex/root domain (e.g.,
example.com
) cannot have aCNAME
record if other records (likeMX
,TXT
,NS
) exist for the same domain. - This is because
CNAME
conflicts with other record types. GitHub Pages requires aCNAME
for verification, but apex domains needA
/AAAA
records instead.
- The apex/root domain (e.g.,
- How GitHub Pages Checks Domains:
- When you add
example.com
in GitHub Pages settings, GitHub:- Looks for a
CNAME
file in your repo (for subdomains likewww.example.com
). - For apex domains, it checks for
A
records pointing to GitHub’s IPs.
- Looks for a
- If GitHub finds a
CNAME
at the apex (which violates DNS rules), verification fails.
- When you add
GitHub Pages sites can be stored in any repository
Read Types of GitHub Pages sites.
In this guide we worked with the <username>.github.io
repository, which has the apex domain <username>.github.io
(accesible via http(s)://<username>.github.io
).
But GitHub Pages also support storing sites in other repositories, like <project-name>.github.io/<repo-name>
, which have the apex domain <project-name>.github.io/<repo-name>
(displayed via http(s)://<project-name>.github.io/<repo-name>
). For these you must have a project account. Read next section.
Hugo is not the only solution
To deploy our local website on GitHub Pages is very recommended to use a static site generator like Hugo.
With Hugo we followed its Host on GitHub Pages docs, which, in summary, apply Github actions adding the config file .github/workflows/hugo.yaml. This workflow install Hugo’s dependencies, Hugo itself, node.js, configure git,… and then builds the site using Hugo. For example, the build step depends on these few lines
- name: Build with Hugo
run: |
hugo \
--gc \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/" \
--cacheDir "${{ runner.temp }}/hugo_cache"
Jekyll is other static site generator solution with built-in support for GitHub Pages, i.e. an alternative to Hugo.
Next I exemplify how to create a Github Pages site without any of those static site generators. It’s exaplained for a user or organization site, but it’s analogous for a project site case.
Publishing from a branch
Create a site for your <username>.github.io
repository, screenshots in https://pages.github.com/ (click on User or organization site).
- Create a new Github repository called
<username>.github.io
(unless you already have one, if you do, you can skip these steps or create a new repo with other name) - Push an
index.html
file to it
cd <repo-path>
echo '<h1>Hello!</h1>' > index.html
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/<username>.github.io.git
git push -u origin main
- In a browser go to
http://<user-name>.github.io
.
Note. The Github Pages docs
is not limited to index.html
:
Create the entry file for your site. GitHub Pages will look for an
index.html
,index.md
, orREADME.md
file as the entry file for your site.
Now let’s create another repo, for example test-publishing-from-a-branch
, with that same index.html
. Then follow steps of
Publishing from a branch
(TL;DR Settings/Pages, under Source select Deploy from a branch, select the main
branch, and click Save)
Also check the step-by-step screenshots in https://pages.github.com/ (click on Project site and Start from scratch). Though initial steps are meant for a project site.
For the repo juanMarinero/test-publishing-from-a-branch that configuration triggers next workflow: pages build and deployment #1
Thus, I can see that index.html is the entry file for my site. Any of next links would work:
- https://juanmarinero.github.io/test-publishing-from-a-branch/
- https://juan-marinero.info/test-publishing-from-a-branch/
- https://www.juan-marinero.info/test-publishing-from-a-branch/
Once the index.html
file is edited the site is auto-updated.
cd <repo-path>
echo '<h2>Welcome!</h2>' >> index.html
git add index.html
git commit -m "Edit index.html"
git push
Check the previous URLs again and the new workflow execution pages build and deployment #2
Publishing with a custom GitHub Actions workflow
Alternative to Publishing from a branch is Publishing with a custom GitHub Actions workflow. This way one sets GitHub Actions, and then, quoting in cursive the docs:
- GitHub will suggest several workflow templates. If you already have a workflow to publish your site, you can skip this step. Actually this is how we already did it before (here) in our Hugo example, via the workflow template
.github/workflows/hugo.yaml
. - Otherwise, choose one of the options to create a GitHub Actions workflow. This is the challenge! To create a custom workflow for your site’s needs.