Skip to Content

Transfering the company site to hugo: Part 1

Posted on 10 mins read
Table of Contents

Background

So my company site at Fluid Media is currently static HTML apart from one PHP file for the contact form (so quick to serve), but edits require HTML editing to change anything (slow and tedious to edit). This was made before I was aware of static site generators like Hugo. The plan is to move it over to Hugo to allow easy editing of content. Without further a do let’s get started!

Step 1: Create a new hugo site

I’m assuming you already have Hugo installed, if not follow this excellent guide on their site. We can then run this to create a new site in the fluidmediahugo folder.

hugo new site fluidmediahugo

We’ll then create a git repository and commit our new site. (Note: don’t use -S if you don’t have pgp keys setup)

cd fluidmediahugo
git init
git add .
git commit -S -m "Initial commit"

And I’ve set up a repository on our company GitHub (practillay everything we make is on GitHub). So let’s add that as a remote and push our initial commit.

git remote add origin [email protected]:FluidMediaProductions/fluidmediahugo.git
git push --set-upstream origin master

Finally I’ll add a LICENSE. I’m using the GPLv3 because it’s company work.

nano LICENSE # Copy in license
git add LICENSE
git commit -S -m "Add license"
git push

That’s our site setup but we can’t do anything yet we need to…

Step 2: Add a theme

We’re not using any premade themes here so lets create a new one. This will create a theme called fluidmedia

hugo new theme fluidmedia

We need to change a few things before we start adding to the templates. We need to change the license and a few config values.

rm themes/fluidmedia/LICENSE
nano themes/fluidmedia/theme.toml
# Set name = "Fluid Media"
# Set license = "GPLv3"
# Set licenselink = "https://github.com/fluidmediaproductions/fluidmediahugo/blob/master/LICENSE.md"
# Set homepage = "https://fluidmedia.wales"
# Set:
# [author]
#   name = "Benjamin Misell"
#   homepage = "https://misell.cymru"
# Remove these lines:
# [author]
#   name = ""
#   homepage = ""

We also need to add this line to the main site config.toml

theme = "fluidmedia"

And commit.

git add .
git commit -S -m "Setup theme config"
git push

Step 4: Copy over old site

First lets create a template partial for the <head> of a page. This will live in layouts/partials/head/head.html (relative to the theme route).

<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Fluid Media Productions</title>
	
	<!-- Bootstrap -->
	<link href="style/bootstrap/css/bootstrap.min.css" rel="stylesheet">
	
	<!-- Main Styles -->
	<link href="style/css/plugins.css" rel="stylesheet" type="text/css">
	
	<!-- Fonts -->
	<link href='http://fonts.googleapis.com/css?family=Glegoo' rel='stylesheet' type='text/css'>
	<link href='http://fonts.googleapis.com/css?family=Coda' rel='stylesheet' type='text/css'>
	<link href='http://fonts.googleapis.com/css?family=Playfair+Display:400italic,700italic' rel='stylesheet' type='text/css'>

	<!--[if lt IE 9]>
	<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
	<![endif]-->
	
	<!-- Main Styles -->
	<link href="style.css" rel="stylesheet" type="text/css">
</head>

This is still quite large for a Hugo partial so let’s split it into:

  • CSS Includes
  • Meta tags
  • IE compatibility

layout/partials/head/meta.html (The {{ .Hugo.Generator }} includes a tag saying this was generated by Hugo, the developers ask nicely that every theme does this for statistics tracking)

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{ .Hugo.Generator }}

layout/partials/head/includes.html (The {{ print | relUrl}} tag makes sure our content is included correctly)

<!-- Bootstrap -->
<link href="{{ print "/bootstrap/css/bootstrap.min.css" | relURL  }}" rel="stylesheet">
<!-- Main Styles -->
<link href="{{ print "/css/plugins.css" | relURL  }}" rel="stylesheet" type="text/css">
<!-- Fonts -->
<link href='http://fonts.googleapis.com/css?family=Glegoo' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Coda' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Playfair+Display:400italic,700italic' rel='stylesheet' type='text/css'>
<!-- Main Styles -->
<link href="{{ print "/css/style.css" | relURL  }}" rel="stylesheet" type="text/css">

layout/partials/head/ie-compat.html

<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

Our layout/partials/head/head.html now look like this.

<head>
	{{ partial "head/meta" . }}
	<title>Fluid Media Productions</title>
	{{ partial "head/ie-compat" . }}
	{{ partial "head/includes" . }}
</head>

Now lets put together the full header.

<!DOCTYPE html>
<html lang='{{ .Site.Language.Lang }}'>

{{ partial "head/head" . }}

<body>
  <div class="bar top-bar">
		<div id="logo">
			<a href="{{ print "/" | absURL }}">
				<img src="{{ print "img/logo.png" | relURL }}" alt="logo" />
			</a>
		</div>
		<a href="#" id="menu-toggle"><span></span></a>
	</div>
  <nav>
		<ul class="pull-left social">
			{{ partial "social" . }}
		</ul>
		
   <ul class="pull-right">
   {{ range .Site.Menus.main }}
       <li><a href='{{ .URL }}'>{{- .Name -}}</a></li>
   {{ end }}
    </ul>
