This is the multi-page printable view of this section. Click here to print.
Content
- 1: Content Mgmt
- 1.1: Hugo
- 1.1.1: Hugo Install
- 1.1.2: Docsy Install
- 1.1.3: Docsy Config
- 1.1.4: Docsy Operate
- 1.1.5: Docsy Github
- 2: Content Deployment
- 2.1: Local Git Deployment
- 3: Content Delivery
- 3.1: Cloudflare
1 - Content Mgmt
There are many ways to manage and produce web content. Traditionally, you’d use a large application with roles and permissions.
A more modern approach is to use a distributed version control system, like git, and a site generator.
Static Site Generators are gaining popularity as they produce static HTML with javascript and CSS that can be deployed to any Content Delivery Network without need for server-side processing.
Astro is great, as is Hugo, with the latter being around longer and having more resources.
1.1 - Hugo
Hugo is a Static Site Generator (SSG) that turns Markdown files into static web pages that can be deployed anywhere.
Like WordPress, you apply a ’theme’ to style your content. But rather than use a web-inteface to create content, you directly edit the content in markdown files. This lends itself well tomanaging the content as code and appeals to those who prefer editing text.
However, unlike other SSGs, you don’t have to be a front-end developer to get great results and you can jump in with a minimal investment of time.
1.1.1 - Hugo Install
Requirements
I use Debian in this example, but any apt-based distro will be similar.
Preparation
Enable and pin the Debian Backports and Testing repos so you can get recent versions of Hugo and needed tools.
Installation
Hugo requires git
and go
# Assuming you have enable backports as per above
sudo apt install -t bullseye-backports git
sudo apt install -t bullseye-backports golang-go
For a recent version of Hugo you’ll need to go to the testing repo. The extended version is recommended by Hugo and it’s chosen by default.
# This pulls in a number of other required packages, so take a close look at the messages for any conflicts. It's normally fine, though.
sudo apt install -t testing hugo
In some cases, you can just install from the Debian package with a lot less effort. Take a look at latest and copy the URL into a wget.
https://github.com/gohugoio/hugo/releases/latest
wget https://github.com/gohugoio/hugo/releases/download/v0.124.1/hugo_extended_0.124.1_linux-amd64.deb
Configuration
A quick test right from the quickstart page to make sure everything works
hugo new site quickstart
cd quickstart
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
echo "theme = 'ananke'" >> config.toml
hugo server
Open up a browser to http://localhost:1313/
and you you’ll see the default ananke-themed site.
Next Steps
The ananke theme you just deployed is nice, but a much better theme is Docsy. Go give that a try.
Links
1.1.2 - Docsy Install
Docsy is a good-looking Hugo theme that provides a landing page, blog, and a documentation sub-sites using bootstrap CSS.
The documentation site in particular let’s you turn a directory of text files into a documentation tree with relative ease. It even has a collapsible left nav bar. That is harder to find than you’d think.
Preparation
Docsy requires Hugo. Install that if you haven’t already. It also needs a few other things; postcss, postcss-cli, and autoprefixer from the Node.JS ecosystem. These should be installed in the project directory as version requirements change per theme.
mkdir some.site.org
cd some.site.org
sudo apt install -t testing nodejs npm
npm install -D autoprefixer
npm install -D postcss
npm install -D postcss-cli
Installation
Deploy Docsy as a Hugo module and pull in the example site so we have a skeleton to work with. We’re using git, but we’ll keep it local for now.
git clone https://github.com/google/docsy-example.git .
hugo server
Browse to http://localhost:1313 and you should see the demo “Goldydocs” site.
Now you can proceed to configure Docsy!
Updating
The Docsy theme gets regular updates. To incorporate those you only have to run this command. Do this now, actually, to get any theme updates the example site hasn’t incoporated yet.
cd /path/to/my-existing-site
hugo mod get -u github.com/google/docsy
Troubleshooting
hugo
Error: Error building site: POSTCSS: failed to transform “scss/main.css” (text/css)>: Error: Loading PostCSS Plugin failed: Cannot find module ‘autoprefixer’
And then when you try to install the missing module
The following packages have unmet dependencies: nodejs : Conflicts: npm npm : Depends: node-cacache but it is not going to be installed
You may have already have installed Node.JS. Skip trying to install it from the OS’s repo and see if npm
works. Then proceed with postcss install and such.
1.1.3 - Docsy Config
Let’s change the basics of the site in the config.toml
file. I put some quick sed commands here, but you can edit by hand as well. Of note is the Github integration. We prepoulate it here for future use, as it allows quick edits in your browser down the road.
SITE=some.site.org
GITHUBID=someUserID
sed -i "s/Goldydocs/$SITE/" config.toml
sed -i "s/The Docsy Authors/$SITE/" config.toml
sed -i "s/example.com/$SITE/" config.toml
sed -i "s/example.org/$SITE/" config.toml
sed -i "s/google\/docsy-example/$GITHUBID\/$SITE/" config.toml
sed -i "s/USERNAME\/REPOSITORY/$GITHUBID\/$SITE/" config.toml
sed -i "s/https:\/\/policies.google.com//" config.toml
sed -i "s/https:\/\/github.com\/google\/docsy/https:\/\/github.com\/$GITHUBID/" config.toml
sed -i "s/github_branch/#github_branch/" config.toml
If you don’t plan to translate your site into different languages, you can dispense with some of the extra languages as well.
# Delete the 20 or so lines starting at "lLanguage] and stopping at the "[markup]" section,
# including the english section.
vi config.tml
# Delete the folders from 'content/' as well, leaving 'en'
rm -rf content/fa content/no
You should also set a default meta description or the engine will put in in the bootstrap default and google will summarize all your pages with that
vi config.toml
[params]
copyright = "some.site.org"
privacy_policy = "/privacy"
description = "My personal website to document what I know and how I did it"
Keep and eye on the site in your browser as you make changes. When you’re ready to start with the main part of adding content, take a look at the next section.
Notes
You can’t dispense with the en folder yet, as it breaks some github linking functionality you may want to take advantage of later
1.1.4 - Docsy Operate
This is a quick excerpt from the Docsy Content and Customization docs. Definitely spend time with those after reading the overview here.
Directory Layout
Content is, appropriately enough, in the content
directory, and it’s subdirectories line up with the top-level navigation bar of the web site. About, Documentation, etc corresponds to content/about
, content/docs
and so on.
The directories and files you create will be the URL that you get with one important exception, filenames are converted to a ‘slug’, mimicking how index files work. For example, If you create the file docs/tech/mastadon.md
the URL will be /docs/tech/mastadon/
. This is for SEO (Search Engine Optimization).
The other thing you’ll see are _index.html
files. In the example above, the URL /docs/tech/
has no content, as it’s a folder. But you can add a _index.md
or .html to give it some. Avoid creating index.md
or tech.md
(a file that matches the name of a subdirectory). Either of those will block Hugo from generating content for any subdirectories.
The Landing Page and Top Nav Pages
The landing page itself is the content/_index.html
file and the background is featured-background.jpg. The other top-nav pages are in the content folders with _index
files. You may notice the special header variable “menu: main: weight: " and that is what flags that specific page as worth of being in the top menu. Removing that, or adding that (and a linkTitle) will change the top nav.
The Documentation Page and Left Nav Bar
One of the most important features of the Docsy template is the well designed documentation section that features a Section menu, or left nav bar. This menu is built automatically from the files you put in the docs
folder, as long as you give them a title. (See Front Matter, below). They are ordered by date but you can add a weight to change that.
It doesn’t collapse by default and if you have a lot of files, you’ll want to enable that.
# Search and set in your config.toml
sidebar_menu_compact = true
Front Matter
The example files have a section at the top like this. It’s not strictly required, but you must have at least the title or they won’t show up in the left nav tree.
---
title: "Examples"
---
Page Content and Short Codes
In addition to normal markdown or html, you’ll see frequent use of ‘shortcodes’ that do things that normal markdown can’t. These are built in to Hugo and can be added by themes, and look like this;
{{% blocks/lead color="dark" %}}
Some Important Text
{{% /blocks/lead %}}
Diagrams
Docsy supports mermaid and a few other tools for creating illustrations from code, such as KaTeX, Mermaid, Diagrams.net, PlantUML, and MarkMap. Simply use a codeblock.
```mermaid
graph LR
one --> two
```
Generate the Website
Once you’re satisfied with what you’ve got, tell hugo to generate the static files and it will populate the folder we configured earlier
hugo
Publish the Web Site
Everything you need is in the public
folder and all you need do is copy it to a web server. You can even use git, which I advise since we’re already using it to pull in and update the module.
Bonus Points
If you have a large directory structure full of markdown files already, you can kick-start the process of adding frontmatter like this;
find . -type f | \
while read X
do
TITLE=$(basename ${X%.*})
FRONTMATTER=$(printf -- "---\ntitle = ${TITLE}\n---")
sed -i "1s/^/$FRONTMATTER\n/" "$X"
done
1.1.5 - Docsy Github
You may have noticed the links on the right like “Edit this page” that takes one to Github. Let’s set those up.
On Github
Go to github and create a new repository. Use the name of your side for the repo name, such as “some.site.org”. If you want to use something else, you can edit your config.toml
file to adjust.
Locally
You man have noticed that Github suggested some next steps with a remote add
using the name “origin”. Docsy is already using that, however, from when you cloned it. So we’ll have to pick a new name.
cd /path/to/my-existing-site
git remote add github https://github.com/yourID/some.site.org
Let’s change our default banch to “main” to match Github’s defaults.
git branch -m main
Now we can add, commit and push it up to Github
git add --all
git commit -m "first commit of new site"
git push github
You’ll notice something interesting when you go back to look at Github; all the contributers on the right. That’s because you’re dealing with a clone of Docsy and you can still pull in updates and changes from original project.
It may have been better to clone it via github
2 - Content Deployment
Automating deployment as part of a general continuous integration strategy is best-practice these days. Web content should be similarly treated.
I.e. version controlled and deployed with git.
2.1 - Local Git Deployment
Overview
Let’s create a two-tiered system that goes from dev to prod using a post-commit trigger
graph LR Development --git / rsync---> Production
The Development system is your workstation and the Production system is a web server you can rsync to. Git commit will trigger a build and rsync.
I use Hugo in this example, but any system that has an output (or build) folder works similarly.
Configuration
The first thing we need is a destination.
Production System
This server probably uses folders like /var/www/XXXXX
for its web root. Use that or create a new folder and make yourself the owner.
sudo mkdir /var/www/some.site.org
sudo chown -R $USER /var/www/some.site.org
echo "Hello" > /var/www/some.site.org/index.html
Edit your web server’s config to make sure you can view that web page. Also check that rsync
is available from the command line.
Development System
Hugo builds static html in a public
directory. To generate the HTML, simply type hugo
cd /path/to/my-existing-site
hugo
ls public
We don’t actually want this folder in git and most themes (if you’re using Hugo) already have a .gitignore
file. Take a look and create/add to it.
# Notice /public is at the top of the git ignore file
cat .gitignore
/public
package-lock.json
.hugo_build.lock
...
Assuming you have some content, let’s add and commit it.
git add --all
git commit -m "Initial Commit"
Note: All of these git commands work because pulling in a theme initialized the directory. If you’re doing something else you’ll need to git init
.
The last step is to create a hook that will build and deploy after a commit.
cd /path/to/my-existing-site
touch .git/hooks/post-commit
chmod +x .git/hooks/post-commit
vi .git/hooks/post-commit
#!/bin/sh
hugo --cleanDestinationDir
rsync --recursive --delete public/ [email protected]:/var/www/some.site.org
This script ensures that the remote directory matches your local directory. When you’re ready to update the remote site:
git add --all
git commit --allow-empty -m "trigger update"
If you mess up the production files, you can just call the hook manually.
cd /path/to/my-existing-site
touch .git/hooks/post-commit
Troubleshooting
bash: line 1: rsync: command not found
Double check that the remote host has rsync.
3 - Content Delivery
3.1 - Cloudflare
- Cloudflare acts as a reverse proxy to hide your server’s IP address
- Takes over your DNS and directs requests to the closest site
- Injects JavaScript analytics
- If the browser’s “do not track” is on, JS isn’t injected.
- Can uses a tunnel and remove encryption overhead