Background
Historically, we used the terms site and project interchangeably. With monolingual projects, that was essentially correct. With multilingual projects, it was not correct, in that every language is internally represented as a separate site. So, we were a bit lazy with our word selection.
With the introduction of the multidimensional content model in v0.153.0, the distinction between site and project becomes much more important. For example, a software documentation project in 4 languages with 3 versions is internally represented by 12 sites. In a single-host setup, all 12 sites will be served from the same URL. With a multihost setup, there would be 4 URLs, one for each language.
So, going forward, we need to use these words carefully.
Definitions
A site is a specific instance of your project representing a unique combination of language, role, and version. While a simple project may consist of only a single site, Hugo’s multidimensional content model allows a single codebase to generate a matrix of sites simultaneously
A project is a collection of components used to generate one or more sites. While a project may consist of only a single site, Hugo allows a single project to generate a matrix of sites based on language, role, and version. The project serves as the parent container for the common assets and logic used across all sites within the build.
Deprecated methods
In several places, our API did not align with this model. For example, accessing files in the data directory via Site.Data is conceptually inaccurate; the data directory is tied to the project, not to an individual site.
To align our API with this content model, we have made the following changes in v0.156.0:
| Deprecated method | Replacement | Explanation |
|---|---|---|
Site.Data |
hugo.Data |
Data belongs to the project, not to a site. |
Site.Sites |
hugo.Sites |
Sites belong to the project, not to a site. |
Page.Sites |
hugo.Sites |
Sites belong to the project, not to a page. |
Site.AllPages |
See Example A | This method does not return all pages for a site. It returns all pages for all languages, which is an odd construct within the new content model. |
Site.BuildDrafts |
Page.Draft |
This is also an odd construct, reporting whether draft publishing is enabled for the current build, which will return true even when there is no draft content. |
Site.Languages |
See Example B | We’ve seen this used in language selectors, which doesn’t make a lot of sense. Language selectors should be based on the current page, not the site or project. |
Example A – Range over all pages in a project
If you need to range over all pages in a project, range over the sites, then range over the pages within each site.
{{ range hugo.Sites }}
{{ range .Pages}}
...
{{ end }}
{{ end }}
Example B – Language selector
If you need to create a language selector, rotate through the translations of the current page.
{{ with .Rotate "language" }}
<nav class="language-switcher">
<ul>
{{ range . }}
{{ if eq .Site.Language $.Site.Language }}
<li class="active"><a aria-current="page" href="{{ .Permalink }}">{{ .Site.Language.LanguageName }}</a></li>
{{ else }}
<li><a href="{{ .Permalink }}">{{ .Site.Language.LanguageName }}</a></li>
{{ end }}
{{ end }}
</ul>
</nav>
{{ end }}
Identify usage of deprecated methods
Run hugo build --logLevel info to see if your project uses any of the deprecated methods above. In about 3 months, the info log deprecation messages will be elevated to warnings, and about 12 months after that, they will be elevated to errors. This is in accordance with our published deprecation process.