Fixes #156, #176: Document Hugo and handle Multihost error better

parent c56229ca
......@@ -641,6 +641,48 @@ The statistics are ephemeral as they are only kept in memory and they reset any
The statistics are very basic and they’re there only to give an idea about which parts of your site are most popular as well as to highlight missing pages, etc., They’re not there so you can spy on people (if you want to do that, this is not the tool for you).
## Static site generation
As of version 12.11.0, Site.js includes the [Hugo static site generator](
To create a new Hugo site and start serving it:
mkdir my-site
__Note:__ During development, this feature uses Site.js’s live reload instead of Hugo’s. Your web page must have at least a `<body>` tag for it to work.
### How it works
If Site.js finds a folder called _.hugo_ in your site’s root, it will build it using its integrated Hugo instance (you don’t need to install Hugo separately) and place the generated files into a folder called _.generated_ in your site’s root. It will also automatically serve these files.
You can pass any command you would normally pass to Hugo using Site.js’s integrated Hugo instance:
site hugo [any valid Hugo command]
Please see [the Hugo documentation]( for detailed information on how Hugo works.
### Mounting Hugo sites
Site.js will automatically mount files in the _.hugo_ directory at your site’s root.
If you want the generated Hugo site to be mounted at a different path, include the path structure you want in the name of the hugo folder, separating paths using two dashes. For example:
Folder name | Mount path |
------------------------- | ------------------ |
.hugo | / |
.hugo--docs | /docs |
.hugo--second-level--blog | /second-level/blog |
You can include any number of Hugo sites in your site and mount them at different paths and the results will be weaved together into the _.generated_ folder. We call this feature… _ahem_… Hugo Weaving (we’ll show ourselves out).
All regular Site.js functionality is still available when using Hugo generation. So you can, for example, have your blog statically-generated using Hugo and extend it using locally-hosted dynamic comments.
__Note:__ Hugo’s [Multilingual Multihost mode]( is _not_ supported.
## Dynamic sites
You can specify routes with dynamic functionality by specifying HTTPS and WebSocket (WSS) routes in two ways: either using DotJS – a simple file system routing convention ala PHP, but for JavaScript – or through code in a _routes.js_ file.
......@@ -447,7 +447,21 @@ class Site {
const baseURL = ? globalBaseURL : localBaseURL
// Start the server and await the end of the build process.
const { hugoServerProcess, hugoBuildOutput } = await this.hugo.serve(sourcePath, destinationPath, baseURL)
let hugoServerProcess, hugoBuildOutput
try {
const response = await this.hugo.serve(sourcePath, destinationPath, baseURL)
hugoServerProcess = response.hugoServerProcess
hugoBuildOutput = response.hugoBuildOutput
} catch (error) {
let errorMessage = error
if (errorMessage.includes('--appendPort=false not supported when in multihost mode')) {
errorMessage = 'Hugo’s Multilingual Multihost mode is not supported in Site.js.'
this.log(` ❌ ❨site.js❩ Could not start Hugo server. ${errorMessage}`)
// At this point, the build process is complete and the .generated folder should exist.
......@@ -459,7 +473,13 @@ class Site {
hugoServerProcess.stderr.on('data', (data) => {
const lines = data.toString('utf-8').split('\n')
lines.forEach(line => this.log(`${Site.HUGO_LOGO} [ERROR] ${line}`))
lines.forEach(line => {
this.log(`${Site.HUGO_LOGO} [ERROR] ${line}`)
if (line.includes('panic: runtime error: index out of range [1] with length 1')) {
this.log('\n 📎 ❨site.js❩ Looks like you configured Multilingual Multihost mode in Hugo. This is not supported.\n')
// Save a reference to all hugo server processes so we can
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment