I’ve built a website with static content for my AWS-education program. This website is used by different type of users. Students, pro-level students, and trainers. I might want to add more types of users in the future. I want to use the same code base and host different rendered websites for each group. At the end of this blog post you can use the following command to generate a website for a specific audience:
hugo -e professional
hugo -e trainer
hugo server -e trainer
It took some time to figure out what feature I could use to get this done properly. Abusing the multilanguage system didn’t work out well. I decided to use the configuration system. According the documentation, the main purpose is to have a different production and development website (aka environment). I think I can use that!
Never heard of Hugo?
Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. Learn more. It works in a few simple steps:
- Download/install hugo (
brew install hugo
).- Create a
/config.yaml
with a few settings- Create a
/content
directory with your site structure in directories and some markdown files (i.e. index.md)- Create (or download) a theme and store this in
/themes
- Run
hugo server
to live render the website on your computer, or justhugo
and upload the/public
folder to a static website hosting like S3 or Amplify.
This blog post is structured in three steps:
Enjoy reading!
I only have a single config.yaml
file in the root of my project. To get more environments, I’ve to create a directory /config/_default
. The old config is then copied to /config/_default/config.yaml
. If you have a config.toml, that works the same. Then I create 2 new directories: /config/professional
and /config/trainer
. Now I create an empty file params.yaml
and config.yaml
in each of these folders. This is the result:
├── config/
│ ├── _default
│ │ └── config.yaml
│ ├── professional
│ ├── config.yaml
│ │ └── params.yaml
│ └── trainer
│ ├── config.yaml
│ └── params.yaml
├── content
│ └── ...
├── themes
└── ...
The /config/trainer/config.yaml
contains a different title
for this Site. You could of course change all other settings, they are merged with the default. Both /config/professional/params.yml
and /config/trainer/params.yaml
contain a parameter audience
that contains a list of audiences. For example, the trainer configuration has access to all content:
audience: ["professional", "trainer"]
Create a Hugo shortcode in your theme /theme/themename/layouts/shortcodes/audience.html
or your site /layouts/shortcodes/audience.html
, the last one is recommended. Add the following code to that file. If audience is not set, it just shows the page. If audience is set, it will check if the audience is also in the site configuration. If yes, it shows the page. If no, it writes some hidden comments in HTML. If a second string was provided, it will show this information in the browser. For example: “Validate your results together with your trainer.”.
|
|
Now edit a content file where you want to add a piece of content being showed or hidden, depending on the configuration.
|
|
The previous discussed option is an ideal way to block access to content blocks within a page. To block a complete page, you could copy the following template, find {{ .Content }}
in the templates. If you use a third party template, I recommend to first copy the layouts from /themes/themename/layouts/
to /layouts/
and only change those, leaving the third party theme intact.
|
|
Now add audience: "professional"
to the frontmatter of another page. A page that you want to hide for users. If the site was rendered for the specified audience, the page will be visible, otherwise it shows an Access Denied.
|
|
We have learned how to make use of a single codebase for a Hugo static website, and let it generate different content for different audiences. I host every page with an S3 bucket. And I use a CloudFront distribution with a Lambda@Edge custom authorizer to protect access to these websites. I might want to write my own blog post about this setup somewhere in the future.
If you have any feedback, please let me know.
-Martijn
Photo by Nicholas Green on Unsplash