</nav>

And let’s commit all of that

git add .
git commit -S -m "Add header to theme"
git push

Let’s create a foot partials folder and create a partial for scripts.

layout/partials/foot/scripts.html

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="{{ print "/bootstrap/js/bootstrap.min.js" | relURL }}"></script>
<!-- Main Custom JS for this template -->
<script src="{{ print "js/plugins.js" | relURL }}"></script>
<script src="{{ print "js/main.js" | relURL }}"></script>

layouts/partials/social.html The social links are the same on the menu and footer so a partial for them is good. We’ll also get the names from site config.

<li><a href="https://twitter.com/{{ .Site.Params.twitter }}"><i class="fa fa-twitter"></i></a></li>
<li><a href="https://www.facebook.com/{{ .Site.Params.facebook }}"><i class="fa fa-facebook"></i></a></li>
<li><a href="https://www.instagram.com/{{ .Site.Params.instagram }}"><i class="fa fa-instagram"></i></a></li>
<li><a href="https://www.youtube.com/channel/{{ .Site.Params.youtube }}"><i class="fa fa-youtube"></i></a></li>

Now we put the full footer together.

layouts/partials/footer.html

<footer id="main-footer">
  <div class="container">
    <div class="row">		
      <div class="col-md-3 rp30">
        <div class="widget">
          <img src="{{ print "img/logo-light.png" | relURL }}" alt="logo" class="bm30" />
        </div>
      </div>	
      <div class="col-md-3 rp30">
        <div class="widget">
          <h5>About Us</h5>
          <p>Fluid Media Productions was started in 2016 by a 14 year old with an aspiring dream.<br> Fluid Media Productions adapts to the clients needs what ever they may be, big or small.</p>
        </div>
      </div>
      <div class="col-md-3 rp30">
        <div class="widget">
          <h5>Categories</h5>
          <ul>
            <li>Video Production</li>
            <li>Web Design</li>
            <li>Photography</li>
          </ul>
        </div>
      </div>
      <div class="col-md-3">
        <div class="widget">
          <h5>Instagram</h5>
          <div class="instafeed"></div>
        </div>
      </div>			
    </div>
  </div>
</footer>
<footer id="sub-footer">
  <div class="container">
    <div class="row">
      <div class="col-md-6">
        <p>© Fluid Media Productions {{ dateFormat "2006" now }}</p>
      </div>
      <div class="col-md-6">
        <ul class="pull-right social">
          {{ partial "social" . }}
        </ul>
      </div>
    </div>
  </div>
</footer>
{{ partial "foot/scripts" . }}
</body>
</html>

And commit

git add .
git commit -S -m "Add footer to theme"
git push

Index

We can now test all of this by including this in a blank index page and running the built in Hugo server.

layouts/index.html

{{ partial "header" . }}
{{ partial "footer" . }}

Run the server

hudo -D server

And we have a page! But no styling. Let’s add that.

1516209017886

So we need to copy bootstrap, img, fonts, css, js and video from the old site to the static folder in our theme. Let’s try again with styling.

Ahh! Much better!

1516209723801

And commit

git add .
git commit -S -m "Add static files"
git push

Page top

We shall put all bits of the index page in layout/partials/index. The first one is the simplest, a video and header.

layout/partials/index/top.html

<div 
		id="header-video"
		class="full-height black-wrapper" 
		style="width: 100%; height: 500px;" 
		data-vide-bg="mp4: video/ocean, webm: video/ocean, ogv: video/ocean, poster: video/ocean.jpg" 
		data-vide-options="position: 0% 50%">
		<div class="bar left-bar"></div>
		<div class="bar right-bar"></div>
		<div class="bar bottom-bar"></div>
		<div class="page-header text-center">
			<h1><small>Welcome to</small>Fluid Media Productions<small>A Small Boat in the Big Sea</small></h1>
		</div>
		<a id="down-link" href="#"><i class="icon-mouse"></i></a>
</div>

We can now include this in the index with

{{ partial "index/top" . }}

This is beginning to look good.

Screenshot_2018-01-17_17-44-36

And commit

git add .
git commit -S -m "Add top video"
git push

Displaying content on the homepage

Now here’s the real reason where moving to Hugo, to be able to easily edit our content. Although we have a slight problem, our site is basically a single page site but that’s not exactly what Hugo was designed for. But never fear code is here!

What we specialize in

Let’s start with “What we specialize in”. We can loop over each page that has a section of specialties, and output the HTML with the content filled.

<section id="services" class="page-section light-wrapper no-bottom">
  <div class="container-fluid">
    <div class="row">
      <div class="page-header text-center">
	    <h1>What we specialize in<small>We are good at this</small></h1>
      </div>
      {{ range where .Site.Pages "Section" "specialities" }}
        <div class="col-md-3 service even">
          <i class="fa fa-video-camera"></i>
          <h3>{{ .Title }}</h3>
          <p>{{ .Content }}</p>
          <a href="{{ .URL }}" class="btn btn-white tm15">Learn More</a>
        </div>
      {{ end }}
    </div>
  </div>
