Landing pages and Hugo

A client of mine came to me with a problem. They have multiple partners that use my clients product for their customers and each of those partners needs a landing page to promote and onboard their users.

My client was creating those landing pages by copy-pasting some html code and editing everything manually. Which was obviously getting overwhelming for them since their partners kept growing and growing. They wanted a solution that was simple manage and allowed them to update one or all the websites without too much hassle.

The websites would live on my clients subdomains and be mostly identical but still have many features that would always be different, such as the name of the partner, logo, email, etc. And some features that would sometimes be different, such as the hero text, call to action and various other parts. Some features would mostly be the same though, like some generic signup text and other things.

The design

At first I was thinking about using color schemes and design features from each partner but after a little experimentation, and prior experience trying to accommodate for such a wide variety of unknown variables, we came to the conclusion that it would be very difficult to make it consistently good looking. Instead we decided to go with something more like with our own clean design that would be similar with the design of the product itself, so once a user would signup or login they would feel like they are in familiar territory.

The development

When it came to actually developing the sites my first thought was that I would be able to use Drupal for it. I have a long history with Drupal so I was confident I could make it pick up the subdomains as variables and use them to completely transform itself for each subdomain name, serving different content from one Drupal instance. I quickly developed a prototype that did exactly that.

After discussing pros and cons of my prototype and possible solutions with my client we decided that a static site generator would fit better into their current ecosystem. It would keep them from the burden of managing one more database that would be vulnerable to an attack that could damage their reputation.

I had never heard of anyone doing something like this using static site generators but I was thirsty for a good challenge so I didn't hesitate and got started doing some research.

Enter Hugo

Hugo was quick to make it to the top of my list. I had heard many people praising it and after digging into their documentation and forum I found out you could specify a different config file with a different publish path that would allow me to create multiple websites from a single source.

This would enable me use one config file for each website I needed to create and just change a couple of variables to create a completely different website with its own url, partner name, logo, subpages, contact email and other things that needed to change, all in a matter of minutes.

The main parts of the config files look something like this:

# ****  IMPORTANT!! - START  ****

# Change these variables to be partner-specific.

# The logo should be white and either a SVG or a PNG with a transparent background.
# If it's a PNG the height of the logo should be 128px (Which will then be scaled down to 64px to look crisp on retina screens)

partnerLogo = "/images/partnerlogo.png"

# filesystem path to write files to 
# This is where the partner website will be created and the routing system should be directed to.
publishDir = "public/partnername" # this should be same as public/slugname

[params]
  partnerName = "Example Name"
  partnerSlugName = "example"
  partnerSignupCode = "exampleSignupCode"
  partnerWebsite = "//www.example.com/"
  partnerContactMail = "info@example.com"
  ...

# ****  IMPORTANT!! - END  ****

  # OPTIONALLY EDIT - START

  ## Enable / Disable Sections
  enableDashboardSection = true
  enableVideoSection = false
  enableTestimonialsSection = false
  enablePaymentsSection = true
  enableSignupButton = true
    ... 

  ## Overwrite text
  ## The following text overwrites the default text located in data/text.toml
  ## It's not necessary to edit any of the following variables. Only do so if you want it different specificly for this partner.

  heroHeading = ""
  heroText = ""
  heroButtonText = ""

  introHeading = ""
  introText = ""

  dashboardHeading = ""
  dashboardSubHeading = ""
  dashboardFirstItemHeading = ""
  dashboardFirstItemText = ""
  dashboardSecondItemHeading = ""
  dashboardSecondItemText = ""
  dashboardThirdItemHeading = ""
  dashboardThirdItemText = ""

  testimonialsHeading = ""
  testimonialsSubHeading = ""
  testimonialsFirstQuoteName = ""
  testimonialsFirstQuoteText= ""
  testimonialsSecondQuoteName = ""
  testimonialsSecondQuoteText= ""
  ...

You may have noticed at the end there that all the variables were empty. This is because in most cases we don't want to change that text between individual partner websites. Instead the default text is located in a data file in data/text.toml

Then in the templates there is a conditional that checks whether the variable is empty. If it isn't then it uses the variable inside the partner file rather than the default data text file.

For example:

<h1>
  {{ if .Site.Params.heroHeading }}
    {{ .Site.Params.heroHeading }}
  {{ else }}
    {{ .Site.Data.text.heroHeading }}
  {{ end }}
</h1>

I was really impressed with Hugo and its flexibility when it comes to bending it to your will like that and use it for something it wasn't really made for. The main drawback with the way I did this is that you can't include inline links in those variables.

Given the number of partners we needed to create these websites for,we created a little bash script to take care of actually generating and updating all the sites. So if we need to update the design or fix a bug only one command is need to update tens, or perhaps hundreds in the future, of websites in one go.

I'm happy to report that the client was extremely happy with the how things were set up and was quick to set up 15 partner websites right away.