Switching the lights on: Hugo vs Hugo config files
Tags: staticsite, webdev, blogging, deployment
Published: 2018-08-17 12:54:37

---
title: Switching the lights on: Hugo vs Hugo config files
published: true
description: A simple Hugo blog setup
tags: static site, webdev, blogging, deployment
canonical_url: https://codewithhugo.com/switching-the-lights-on-hugo-vs-hugo-config-files/
---

> A simple Hugo blog setup

The story of getting [codewithhugo.com](https://codewithhugo.com) up and running.

The **tl;dr** is the following: 

- I always rave about my blog setup, it’s simple, fast and just works
- I used [Hugo](http://gohugo.io), “The world’s fastest framework for building websites”, a static site generator
- I used a theme, [casper-two](https://github.com/eueung/hugo-casper-two), which is a Hugo port of the https://ghost.org/ default theme
- I deployed to GitHub pages behind Cloudflare *.

There's been an update in the deployment saga, read it here: ["A tiny case study about migrating to Netlify when disaster strikes at GitHub, featuring Cloudflare"](https://codewithhugo.com/a-tiny-case-study-about-migrating-to-netlify-when-disaster-strikes-at-github-featuring-cloudflare/)

> This was sent out on the [Code with Hugo newsletter](https://buttondown.email/hugo) last Monday.
> [Subscribe](https://buttondown.email/hugo) to get the latest posts right in your inbox (before anyone else).

- [Why I didn’t build my own website 🏃‍♂️](#why-i-didn-t-build-my-own-website)
- [Picking a theme and overriding little things 🖼](#picking-a-theme-and-overriding-little-things)
- [Enabling syntax highlighting 🎨](#enabling-syntax-highlighting)
- [Image and things 🤳](#image-and-things)
    - [Resize using imagemagick](#resize-using-imagemagick)
    - [Convert PNG to JPG](#convert-png-to-jpg)
- [Deployment and more](#deployment-and-more)
    - [Deployment script](#deployment-script)
    - [“Cleaning up” with Node and npm scripts 🙄](#cleaning-up-with-node-and-npm-scripts)
        - [Minify and optimise CSS](#minify-and-optimise-css)
        - [Imageoptim](#imageoptim)
    - [Running in development mode](#running-in-development-mode)
- [Cloudflare setup](#cloudflare-setup)

## Why I didn’t build my own website 🏃‍♂️

I’m not a designer, and Code with Hugo wasn’t about me learning or showing off my website-making skills, it was about writing content consistently.
That’s why I used a template, Hugo and GitHub pages. It’s a static site with a CDN (Cloudflare) in front so pretty much nothing can go wrong. That means I *have* to focus on the content.

## Picking a theme and overriding little things 🖼

[Casper Two](https://github.com/eueung/hugo-casper-two), the [ghost.org](https://ghost.org) default theme is awesome.
I tweaked a couple of things, as you can see in my `static/overrides.css`:

```css
.site-title {
    font-weight: 200;
    font-size: 8rem;
}
.collection-title {
    text-transform: uppercase;
    font-size: 6rem;
    font-weight: 300;
}
.site-header:before {
    background: rgba(0, 0, 0, 0.5);
}
// This was only needed when I enabled pygments for syntax highlighting
.site-wrapper {
    min-height: auto;
}
.highlight {
    width: 100%;
}
```

Adding that stuff in `config.toml`:
```toml
[params]
    customCSS = "overrides.css"
```

That’s all the CSS I wrote 🙂 .

## Enabling syntax highlighting 🎨

codewithhugo.com didn’t have syntax highlighting for a while, 😕 and I even started whining.

![<blockquote><p>When <a href="https://twitter.com/ThePracticalDev?ref_src=twsrc%5Etfw">@ThePracticalDev</a> has better syntax highlighting than your blog 😂😂 does anyone  know how to sort out <a href="https://twitter.com/GoHugoIO?ref_src=twsrc%5Etfw">@GoHugoIO</a> syntax highlighting <a href="https://t.co/PBJAolNlDY">https://t.co/PBJAolNlDY</a> <a href="https://t.co/2PXyY7l0dV">pic.twitter.com/2PXyY7l0dV</a></p>&mdash; Hugo Di Francesco (@hugo__df) <a href="https://twitter.com/hugo__df/status/984699817531203584?ref_src=twsrc%5Etfw">13 April 2018</a></blockquote>](https://d2mxuefqeaa7sj.cloudfront.net/s_3F94311F9467F8A3B0176D80603BB5F981B49B6D0E353DBB8DC8DC3DFEB48211_1533578484452_image.png)


I tried a couple of times to enable it, it was meant to be as simple as putting the following in `config.toml`:
```toml
pygmentsUseClassic=false
pygmentsCodefences=true
pygmentsUseClasses=true
```

This stumped me for months, finally it turns out I was doing this
```toml
[params]
  pygmentsUseClassic=false
  pygmentsCodefences=true
  pygmentsUseClasses=true
```

Classic case of blinders being on.
As part of this process I got `highlight.js` working, but in keeping with the “It’s a static site so pretty much nothing can go wrong” it felt a bit wrong to use a client-side library to highlight stuff.
Since syntax highlighting is done at build-time, no `highlight.js` JS in `layouts/partials/js.html` :
```html
<!-- <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script> -->
```

If you want it to actually look nice we need to generate the `syntax.css`:
```sh
$ hugo gen chromastyles --style=monokai > ./static/syntax.css
```

And hook it up in `config.toml`:
```toml
[params]
  customCSS = [
    "overrides.css",
    "syntax.css"
  ]
```

## Image and things 🤳

### Resize using imagemagick

Create a `/static/img` folder using:

```sh
$ mkdir -p static/img
```

Then we can resize whatever image I’m going to use (usually for the post cover photos):

```sh
$ convert my-image.jpg -resize 1500x1500 ./static/img/my-image.jpg
```

### Convert PNG to JPG

I use Alchemy to convert from PNG to JPG https://dawnlabs.io/alchemy/, although I thing ImageMagick can do it as well.

## Deployment and more

### Deployment script 

`./scripts/deploy.sh`, as taken from [the Hugo docs](https://gohugo.io/hosting-and-deployment/hosting-on-github/#put-it-into-a-script-1):
```bash
#!/bin/bash
echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"
# Build the project.
hugo # if using a theme, replace with `hugo -t <YOURTHEME>`
# Go To Public folder
cd public
# Add changes to git.
git add .
# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
    then msg="$1"
fi
git commit -m "$msg"
# Push source and build repos.
git push origin master
# Come Back up to the Project Root
cd ..
```


### “Cleaning up” with Node and npm scripts 🙄 

This is the full `package.json` (minus the stuff that's not necessary):
```json
{
    "name": "codewithhugo",
    "description": "Repo for content of codewithhugo.com.",
    "config": {
      "syntax": "static/syntax",
      "overrides": "static/overrides",
      "images": "static/img"
    },
    "scripts": {
      "build": "concurrently --names \"SYNTAX,OVERRIDES,IMAGES\" -c \"bgBlue.bold,bgMagenta.bold,bgYellow.bold\" \"npm:build:css:syntax\" \"npm:build:css:overrides\" \"npm run build:imageoptim\"",
      "predeploy": "npm run build",
      "deploy": "./scripts/deploy.sh",
      "serve": "./scripts/serve.sh",
      "start": "npm run dev",
      "dev": "concurrently --names \"CSS,HUGO\" -c \"bgBlue.bold,bgMagenta.bold\" \"npm:watch:css\" \"npm:serve\"",
      "watch:css": "concurrently \"npm run build:css:syntax -- --watch --map inline\" \"npm run build:css:overrides -- --watch --map inline\"",
      "build:css:syntax": "csso -i $npm_package_config_syntax.css -o $npm_package_config_syntax.min.css --stat",
      "build:css:overrides": "csso -i $npm_package_config_overrides.css -o $npm_package_config_overrides.min.css --stat",
      "build:imageoptim": "imageoptim $npm_package_config_images"
    },
    "author": "Hugo Di Francesco",
    "homepage": "https://github.com/HugoDF/codewithhugo#readme",
    "devDependencies": {
      "concurrently": "^3.6.0",
      "csso-cli": "^1.1.0",
      "imageoptim-cli": "^2.0.3"
    }
}
```

Let’s walk through what happens when I run `npm run deploy`, these three tasks are the main ones:
```json
"build": "concurrently --names \"SYNTAX,OVERRIDES,IMAGES\" -c \"bgBlue.bold,bgMagenta.bold,bgYellow.bold\" \"npm:build:css:syntax\" \"npm:build:css:overrides\" \"npm run build:imageoptim\"",
"predeploy": "npm run build",
"deploy": "./scripts/deploy.sh",
```

A feature of `npm` is that if you have a script called `something`  you can defined another script `presomething` that will run before `something` whenever it’s called.
So before deploying, we `npm run build`.
`npm run build` runs a couple of tasks in parallel with `concurrently` ([https://www.npmjs.com/package/concurrently](https://www.npmjs.com/package/concurrently)): 

- `npm:build:css:syntax` which is `concurrently`-specific shorthand for `npm run build:css:syntax`
- `npm:build:css:overrides` which is `concurrently`-specific shorthand for `npm run build:css:overrides`
- `npm run build:imageoptim`

#### Minify and optimise CSS

```json
"build:css:syntax": "csso -i $npm_package_config_syntax.css -o $npm_package_config_syntax.min.css --stat",
"build:css:overrides": "csso -i $npm_package_config_overrides.css -o $npm_package_config_overrides.min.css --stat",
```

`build:css:syntax` and `build:css:overrides` pretty much run the same command but on different files. Namely the files are `$npm_package_config_syntax.css` and `$npm_package_config_overrides.css` which interpolates npm_config syntax  and evaluate to `static/syntax.css` and `static/overrides.css` (see `config.syntax` and `config.overrides` in `package.json`. We use https://github.com/css/csso-cli, which pretty much just minifies the CSS.

The optimised CSS files get output as `static/syntax.min.css` and `static/overrides.min.css`, which I also update in the `config.toml`:
```toml
[params]
  customCSS = [
    "overrides.min.css",
    "syntax.min.css"
  ]
```

#### Imageoptim
A similar approach is used for `build:imageoptim`:

```json
"build:imageoptim": "imageoptim $npm_package_config_images"
```

It runs [imageoptim-cli](https://github.com/JamieMason/ImageOptim-CLI) on the contents of `$npm_package_config_images` (which expands to `static/img`).

### Running in development mode

Now that I’ve got a build step in place… the problem is that I need to watch for changes etc in development as well, which are the following scripts, from `package.json`:

```json
"serve": "./scripts/serve.sh",
"start": "npm run dev",
"dev": "concurrently --names \"CSS,HUGO\" -c \"bgBlue.bold,bgMagenta.bold\" \"npm:watch:css\" \"npm:serve\"",
"watch:css": "concurrently \"npm run build:css:syntax -- --watch --map inline\" \"npm run build:css:overrides -- --watch --map inline\"",
```

`./scripts/serve.sh`:
```sh
hugo serve . -F
# -D will serve even draft posts
# -F will serve future posts
```

I like not having to change the dates of my posts when they’re not ready to be published yet, so I use the `-F` flag. If I don’t want a certain post to appear in development I’ll use `draft: true` in the frontmatter.
`npm run dev` just runs the `csso-cli` tasks in watch mode as well as the Hugo dev server.

# Getting a full RSS feed 😄 

The default Hugo RSS feed doesn’t have the full post contents, it just has the excerpt (what would display on the homepage tiles in my case).
The problem with that is… well that the RSS feed doesn’t have full post contents.
I knew it was a problem but as usual I never got round to fixing it until I embarrassed myself while promoting it 😄:


![<blockquote><p>If you have a blog and write/share useful things (big or small) about Web design / front-end dev and you provide an RSS feed to the blog, please respond to this tweet w/ the URL for it — I’d like to add more useful content feeds to my reader. 🙌🏻💃</p>&mdash; Sara Soueidan (@SaraSoueidan) <a href="https://twitter.com/SaraSoueidan/status/1020288178597613569?ref_src=twsrc%5Etfw">20 July 2018</a></blockquote>](https://d2mxuefqeaa7sj.cloudfront.net/s_3F94311F9467F8A3B0176D80603BB5F981B49B6D0E353DBB8DC8DC3DFEB48211_1533580523884_image.png)

And my reply to that:

> Hey there, I write at [https://codewithhugo.com](https://t.co/tkBYwl47Q6), I don&#39;t think the RSS feed I&#39;ve got actually has the full posts though 🙈</p>&mdash; Hugo Di Francesco (@hugo__df) 21 July 2018</blockquote>


To fix that I found https://randomgeekery.org/2017/09/15/full-content-hugo-feeds/, (where there’s a full explanation of what we’re doing). Essentially it boils down to creating the following 
`layouts/_default/rss.xml`:

```xml
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
    <title>{{ if eq  .Title  .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
    <link>{{ .Permalink }}</link>
    <description>Recent content {{ if ne  .Title  .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
    <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
    <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
    <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
    <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
    <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
    {{ with .OutputFormats.Get "RSS" }}
        {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
    {{ end }}
    {{ range .Pages }}
    <item>
        <title>{{ .Title }}</title>
        <link>{{ .Permalink }}</link>
        <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
        {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
        <guid>{{ .Permalink }}</guid>
        <description>{{ .Content | html }}</description>
    </item>
    {{ end }}
    </channel>
</rss>
```

Which is just the default template except instead of:

```xml
<description>{{ .Summary | html }}</description>
```

We do:

```xml
<description>{{ .Content | html }}</description>
```

This make the built `index.xml` file huge since it’s putting every post’s full contents, so again on https://randomgeekery.org/2017/09/15/full-content-hugo-feeds/, I decided to limit the number of feed items to 15 (instead of 20 suggested in that post) that’s an update in `config.toml`:

```toml
rssLimit = 15
```

Full credit for this to this post https://randomgeekery.org/2017/09/15/full-content-hugo-feeds/, which actually explains the how and why of what has been done.

## Cloudflare setup

I flipped on a couple of settings, notably forcing HTTPS: Cloudflare Dashboard > Crypto > Always use HTTPS > On and in the same section Crypto > Automatic HTTPS Rewrites > On.

I increased the Caching > Browser Cache Expiration to 8 days (could/should be more but I don’t want to have to version my assets) and switched on Caching > Always Online™ so that should GitHub Pages fall down, Cloudflare will still serve my content and all would be well.

That’s pretty much all of my Hugo setup for [codewithhugo.com](https://codewithhugo.com) short of a couple of extra images and setting strings in `config.toml`.

[Parker Whitson](https://unsplash.com/@parkerkwhitson?utm_medium=referral&amp;utm_campaign=photographer-credit&amp;utm_content=creditBadge)