Hugo Elliott

| website | hugo | Est reading time: 7 mins

How to add static pages to our Hugo website

In our previous post we learnt how to set up a Hugo website and added a homepage. In this post we’ll add About, Contact, Privacy and 404 pages. The method of adding each page is going to be the similar. We’re going to create custom template for each page and then populate them with content.

Open and edit themes/new-theme/layouts/partials/footer.html adding

<footer class="footer">
    ...
    <div class="container">
        <div class="has-text-centered is-size-7-mobile pb-05">
            {{ range .Site.Menus.foot }}
            <a href="{{ .URL }}" title="{{ .Name }}">
                {{ .Name }}
            </a>
            {{ end }}
            |
            {{ range .Site.Menus.taxonomy }}
            <a href="{{ .URL }}" title="{{ .Name }}">
                {{ .Name }}
            </a>
            {{ end }}
        </div>
        ...
</footer>

Open and edit config.toml adding

[menu]
    ...
    [[menu.foot]]
        name = "About"
        url = "/about"
    [[menu.foot]]
        name = "Contact"
        url = "/contact"
    [[menu.foot]]
        name = "Privacy"
        url = "/privacy"

We also need to add links to our social media pages. In config.toml add

[menu]
    [[menu.social]]
        name = "LinkedIn"
        url = "https://www.linkedin.com/in/hugo-elliott-07bb9a2/"
        pre = "<i class='fab fa-linkedin'></i>"
    [[menu.social]]
        name = "Github"
        url = "https://github.com/hugoelliott"
        pre = "<i class='fab fa-github-square'></i>"
    [[menu.social]]
        name = "Twitter"
        url = "https://twitter.com/hogo_elliott"
        pre = "<i class='fab fa-twitter-square'></i>"

Plainly you ought to amend the urls, as these link to my social media pages. It’s pretty easy to add links to other social media sites, just by copying and amending the block of code. A point to note, Hugo displays these links in alphabetical order of the name. If you want to change the order they are displayed, edit the name to include a digit at the front such as “1 LinkedIn”.

Fontawesome has all the icons for your code.

2. About Page

Now we need to create our first static page. In terminal run the commands

hugo new about.md
hugo new themes/new-theme/layouts/_default/about.html

Where new-site and new-theme are the names of your new website and theme.

Open and edit content/about.md delete draft: true (if it’s there) and add layout: about

Open and edit layouts/_default/about.html adding

{{ define "main" }}
<!-- Content for about page -->
    <div class="container pt-3 pl-1 pr-1 pb-3">
        <!-- <h1 class="title">{{ .Title }}</h1> -->
        <div class="columns">
            <div class="column is-one-quarter">
                <figure class="image is-128x128">
                    <img class="is-rounded" src="{{ .Params.authorimageurl }}" alt="{{ .Params.author }}">
                </figure>
                <div class="column">
                    <p class=""><strong>{{ .Params.authorName }}</strong></p>
                </div>
                <div>
                    {{ range .Site.Menus.social }}
                        <a href="{{ .URL }}">
                            <p class="is-size-4 icon mr-1">{{ .Pre }}</p>
                            <!-- <p>{{ .Name }}</p> -->
                        </a>
                    {{ end }}
                </div>
            </div>
            <div>
                <div class="column is-three-quarters about">
                    {{ .Content }}
                </div>
            </div>
        </div>
    </div>
{{ end }}

You’ll notice that

  1. The About page is split into two columns,
  2. The first column contains a Photograph, name and social media links, and
  3. The second column contains {{ .Content }}

You can now open and edit content/about.md to add content for the About Page’s second column.

3. Contact Page

We will create a custom template for the Contact page. But we’re going to do things a little differently from the About Page (above). Firstly, we’re going to use a ‘Partial’ and secondly, we’re going to use a form from Kwes.io. This is simply because forms are difficult to code, and I’d prefer to use a third party form provider at this stage.

In terminal run the commands

hugo new contact.md
hugo new themes/new-theme/layouts/_default/contact.html
hugo new themes/new-theme/layouts/partials/widgets/contactform.html

Where new-site and new-theme are the names of your new website and theme.

Open and edit content/contact.md delete draft: true (if it’s there) and add layout: contact

a. What is a partial?

In the previous blog post, you may have spotted the text ‘partial’ in some of the code we wrote. A partial is simply a piece of code that can be reused in the website, it helps code my code DRY.

b. Sign up to a third party form service

A simple search on the internet reveals there are several options to integrate forms into to a static website, ranging from building your own using Google Sheets to third party providers such as Formspree.

We use Kwes.io. You get a pretty generous unlimited number of submissions per month. On their free plan they they limit the number of spam submissions they block per month.

c. Create the contact form

Open and edit layouts/_default/contact.html adding

{{ define "main" }}

<!-- Content for contact form -->
<div class="container pl-05 pr-05 pb-2">
    <div>
        {{ partial "widgets/contactform.html" . }}
    </div>
</div>

<!-- Kwes Forms -->
<script src="https://kwes.io/v2/kwes-script.js" defer></script>