</section>

But we have a problem, this also displays the list page. So we add another where to check that ItPage is true.

{{ range where (where .Site.Pages "Section" "specialities") "IsPage" true }}

We also need a way to set the icon and a summary to display instead of the whole page content. We can do thing by appending to the markdown front matter. so this

---
title: "Video production"
---
Our team have over 4 years experience in video production. Now we want to share our skills with you by offering professionally made videos.

becomes

---
title: "Video production"
icon: "fa-video-camera"
summary: "Our team have over 4 years experience in video production. Now we want to share our skills with you by offering professionally made videos."
---
Full page

And our display code becomes

<div class="col-md-3 service even">
  <i class="fa {{ .Params.icon }}"></i>
  <h3>{{ .Params.Title }}</h3>
  <p>{{ .Params.summary }}</p>
  <a href="{{ .URL }}" class="btn btn-white tm15">Learn More</a>
</div>

We also need to start a new row every 4 blocks so we need to modify our range again to have an index.

{{ range $index, $element := where (where .Site.Pages "Section" "specialities") "IsPage" true }}
  <div class="col-md-3 service even">
    <i class="fa {{ $element.Params.icon }}"></i>
    <h3>{{ $element.Title }}</h3>
    <p>{{ $element.Params.summary }}</p>
    <a href="{{ $element.URL }}" class="btn btn-white tm15">Learn More</a>
  </div>
  {{ if modBool (add $index 1) 4 }}
  </div>
  <div class="row">
  {{ end }}
{{ end }}

And thats it. Relativity simple wasn’t it, but believe it not this took me the best part of two hours to figure out. And commit

git add .
git commit -S -m "Add specialties"
git push

Our work

So with a very similar template to the previous section we can add this section. Notice we don’t need to break every 4 here.

<section id="work" class="page-section dark-wrapper no-bottom">
    <div class="wrapper">
        <div class="page-header text-center">
            <h1>Our Work<small>Its Not Bad</small></h1>
        </div>
    </div>
    <div id="loader">
        <div class="item"></div>
    </div>
    <div id="container">
        {{ range $index, $element := where (where .Site.Pages "Section" "work") "IsPage" true }}
            <div class="item small">
                <div class="item-inner">
                    <a href="{{ $element.URL }}">
                        <img src="" alt="Portfolio Item" />
                        <div class="project-title">
                            <div class="title-wrapper">
                                <h3>{{ $element.Title }}</h3>
                                <span></span>
                            </div>
                        </div>
                    </a>
                </div>
            </div>
        {{ end }}
    </div>
</section>

Now the new bits. Each item can have tags associated with it and you can filter by tags, so first lets add the tags to the item markdown.

---
title: "PPD Gallery"
tags:
 - Photography
 - Development
---
Full page

We can now access these tags in the template. So this goes in the span element containing the tags. The if in the middle is to put a comma unless its the last item.

{{ range $tagIndex, $tag := $element.Params.tags }}
  {{ $tag }}{{ if not (eq $tagIndex (sub (len $element.Params.tags) 1))}},{{ end }}
{{ end }}

We can also change add this to the class definition on each item to allow filtering. We set it to lower and replace spaces with - to make it nice for a class.

{{ range $tagIndex, $tag := $element.Params.tags }}{{ lower (replace $tag " " "-" )}} {{ end }}

The last bit is somewhat more complicated because we have to get all the tags used to make the filtering buttons. Hugo has this thing called Scratch which is for temporary data while rendering. First well start off the tags slice by adding it to the scratch with the “All” tag defined.

{{ $.Scratch.Add "tags" (slice "All") }}

Next we iterate over each item

{{ range $element := where (where .Site.Pages "Section" "work") "IsPage" true }}
{{ end }}

Then inside there we get each tag.

{{ range $tag := $element.Params.tags }}

{{ end }}

And finally if it is not already in the slice we append it.

{{ if not (in ($.Scratch.Get "tags") $tag)}}
	{{ $.Scratch.Add "tags" (slice $tag) }}
{{ end }}

All of that together looks like this.

{{ $.Scratch.Add "tags" (slice "All") }}
{{ range $element := where (where .Site.Pages "Section" "work") "IsPage" true }}
    {{ range $tag := $element.Params.tags }}
		{{ if not (in ($.Scratch.Get "tags") $tag)}}
            {{ $.Scratch.Add "tags" (slice $tag) }}
        {{ end }}
    {{ end }}
{{ end }}

Then with this calculated slice we can add the filter list to the template

<ul id="filters">
  {{ range $tag := $.Scratch.Get "tags" }}
    <li>
      {{ if (eq $tag "All") }}
      	<a href=".item" class="btn active">All</a>
      {{ else }}
      	<a href=".{{ lower (replace $tag " " "-" )}}" class="btn">{{ $tag }}</a>
      {{ end }}
    </li>
  {{ end }}
</ul>

And thats it. Let’s commit

git add .
git commit -S -m "Add clients"
git push

I’m going to leave out the rest of the sections on the homepage as they’re all really the same and come back to this in a part 2 discussing anything else that came up and what I did for pages other then the home.