{{ end }}

Open and edit layouts/partials/widgets/contactform.html adding

<h1 class="title mt-2">{{ .Title }}</h1>
<p class="subtitle mt-1 contactform">Please contact me using the form below</p>

<form action="{{ .Site.Params.contactFormWebHook }}" method="POST" id="contactform" class="kwes-form">
    <div class="field">
        <div class="control has-icons-left">
            <input name="first_name" class="input" type="text" placeholder="First name" rules="required|max:255">
            <span class="icon is-small is-left">
                <i class="fas fa-user"></i>
            </span>
        </div>
    </div>
    <div class="field">
        <div class="control has-icons-left">
            <input name="family_name" class="input" type="text" placeholder="Family name" rules="required|max:255">
            <span class="icon is-small is-left">
                <i class="fas fa-user"></i>
            </span>
        </div>
    </div>
    <div class="field">
        <div class="control has-icons-left">
            <input name="email" class="input" type="email" placeholder="Email" rules="required|max:255">
            <span class="icon is-small is-left">
            <i class="fas fa-envelope"></i>
            </span>
        </div>
    </div>
    <div class="field">
        <div class="control has-icons-left">
            <textarea name="message" class="input" placeholder="Your message" style="min-height: 10rem;" rules="required|max:700"></textarea>
            <span class="icon is-small is-left">
                <i class="fas fa-pen"></i>
            </span>
        </div>
    </div>
    <button type="submit" class="button is-link">Submit</button>
</form>

Open and edit config.toml adding

[params]
    ...
    contactFormWebHook = "https://kwes.io/api/foreign/forms/xxxxxxxxxxx"

Where the parameter ‘contactFormWebHook’ is Action URL given in the Kwes.io set up process.

Now save the pages, start the hugo server and navigate to your contact page. It should look like this.

Contact form

Do a test submission and check it works.

4. Privacy Regulations

With the advent of data protection regulations such as

  1. European General Data Protection Regulation, and
  2. California’s Consumer Privacy Act,

if you collect user data (with cookies), or allow people to subscribe to a mailing list you probably need a Privacy Policy.

There are a number of free services that help write your Privacy Policy. Here are a couple I found online

  1. Shopify,
  2. SEQ Legal

Although we use SEQ Legal’s free policy (as we’re based in the UK), I can’t vouch/endorse of any of these listed above.

Remember if you’ve a complex site, you probably ought to get a lawyer to review your policy.

Thankfully Hugo makes it very easy to change your site’s Privacy Settings.

5. Privacy Page

We will create a custom template for the Privacy page.

In terminal run the commands

hugo new privacy.md
hugo new themes/new-theme/layouts/_default/privacy.html

Where new-site and new-theme are the names of your new website and theme.

In content/privacy.md delete draft: true and add layout: about

Open and edit layouts/_default/privacy.html adding

{{ define "main" }}
<!-- Content for privacy page -->
<div class="container">
    <h1 class="title">{{ .Title }}</h1>
    <div class="privacy">
        {{ .Content }}
    </div>
</div>
{{ end }}

Open and edit static/css/main.css and add

.privacy ol li {
    margin-bottom: 1rem;
}

If you open and inspect (with Chrome Dev Tools) our Privacy Policy, you see that Hugo’s Markup Engine has inserted our policy as an ordered list.

This addition to main.css just adds a margin-bottom of 1rem to the list items on the Privacy Page.

6. 404 Page

We will create a custom template for the 404 page.

In terminal run the commands

hugo new 404.md
hugo new themes/new-theme/layouts/_default/404.html

In content/404.md delete draft: true and add layout: 404

Open and edit config.toml adding

[params]
    ...
    BackgroundImage404 = "https://source.unsplash.com/6bXvYyAYVrE"

Open and edit layouts/_default/404.html adding

{{ define "main" }}
<!-- Content for 404 page -->

<div class="hero is-fullheight-with-navbar" style="background: grey url('{{ .Site.Params.BackgroundImage404 }}') no-repeat center/cover;">

    <div class="hero-head">
    <!-- Placeholder -->
    </div>

    <div class="hero-body">
        <!-- Placeholder -->
    </div>

    <div class="hero-foot pb-2 pl-1 pr-1">
        <div class="container has-text-">
        <p class="title is-size-5-touch is-size-4-tablet has-text-light mb-2">
            Sorry but the page you were searching for doesn't exist
        </p>
        <p class="subtitle has-text-light ">
            <a href="{{ `` | absURL }}">
                <button class="button is-link mb-2">
                    <p class="is-size-6-touch">Click here to go home</p>
                </button>
            </a>
        </p>
        </div>
    </div>
    </div>
{{ end }}

You will notice that in config.toml I’ve added a link to a background image. In layouts/_default/404.html I’ve added some inline style referencing the Parameter for the background image. I tried for a long time to add this to my custom css style sheet, but eventually figured out that Hugo didn’t want to let me do this…

Here is the final 404 page with a link back to the home page.

404 page

If you'd like help with a project, please click below

.