This is the multi-page printable view of this section. Click here to print.
Content and Customization
1 - Adding Content
So you’ve got a new Hugo website with Docsy, now it’s time to add some content! This page tells you how to use the theme to add and structure your site content.
Content root directory
You add content for your site under the content root directory of your Hugo site project - either content/
or a language-specific root like content/en/
. The main exception here is static files that you don’t want built into your site: you can find out more about where you add these below in Adding static content. The files in your content root directory are typically grouped in subdirectories corresponding to your site’s sections and templates, which we’ll look at in Content sections and templates.
You can find out more about Hugo directory structure in Directory Structure Explained.
Content sections and templates
Hugo builds your site pages using the content files you provide plus any templates provided by your site’s theme. These templates (or “layouts” in Hugo terminology) include things like your page’s headers, footers, navigation, and links to stylesheets: essentially, everything except your page’s specific content. The templates in turn can be made up of partials: little reusable snippets of HTML for page elements like headers, search boxes, and more.
Because most technical documentation sites have different sections for different types of content, the Docsy theme comes with the following templates for top-level site sections that you might need:
docs
is for pages in your site’s Documentation section.blog
is for pages in your site’s Blog.community
is for your site’s Community page.
It also provides a default “landing page” type of template with the site header and footer, but no left nav, that you can use for any other section. In this site and our example site it’s used for the site home page and the About page.
Each top-level section in your site corresponds to a directory in your site content root. Hugo automatically applies the appropriate template for that section, depending on which folder the content is in. For example, this page is in the docs
subdirectory of the site’s content root directory content/en/
, so Hugo automatically applies the docs
template. You can override this by explicitly specifying a template or content type for a particular page.
If you’ve copied the example site, you already have appropriately named top-level section directories for using Docsy’s templates, each with an index page ( _index.md
or index.html
) page for users to land on. These top-level sections also appear in the example site’s top-level menu.
Custom sections
If you’ve copied the example site and don’t want to use one of the provided content sections, just delete the appropriate content subdirectory. Similarly, if you want to add a top-level section, just add a new subdirectory, though you’ll need to specify the layout or content type explicitly in the frontmatter of each page if you want to use any existing Docsy template other than the default one. For example, if you create a new directory content/en/amazing
and want one or more pages in that custom section to use Docsy’s docs
template, you add type: docs
to the frontmatter of each page:
+++
title = "My amazing new section"
weight = 1
type = "docs"
description = '''
A special section with a docs layout.
'''
+++
---
title: "My amazing new section"
weight: 1
type: docs
description: >
A special section with a docs layout.
---
{
"title": "My amazing new section",
"weight": 1,
"type": "docs",
"description": "A special section with a docs layout.\n"
}
Alternatively, create your own page template for your new section in your project’s layouts
directory based on one of the existing templates.
You can find out much more about how Hugo page layouts work in Hugo Templates. The rest of this page tells you about how to add content and use each of Docsy’s templates.
Alternative site structure
As noted above, by default your site has a home page (using the _default
layout), a docs section under /docs/
, a blog section under /blog/
and a community section under /community/
. The type of each section (which determines the layout it uses) matches its directory name.
In some cases, you may want to have a different directory structure, but still make use of Docsy’s layouts. A common example is for a “docs site”, where most of the pages (including the home page) use the docs layout, or perhaps you’d rather have a /news/
directory treated with the blog layout.
Since Hugo 0.76, this has become practical without copying layouts to your site, or having to specify type: blog
on every single page by making use of target specific cascading front matter.
For example, for the /news/
section, you can specify the following front matter in the index page which will change the type of the section and everything below it to “blog”:
+++
title = "Latest News"
linkTitle = "News"
[menu.main]
weight = 30
[[cascade]]
type = "blog"
+++
---
title: "Latest News"
linkTitle: "News"
menu:
main:
weight: 30
cascade:
- type: "blog"
---
{
"title": "Latest News",
"linkTitle": "News",
"menu": {
"main": {
"weight": 30
}
},
"cascade": [
{
"type": "blog"
}
]
}
If you want to create a “docs” site, specifying something like the following in the top level _index.md
will set all top level sections to be treated as “docs”, except for “news”:
+++
title = "My Wonderful Site"
[[cascade]]
type = "blog"
toc_root = true
[cascade._target]
path = "/news/**"
[[cascade]]
type = "docs"
[cascade._target]
path = "/**"
+++
---
title: "My Wonderful Site"
cascade:
- type: "blog"
toc_root: true
_target:
path: "/news/**"
- type: "docs"
_target:
path: "/**"
---
{
"title": "My Wonderful Site",
"cascade": [
{
"type": "blog",
"toc_root": true,
"_target": {
"path": "/news/**"
}
},
{
"type": "docs",
"_target": {
"path": "/**"
}
}
]
}
Note the addition of toc_root
here. Setting that to true for a section causes it to be treated as a separate part of the site, with its own left hand navigation menu.
An example docs-based site that uses this technique can be found at the mostly docs repo.
Page frontmatter
Each page file in a Hugo site has metadata frontmatter that tells Hugo about the page. You specify page frontmatter in TOML, YAML, or JSON (our example site and this site use YAML). Use the frontmatter to specify the page title, description, creation date, link title, template, menu weighting, and even any resources such as images used by the page. You can see a complete list of possible page frontmatter in Front Matter.
For example, here’s the frontmatter for this page:
+++
title = "Adding Content"
linkTitle = "Adding Content"
weight = 1
description = '''
Add different types of content to your Docsy site.
'''
+++
---
title: "Adding Content"
linkTitle: "Adding Content"
weight: 1
description: >
Add different types of content to your Docsy site.
---
{
"title": "Adding Content",
"linkTitle": "Adding Content",
"weight": 1,
"description": "Add different types of content to your Docsy site.\n"
}
The minimum frontmatter you need to provide is a title: everything else is up to you! However, if you leave out the page weight, your navigation may get a little disorganized. You may also want to include description
since Docsy uses that to generate the meta description
tag used by search engines. See Search Engine Optimization (SEO) meta tags for details.
Page contents and markup
By default you create pages in a Docsy site as simple Markdown or HTML files with page frontmatter, as described above. As of version 0.100, Goldmark is the only Markdown parser supported by Hugo.
Tip
If you’ve been using versions of Hugo before 0.60 that use BlackFriday
as its Markdown parser, you may need to make some small changes to your site to work with the current Goldmark
Markdown parser. In particular, if you cloned an earlier version of our example site, add the following to your config.toml
/config.yaml
/config.json
to allow Goldmark to render raw HTML as well as Markdown:
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
markup:
goldmark:
renderer:
unsafe: true
{
"markup": {
"goldmark": {
"renderer": {
"unsafe": true
}
}
}
}
In addition to your marked-up text, you can also use Hugo and Docsy’s shortcodes: reusable chunks of HTML that you can use to quickly build your pages. Find out more about shortcodes in Docsy Shortcodes.
Note
Hugo also supports adding content using other markups using external parsers as helpers. For example, you can add content in RST using rst2html
as an external parser (though be aware this does not support all flavors of RST, such as Sphinx RST). Similarly, you can use asciidoctor
to parse Asciidoc files, or pandoc
for other formats.
External parsers may not be suitable for use with all deployment options, as you’ll need to install the external parser and run Hugo yourself to generate your site (so, for example, you won’t be able to use Netlify’s continuous deployment feature). In addition, adding an external parser may cause performance issues building larger sites.
Working with links
Hugo lets you specify links using normal Markdown syntax, though remember that you need to specify links relative to your site’s root URL, and that relative URLs are left unchanged by Hugo in your site’s generated HTML.
Alternatively you can use Hugo’s helper ref
and relref
shortcodes for creating internal links that resolve to the correct URL. However, be aware this means your links will not appear as links at all if a user views your page outside your generated site, for example using the rendered Markdown feature in GitHub’s web UI.
You can find (or add!) tips and gotchas for working with Hugo links in Hugo Tips.
Content style
We don’t mandate any particular style for your page contents. However, if you’d like some guidance on how to write and format clear, concise technical documentation, we recommend the Google Developer Documentation Style Guide, particularly the Style Guide Highlights.
Page bundles
You can create site pages as standalone files in their section or subsection directory, or as folders where the content is in the folder’s index page. Creating a folder for your page lets you bundle images and other resources together with the content.
You can see examples of both approaches in this and our example site. For example, the source for this page is just a standalone file /content/en/docs/adding-content.md
. However the source for Docsy Shortcodes in this site lives in /content/en/docs/adding-content/shortcodes/index.md
, with the image resource used by the page in the same /shortcodes/
directory. In Hugo terminology, this is called a leaf bundle because it’s a folder containing all the data for a single site page without any child pages (and uses index.md
without an underscore).
You can find out much more about managing resources with Hugo bundles in Page Bundles.
Adding docs and blog posts
The template you’ll probably use most often is the docs
template (as used in this page) or the very similar blog
template. Both these templates include:
- a left nav
- GitHub links (populated from your site config) for readers to edit the page or create issues
- a page menu
as well as the common header and footer used by all your site’s pages. Which template is applied depends on whether you’ve added the content to the blog
or docs
content directory. You can find out more about how the nav and page menu are created in Navigation and Search.
Organizing your documentation
While Docsy’s top-level sections let you create site sections for different types of content, you may also want to organize your docs content within your docs
section. For example, this site’s docs
section directory has multiple subdirectories for Getting Started, Content and Customization, and so on. Each subdirectory has an _index.md
(it could also be an _index.html
), which acts as a section index page and tells Hugo that the relevant directory is a subsection of your docs.
Docsy’s docs
layout gives you a left nav pane with an autogenerated nested menu based on your docs
file structure. Each standalone page or subsection _index.md
or _index.html
page in the docs/
directory gets a top level menu item, using the link name and weight
metadata from the page or index.
To add docs to a subsection, just add your page files to the relevant subdirectory. Any pages that you add to a subsection in addition to the subsection index page will appear in a submenu (look to the left to see one in action!), again ordered by page weight
. Find out more about adding Docsy’s navigation metadata in Navigation and Search
If you’ve copied the example site, you’ll already have some suggested subdirectories in your docs
directory, with guidance for what types of content to put in them and some example Markdown pages. You can find out more about organizing your content with Docsy in Organizing Your Content.
Docs section landing pages
By default a docs section landing page (the _index.md
or _index.html
in the section directory) uses a layout that adds a formatted list of links to the pages in the section, with their frontmatter descriptions. The Content and Customization landing page in this site is a good example.
To display a simple bulleted list of links to the section’s pages instead, specify simple_list: true
in the landing page’s frontmatter:
+++
title = "Simple List Page"
simple_list = true
weight = 20
+++
---
title: "Simple List Page"
simple_list: true
weight: 20
---
{
"title": "Simple List Page",
"simple_list": true,
"weight": 20
}
To display no links at all, specify no_list: true
in the landing page’s frontmatter:
+++
title = "No List Page"
no_list = true
weight = 20
+++
---
title: "No List Page"
no_list: true
weight: 20
---
{
"title": "No List Page",
"no_list": true,
"weight": 20
}
Organizing your blog posts
Docsy’s blog
layout also gives you a left nav menu (like the docs
layout), and a list-type index page for your blog that’s applied to /blog/_index.md
and automatically displays snippets of all your recent posts in reverse chronological order.
To create different blog categories to organize your posts, create subfolders in blog/
. For instance, in our example site we have news
and releases
. Each category needs to have its own _index.md
or _index.html
landing page file specifying the category title for it to appear properly in the left nav and top-level blog landing page. Here’s the index page for releases
:
+++
title = "New Releases"
linkTitle = "Releases"
weight = 20
+++
---
title: "New Releases"
linkTitle: "Releases"
weight: 20
---
{
"title": "New Releases",
"linkTitle": "Releases",
"weight": 20
}
To add author and date information to blog posts, add them to the page frontmatter:
+++
date = 2018-10-06T00:00:00.000Z
title = "Easy documentation with Docsy"
linkTitle = "Announcing Docsy"
description = "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch"
author = "Riona MacNamara"
[[resources]]
src = "**.{png,jpg}"
title = "Image #:counter"
[resources.params]
byline = "Photo: Riona MacNamara / CC-BY-CA"
+++
---
date: 2018-10-06
title: "Easy documentation with Docsy"
linkTitle: "Announcing Docsy"
description: "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch"
author: Riona MacNamara
resources:
- src: "**.{png,jpg}"
title: "Image #:counter"
params:
byline: "Photo: Riona MacNamara / CC-BY-CA"
---
{
"date": "2018-10-06T00:00:00.000Z",
"title": "Easy documentation with Docsy",
"linkTitle": "Announcing Docsy",
"description": "The Docsy Hugo theme lets project maintainers and contributors focus on content, not on reinventing a website infrastructure from scratch",
"author": "Riona MacNamara",
"resources": [
{
"src": "**.{png,jpg}",
"title": "Image #:counter",
"params": {
"byline": "Photo: Riona MacNamara / CC-BY-CA"
}
}
]
}
If you’ve copied the example site and you don’t want a blog section, or want to link to an external blog instead, just delete the blog
subdirectory.
Working with top-level landing pages.
Docsy’s default page template has no left nav and is useful for creating a home page for your site or other “landing” type pages.
Customizing the example site pages
If you’ve copied the example site, you already have a simple site landing page in content/en/_index.html
. This is made up of Docsy’s provided Hugo shortcode page blocks.
To customize the large landing image, which is in a cover block, replace the content/en/featured-background.jpg
file in your project with your own image (it can be called whatever you like as long as it has background
in the file name). You can remove or add as many blocks as you like, as well as adding your own custom content.
The example site also has an About page in content/en/about/_index.html
using the same Docsy template. Again, this is made up of page blocks, including another background image in content/en/about/featured-background.jpg
. As with the site landing page, you can replace the image, remove or add blocks, or just add your own content.
Building your own landing pages
If you’ve just used the theme, you can still use all Docsy’s provided page blocks (or any other content you want) to build your own landing pages in the same file locations.
Adding a community page
The community
landing page template has boilerplate content that’s automatically filled in with the project name and community links specified in config.toml
/config.yaml
/config.json
, providing your users with quick links to resources that help them get involved in your project. The same links are also added by default to your site footer.
[params.links]
# End user relevant links. These will show up on left side of footer and in the community page if you have one.
[[params.links.user]]
name = "User mailing list"
url = "https://example.org/mail"
icon = "fa fa-envelope"
desc = "Discussion and help from your fellow users"
[[params.links.user]]
name ="Twitter"
url = "https://example.org/twitter"
icon = "fab fa-twitter"
desc = "Follow us on Twitter to get the latest news!"
[[params.links.user]]
name = "Stack Overflow"
url = "https://example.org/stack"
icon = "fab fa-stack-overflow"
desc = "Practical questions and curated answers"
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
[[params.links.developer]]
name = "GitHub"
url = "https://github.com/google/docsy"
icon = "fab fa-github"
desc = "Development takes place here!"
[[params.links.developer]]
name = "Slack"
url = "https://example.org/slack"
icon = "fab fa-slack"
desc = "Chat with other project developers"
[[params.links.developer]]
name = "Developer mailing list"
url = "https://example.org/mail"
icon = "fa fa-envelope"
desc = "Discuss development issues around the project"
params:
links:
user:
- name: User mailing list
url: 'https://example.org/mail'
icon: fa fa-envelope
desc: Discussion and help from your fellow users
- name: Twitter
url: 'https://example.org/twitter'
icon: fab fa-twitter
desc: Follow us on Twitter to get the latest news!
- name: Stack Overflow
url: 'https://example.org/stack'
icon: fab fa-stack-overflow
desc: Practical questions and curated answers
developer:
- name: GitHub
url: 'https://github.com/google/docsy'
icon: fab fa-github
desc: Development takes place here!
- name: Slack
url: 'https://example.org/slack'
icon: fab fa-slack
desc: Chat with other project developers
- name: Developer mailing list
url: 'https://example.org/mail'
icon: fa fa-envelope
desc: Discuss development issues around the project
{
"params": {
"links": {
"user": [
{
"name": "User mailing list",
"url": "https://example.org/mail",
"icon": "fa fa-envelope",
"desc": "Discussion and help from your fellow users"
},
{
"name": "Twitter",
"url": "https://example.org/twitter",
"icon": "fa-brands fa-twitter",
"desc": "Follow us on Twitter to get the latest news!"
},
{
"name": "Stack Overflow",
"url": "https://example.org/stack",
"icon": "fa-brands fa-stack-overflow",
"desc": "Practical questions and curated answers"
}
],
"developer": [
{
"name": "GitHub",
"url": "https://github.com/google/docsy",
"icon": "fa-brands fa-github",
"desc": "Development takes place here!"
},
{
"name": "Slack",
"url": "https://example.org/slack",
"icon": "fa-brands fa-slack",
"desc": "Chat with other project developers"
},
{
"name": "Developer mailing list",
"url": "https://example.org/mail",
"icon": "fa fa-envelope",
"desc": "Discuss development issues around the project"
}
]
}
}
}
If you’re creating your own site and want to add a page using this template, add a /community/_index.md
file in your content root directory. If you’ve copied the example site and don’t want a community page, just delete the /content/en/community/
directory in your project repo.
Adding static content
You may want to serve some non-Hugo-built content along with your site: for example, if you have generated reference docs using Doxygen, Javadoc, or other doc generation tools.
To add static content to be served “as-is”, just add the content as a folder and/or files in your site’s static
directory. When your site is deployed, content in this directory is served at the site root path. So, for example, if you have added content at /static/reference/cpp/
, users can access that content at http://{server-url}/reference/cpp/
and you can link to pages in this directory from other pages at /reference/cpp/{file name}
.
You can also use this directory for other files used by your project, including image files. You can find out more about serving static files, including configuring multiple directories for static content, in Static Files.
RSS feeds
Hugo will, by default, create an RSS feed for the home page and any section. For the main RSS feed you can control which sections to include by setting a site param in your config.toml
/config.yaml
/config.json
. This is the default configuration:
rss_sections = ["blog"]
rss_sections:
- blog
{
"rss_sections": [
"blog"
]
}
To disable all RSS feeds, add the following to your config.toml
/config.yaml
/config.json
:
disableKinds = ["RSS"]
disableKinds:
- RSS
{
"disableKinds": [
"RSS"
]
}
Note
If you have enabled our print feature or otherwise specified section-level output formats in config.toml
/config.yaml
/config.json
, make sure that "RSS"
is listed as an output format, otherwise you won’t get section-level RSS feeds (and your blog section won’t get a nice orange RSS button). Your config.toml
/config.yaml
/config.json
specification overrides the Hugo default output formats for sections, which are HTML and RSS.
[outputs]
section = [ "HTML", "RSS", "print" ]
outputs:
section:
- HTML
- RSS
- print
{
"outputs": {
"section": [
"HTML",
"RSS",
"print"
]
}
}
Sitemap
Hugo creates a sitemap.xml
file for your generated site by default: for example, here’s the sitemap for this site.
You can configure the frequency with which your sitemap is updated, your sitemap filename, and the default page priority in your config.toml
/config.yaml
/config.json
:
[sitemap]
changefreq = "monthly"
filename = "sitemap.xml"
priority = 0.5
sitemap:
changefreq: monthly
filename: sitemap.xml
priority: 0.5
{
"sitemap": {
"changefreq": "monthly",
"filename": "sitemap.xml",
"priority": 0.5
}
}
To override any of these values for a given page, specify it in page frontmatter:
+++
title = "Adding Content"
linkTitle = "Adding Content"
weight = 1
description = '''
Add different types of content to your Docsy site.
'''
[sitemap]
priority = 1
+++
---
title: "Adding Content"
linkTitle: "Adding Content"
weight: 1
description: >
Add different types of content to your Docsy site.
sitemap:
priority: 1.0
---
{
"title": "Adding Content",
"linkTitle": "Adding Content",
"weight": 1,
"description": "Add different types of content to your Docsy site.\n",
"sitemap": {
"priority": 1
}
}
To learn more about configuring sitemaps, see Sitemap Template.
2 - Look and Feel
By default, a site using Docsy has the theme’s default fonts, colors, and general look and feel. However, if you want your own color scheme (and you probably will!) you can very easily override the theme defaults with your own project-specific values - Hugo will look in your project files first when looking for information to build your site. And because Docsy uses Bootstrap 4 and SCSS for styling, you can override just single values (such as project colors and fonts) in its special SCSS project variables file, or do more serious customization by creating your own styles.
Docsy also provides options for styling your code blocks, using either Chroma or Prism for highlighting.
Project style files
To customize your project’s look and feel, create your own version of either or both of the following
Docsy placeholder files (note the _project.scss
suffixes):
assets/scss/
_variables_project.scss
is where you add project-specific definitions of theme variables such as site colors, as well as any additional Bootstrap variable values you want to set. You can find a list of Docsy’s theme variables and their default values inassets/scss/_variables.scss
. For information about other Bootstrap 4 variables, see Variable defaults and Bootstrap’s v4-dev/scss/_variables.scss file.assets/scss/
_styles_project.scss
is where you can add your own custom SCSS styles, including overriding any of the styles in Docsy’s theme SCSS files.
Tip
PostCSS (autoprefixing of CSS browser-prefixes) is not enabled when running in server mode (it is a little slow), so Chrome is the recommended choice for development.Site colors
To easily customize your site’s colors, add SCSS variable overrides to
assets/scss/_variables_project.scss
. A simple example changing the primary and
secondary color to two shades of purple:
$primary: #390040;
$secondary: #A23B72;
The theme has features such as rounded corners and gradient backgrounds enabled by default. These can also be toggled in your project variables file:
$enable-gradients: true;
$enable-rounded: true;
$enable-shadows: true;
Fonts
The theme uses Open Sans as its primary font. To disable Google Fonts and use a system font, set this SCSS variable in assets/scss/_variables_project.scss
:
$td-enable-google-fonts: false;
To configure another Google Font:
$google_font_name: "Open Sans";
$google_font_family: "Open+Sans:300,300i,400,400i,700,700i";
Note that if you decide to go with a font with different weights (in the built-in configuration this is 300
(light), 400
(medium) and 700
(bold)), you also need to adjust the weight related variables, i.e. variables starting with $font-weight-
.
CSS utilities
For documentation of available CSS utility classes, see the Bootstrap Documentation. This theme adds very little on its own in this area. However, we have added some color state CSS classes that can be useful in a dynamic context:
.-bg-<color>
.-text-<color>
You can use these classes, for example, to style your text in an appropriate color when you don’t know if the primary
color is dark or light, to ensure proper color contrast. They are also useful when you receive the color code as a shortcode parameter.
The value of <color>
can be any of the color names, primary
, white
, dark
, warning
, light
, success
, 300
, blue
, orange
etc.
When you use .-bg-<color>
, the text colors will be adjusted to get proper contrast:
<div class="-bg-primary p-3 display-4">Background: Primary</div>
<div class="-bg-200 p-3 display-4">Background: Gray 200</div>
.-text-<color>
sets the text color only:
<div class="-text-blue pt-3 display-4">Text: Blue</div>
Code highlighting with Chroma
With Hugo version 0.60 and higher, you can choose from a range of code block highlight and colour styles using Chroma that are applied to your fenced code blocks by default. If you copied a recent config.toml
your site uses Tango (like this site), otherwise the Hugo default is Monokai. You can switch to any of the available Chroma styles (including our Docsy default Tango) using your config.toml
/config.yaml
/config.json
:
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
[markup.highlight]
# See a complete list of available styles at https://xyproto.github.io/splash/docs/all.html
style = "tango"
markup:
goldmark:
renderer:
unsafe: true
highlight:
style: tango
{
"markup": {
"goldmark": {
"renderer": {
"unsafe": true
}
},
"highlight": {
"style": "tango"
}
}
}
By default code highlighting styles are not applied to code blocks without a specified language, instead you get Docsy’s default style of grey with black text. If you would like the code highlighting style to apply to all code blocks, even without a language, uncomment or add the following line under [markup.highlight]
in your config.toml
/config.yaml
/config.json
.
# Uncomment if you want your chosen highlight style used for code blocks without a specified language
guessSyntax = true
guessSyntax: true
"guessSyntax": true
You can find out more about code highlighting in Hugo with Chroma in Syntax Highlighting.
Code highlighting with Prism
Optionally, you can enable Prism syntax highlighting in your config.toml
/config.yaml
/config.json
:
# Enable syntax highlighting and copy buttons on code blocks with Prism
prism_syntax_highlighting = true
prism_syntax_highlighting: true
"prism_syntax_highlighting": true
When this option is enabled your site uses Prism instead of Chroma for code block highlighting.
Prism is a popular open source syntax highlighter which supports over 200 languages and various plugins.
Docsy includes JavaScript and CSS files for a basic Prism configuration, which supports:
- Code blocks styled with the Prism
Default
theme - Copy to clipboard buttons on code blocks
- Syntax highlighting for a number of common languages, as specified in the following Prism download link, Customize your download.
Code blocks with no language
By default, Prism code highlighting styles are not applied to code blocks without a specified language, instead you get Docsy’s default style of grey with black text. To apply Prism styling to code blocks with no language or a language not supported by Prism, specify none
as the language after your triple backticks.
Extending Prism for additional languages or plugins
If the included Prism configuration is not sufficient for your requirements, and you want to use additional languages or plugins you can replace the included files with your own.
- Download your own Prism JS and CSS files from https://prismjs.com/download.html
- Replace the included Prism JS and CSS with the files you downloaded:
- Copy the Javascript file to
static/js/prism.js
- Copy the CSS file to
static/css/prism.css
- Copy the Javascript file to
Navbar
For pages containing a blocks/cover shortcode, like most homepages, the navbar is translucent as long as the hero image hasn’t scrolled up past the navbar. For an example, see the About Docsy page. This initial translucent setting ensures that the hero image is maximally visible.
After the hero image has scrolled past the navbar, the navbar’s (opaque) background color is set – usually to the site’s primary color.
The text of navbar entries can be difficult to read with some hero images. In
these cases, you can disable navbar translucency by setting the
params.ui.navbar_translucent_over_cover_disable
option to true
in your
site’s configuration file.
Styling your project logo and name
The default Docsy navbar (.td-navbar
) displays your site identity, consisting
of the following:
Your logo, which is included in the navbar as an inline SVG, styled by
.td-navbar .navbar-brand svg
. For the style details, see _nav.scss.To ensure your logo displays correctly, you may want to resize it and ensure that it doesn’t have height and width attributes so that its size is fully responsive. Override the default styling of
.td-navbar .navbar-brand svg
or (equivalently).td-navbar .navbar-brand__logo
as needed.Your project name, which is the site
title
. If you don’t want your project name to appear (for example, because your logo is or contains a wordmark), then add the following custom styling to your project’s styles:.td-navbar .navbar-brand__name { display: none; }
Customizing templates
Add code to head or before body end
If you need to add some code (CSS import, cookie consent, or similar) to the head
section on every page, add the head-end.html
partial to your project:
layouts/partials/hooks/head-end.html
And add the code you need in that file. Your partial code is automatically included just before the end of the theme partial head.html
. The theme version of head-end.html
is empty.
Similarly, if you want to add some code right before the body
end, create your own version of the following file:
layouts/partials/hooks/body-end.html
Any code in this file is included automatically at the end of the theme partial scripts.html
.
Both head.html
and scripts.html
are then used to build Docsy’s base page layout, which is used by all the other page templates:
<!doctype html>
<html lang="{{ .Site.Language.Lang }}" class="no-js">
<head>
{{ partial "head.html" . }}
</head>
<body class="td-{{ .Kind }}">
<header>
{{ partial "navbar.html" . }}
</header>
<div class="container-fluid td-default td-outer">
<main role="main" class="td-main">
{{ block "main" . }}{{ end }}
</main>
{{ partial "footer.html" . }}
</div>
{{ partialCached "scripts.html" . }}
</body>
</html>
3 - Navigation and Search
Top-level menu
The top level menu (the one that appears in the top navigation bar for the entire site) uses your site’s main
menu. All Hugo sites have a main
menu array of menu entries, accessible via the .Site.Menus
site variable and populatable via page front matter or your site’s config.toml
/config.yaml
/config.json
.
To add a page or section to this menu, add it to the site’s main
menu in either config.toml
/config.yaml
/config.json
or in the destination page’s front matter (in _index.md
or _index.html
for a section, as that’s the section landing page). For example, here’s how we added the Documentation section landing page to the main menu in this site:
+++
title = "Welcome to Docsy"
linkTitle = "Documentation"
[menu.main]
weight = 20
pre = "<i class='fa-solid fa-book'></i>"
+++
---
title: "Welcome to Docsy"
linkTitle: "Documentation"
menu:
main:
weight: 20
pre: <i class='fa-solid fa-book'></i>
---
{
"title": "Welcome to Docsy",
"linkTitle": "Documentation",
"menu": {
"main": {
"weight": 20,
"pre": "<i class='fa-solid fa-book'></i>"
}
}
}
The menu is ordered from left to right by page weight
. So, for example, a section index or page with weight: 30
would appear after the Documentation section in the menu, while one with weight: 10
would appear before it.
If you want to add a link to an external site to this menu, add it in config.toml
/config.yaml
/config.json
, specifying the weight
.
[[menu.main]]
name = "GitHub"
weight = 50
url = "https://github.com/google/docsy/"
menu:
main:
- name: GitHub
weight: 50
url: 'https://github.com/google/docsy/'
{
"menu": {
"main": [
{
"name": "GitHub",
"weight": 50,
"url": "https://github.com/google/docsy/"
}
]
}
}
Adding icons to the top-level menu
As described in the Hugo docs, you can add icons to the top-level menu by using the pre and/or post parameter for main menu items defined in your site’s config.toml
/config.yaml
/config.json
or via page front matter. For example, the following configuration adds the GitHub icon to the GitHub menu item, and a New! alert to indicate that this is a new addition to the menu.
[[menu.main]]
name = "GitHub"
weight = 50
url = "https://github.com/google/docsy/"
pre = "<i class="fa-brands fa-github"></i>"
post = "<span class='alert'>New!</span>"
menu:
main:
- name: GitHub
weight: 50
url: 'https://github.com/google/docsy/'
pre: <i class="fa-brands fa-github"></i>
post: <span class='alert'>New!</span>
{
"menu": {
"main": [
{
"name": "GitHub",
"weight": 50,
"url": "https://github.com/google/docsy/",
"pre": "<i class="fa-brands fa-github"></i>",
"post": "<span class='alert'>New!</span>"
}
]
}
}
You can find a complete list of icons to use in the FontAwesome documentation. Docsy includes the free FontAwesome icons by default.
Adding a version drop-down
If you add some [params.versions]
in config.toml
, the Docsy theme adds a
version selector drop down to the top-level menu.
You can find out more in the guide to versioning your docs.
Adding a language drop-down
If you configure more than one language in config.toml
, the Docsy theme adds a language selector drop down to the top-level menu. Selecting a language takes the user to the translated version of the current page, or the home page for the given language.
You can find out more in Multi-language support.
Section menu
The section menu, as shown in the left side of the docs
section, is automatically built from the content
tree. Like the top-level menu, it is ordered by page or section index weight
(or by page creation date
if weight
is not set), with the page or index’s Title
, or linkTitle
if different, as its link title in the menu. If a section subfolder has pages other than _index.md
or _index.html
, those pages will appear as a submenu, again ordered by weight
. For example, here’s the metadata for this page showing its weight
and title
:
+++
title = "Navigation and Search"
linkTitle = "Navigation and Search"
date = 2017-01-05T00:00:00.000Z
weight = 3
description = '''
Customize site navigation and search for your Docsy site.
'''
+++
---
title: "Navigation and Search"
linkTitle: "Navigation and Search"
date: 2017-01-05
weight: 3
description: >
Customize site navigation and search for your Docsy site.
---
{
"title": "Navigation and Search",
"linkTitle": "Navigation and Search",
"date": "2017-01-05T00:00:00.000Z",
"weight": 3,
"description": "Customize site navigation and search for your Docsy site.\n"
}
To hide a page or section from the left navigation menu, set toc_hide: true
in the front matter.
To hide a page from the section summary on a docs section landing page, set hide_summary: true
in the front matter. If you want to hide a page from both the TOC menu and the section summary list, you need to set both toc_hide
and hide_summary
to true
in the front matter.
+++
title = "My Hidden Page"
weight = 99
toc_hide = true
hide_summary = true
description = '''
Page hidden from both the TOC menu and the section summary list.
'''
+++
---
title: "My Hidden Page"
weight: 99
toc_hide: true
hide_summary: true
description: >
Page hidden from both the TOC menu and the section summary list.
---
{
"title": "My Hidden Page",
"weight": 99,
"toc_hide": true,
"hide_summary": true,
"description": "Page hidden from both the TOC menu and the section summary list.\n"
}
Section menu options
By default, the section menu shows the current section fully expanded all the way down. This may make the left nav too long and difficult to scan for bigger sites. Try setting site parameter ui.sidebar_menu_compact = true
in config.toml
.
With the compact menu (.ui.sidebar_menu_compact = true
), only the current page’s ancestors, siblings and direct descendants are shown. You can use the optional parameter .ui.ul_show
to set a desired menu depth to always be visible. For example, with .ui.ul_show = 1
the first menu level is always displayed.
As well as the completely expanded and compact menu options, you can also create a foldable menu by setting the site parameter ui.sidebar_menu_foldable = true
in config.toml
. The foldable menu lets users expand and collapse menu sections by toggling arrow icons beside the section parents in the menu.
On large sites (default: > 2000 pages) the section menu is not generated for each page, but cached for the whole section. The HTML classes for marking the active menu item (and menu path) are then set using JS. You can adjust the limit for activating the cached section menu with the optional parameter .ui.sidebar_cache_limit
.
Add icons to the section menu
You can add icons to the section menu in the sidebar by setting the icon
parameter in the page front matter (e.g. icon: fa-solid fa-screwdriver-wrench
).
You can find a complete list of icons to use in the FontAwesome documentation. Docsy includes the free FontAwesome icons by default.
Out of the box, if you want to use icons, you should define icons for all items on the same menu level in order to ensure an appropriate look. If the icons are used in a different way, individual CSS adjustments are likely necessary.
Add manual links to the section menu
By default the section menu is entirely generated from your section’s pages. If you want to add a manual link to this menu, such as a link to an external site or a page in a different section of your site, you can do this by creating a placeholder page file in the doc hierarchy with the appropriate weight and some special parameters in its metadata (frontmatter) to specify the link details.
To create a placeholder page, create a page file as usual in the directory where you want the link to show up in the menu, and add a manualLink
parameter to its metadata. If a page has manualLink
in its metadata, Docsy generates a link for it in the section menu for this page and in the section index (the list of the child pages of a section on a landing page - see description in the Docsy docs), but the link destination is replaced by the value of manualLink
. The link text is the title
(or linkTitle
if set) of your placeholder page. You can optionally also set the title
attribute of the link with the parameter manualLinkTitle
and a link target with manualLinkTarget
- for example if you want an external link to open in a new tab you can set the link target to _blank
. Docsy automatically adds rel=noopener
to links that open new tabs as a security best practice.
You can also use manualLink
to add an additional cross reference to another existing page of your site. For internal links you can choose to use the parameter manualLinkRelref
instead of manualLink
to use the built-in Hugo function relref. If relref
can’t find a unique page in your site, Hugo throws a error message.
Note
Although all generated menu and landing page links based on your placeholder file are set according to the parametersmanualLink
or manualLinkRelref
, Hugo still generates a regular HTML site page for the file, albeit one with no generated links to it. To avoid confusion if users accidentally land on a generated placeholder page, we recommend specifying the URL for the external link in the normal content and / or page description of the page.Breadcrumb navigation
Breadcrumb navigation links appear at the top of each page by default. To disable breadcrumb navigation, set site param ui.breadcrumb_disable = true
in config.toml
.
Breadcrumb navigation links are also shown for each item on the taxonomy results page (i.e. when you click one of the taxonomy labels, e.g. Tags/Categories). These breadcrumbs can be disabled in config.toml
by setting site param taxonomy_breadcrumb_disable = true
.
Site search options
Docsy offers multiple options that let your readers search your site content, so you can pick one that suits your needs. You can choose from:
- Google Custom Search Engine (GCSE), the default option, which uses Google’s index of your public site to generate a search results page.
- Algolia DocSearch, which uses Algolia’s indexing and search mechanism, and provides an organized dropdown of search results when your readers use the search box. Algolia DocSearch is free for public documentation sites.
- Local search with Lunr, which uses Javascript to index and search your site without the need to connect to external services. This option doesn’t require your site to be public.
If you enable any of these search options in your config.toml
, a search box displays in the right of your top navigation bar. By default a search box also displays at the top of the section menu in the left navigation pane, which you can disable if you prefer, or if you’re using a search option that only works with the top search box.
Be aware that if you accidentally enable more than one search option in your config.toml
you may get unexpected results (for example, if you have added the .js
for Algolia DocSearch, you’ll get Algolia results if you enable GCSE search but forget to disable Algolia search).
Disabling the sidebar search box
By default, the search box appears in both the top navigation bar and at the top of the sidebar left navigation pane. If you don’t want the sidebar search box, set sidebar_search_disable
to true
in config.toml
/config.yaml
/config.json
:
sidebar_search_disable = true
sidebar_search_disable: true
"sidebar_search_disable": true
Configure search with a Google Custom Search Engine
By default Docsy uses a Google Custom Search Engine (GCSE) to search your site. To enable this feature, you’ll first need to make sure that you have built and deployed a production version of your site, as otherwise your site won’t be crawled and indexed.
Setting up site search
Create a Google Custom Search Engine for your deployed site by clicking New search engine on the Custom Search page and following the instructions. Make a note of the ID for your new search engine.
Add any further configuration you want to your search engine using the Edit search engine options. In particular you may want to do the following:
- Select Look and feel. Change from the default Overlay layout to Results only, as this option means your search results are embedded in your search page rather than appearing in a separate box. Click Save to save your changes.
- Edit the default result link behavior so that search results from your site don’t open in a new tab. To do this, select Search Features - Advanced - Websearch Settings. In the Link Target field, type “_parent”. Click Save to save your changes.
Tip
Your site search results should show up within a couple of days. If it takes longer than that, you can manually request that your site is indexed by submitting a sitemap through the Google Search Console.Adding the search page
Once you have your search engine set up, you can add the feature to your site:
Ensure you have a Markdown file in
content/en/search.md
(and one per other languages if needed) to display your search results. It only needs a title andlayout: search
, as in the following example:+++ title = "Search Results" layout = "search" +++
--- title: Search Results layout: search ---
{ "title": "Search Results", "layout": "search" }
Add your Google Custom Search Engine ID to the site params in
config.toml
/config.yaml
/config.json
. You can add different values per language if needed.gcs_engine_id = "011737558837375720776:fsdu1nryfng"
gcs_engine_id: '011737558837375720776:fsdu1nryfng'
{ "gcs_engine_id": "011737558837375720776:fsdu1nryfng" }
Disabling GCSE search
If you don’t specify a Google Custom Search Engine ID for your project and haven’t enabled any other search options, the search box won’t appear in your site. If you’re using the default config.toml
from the example site and want to disable search, just comment out or remove the relevant line.
Configure Algolia DocSearch
As an alternative to GCSE, you can use Algolia DocSearch with this theme. Algolia DocSearch is free for public documentation sites. Docsy supports Algolia DocSearch v3.
Note
Docsy previously supported Algolia DocSearch v2, which is now deprecated. If you are an existing Algolia DocSearch v2 user and want to use the latest Docsy version, follow the migration instructions in the DocSearch documentation to update your DocSearch code snippet.Sign up for Algolia DocSearch
Complete the form at https://docsearch.algolia.com/apply/.
If you are accepted to the program, you will receive the code to add to your documentation site from Algolia by email.
Adding Algolia DocSearch
Enable Algolia DocSearch in
config.toml
/config.yaml
/config.json
.algolia_docsearch = true
algolia_docsearch: true
{ "algolia_docsearch": true }
Remove or comment out any GCSE ID in
config.toml
/config.yaml
/config.json
and ensure local search is set tofalse
as you can only have one type of search enabled. See Disabling GCSE search.Disable the sidebar search in
config.toml
/config.yaml
/config.json
as this is not currently supported for Algolia DocSearch. See Disabling the sidebar search box.Add the CSS and JS to use Algolia to the head and body of every page in your site, following the instructions in Add code to head or before body end.
In
head-end.html
add the DocSearch CSS:<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" />
In
body-end.html
add the DocSearch script, replacing thedocsearch
details with the snippet you get from Algolia (the example below is Algolia’s own site index!). You must provide#docsearch
as yourcontainer
value as that’s the ID of thediv
we provide in Docsy’s layout:<script src="https://cdn.jsdelivr.net/npm/@docsearch/js@3"></script> <script type="text/javascript">docsearch({ container: '#docsearch', appId: 'R2IYF7ETH7', apiKey: '599cec31baffa4868cae4e79f180729b', indexName: 'docsearch', });</script>
You can find out more about how to configure DocSearch in the Algolia DocSearch V3 Getting started guide.
When you’ve completed these steps, Algolia search should be enabled on your site. Search results are displayed as a pop-up, so you don’t need to add any search results page.
Configure local search with Lunr
Lunr is a Javascript-based search option that lets you index your site and make it searchable without the need for external, server-side search services. This is a good option particularly for smaller or non-public sites.
To add Lunr search to your Docsy site:
Enable local search in
config.toml
/config.yaml
/config.json
.offlineSearch = true
offlineSearch: true
{ "offlineSearch": true }
Remove or comment out any GCSE ID in
config.toml
/config.yaml
/config.json
and ensure Algolia DocSearch is set tofalse
, as you can only have one type of search enabled. See Disabling GCSE search.
Once you’ve completed these steps, local search is enabled for your site and results appear in a drop down when you use the search box.
Tip
If you’re testing this locally using Hugo’s local server functionality, you need to build youroffline-search-index.xxx.json
file first by running hugo
. If you have the Hugo server running while you build offline-search-index.xxx.json
, you may need to stop the server and restart it in order to see your search results.Changing the summary length of the local search results
You can customize the summary length by setting offlineSearchSummaryLength
in config.toml
/config.yaml
/config.json
.
#Enable offline search with Lunr.js
offlineSearch = true
offlineSearchSummaryLength = 200
offlineSearch: true
offlineSearchSummaryLength: 200
{
"offlineSearch": true,
"offlineSearchSummaryLength": 200
}
Changing the maximum result count of the local search
You can customize the maximum result count by setting offlineSearchMaxResults
in config.toml
/config.yaml
/config.json
.
offlineSearch = true
offlineSearchMaxResults = 25
offlineSearch: true
offlineSearchMaxResults: 25
{
"offlineSearch": true,
"offlineSearchMaxResults": 25
}
Changing the width of the local search results popover
The width of the search results popover will automatically widen according to the content.
If you want to limit the width, add the following scss into assets/scss/_variables_project.scss
.
.td-offline-search-results {
max-width: 460px;
}
Excluding pages from local search results
To exclude pages from local search results, add exclude_search: true
to the the frontmatter of each page:
+++
title = "Index"
weight = 10
exclude_search = true
+++
---
title: "Index"
weight: 10
exclude_search: true
---
{
"title": "Index",
"weight": 10,
"exclude_search": true
}
4 - Doc Versioning
Depending on your project’s releases and versioning, you may want to let your users access previous versions of your documentation. How you deploy the previous versions is up to you. This page describes the Docsy features that you can use to provide navigation between the various versions of your docs and to display an information banner on the archived sites.
Adding a version drop-down menu
If you add some [params.versions]
in config.toml
/config.yaml
/config.json
, the Docsy theme adds a
version selector drop down to the top-level menu. You specify a URL and a name
for each version you would like to add to the menu, as in the following example:
# Add your release versions here
[[params.versions]]
version = "master"
url = "https://master.kubeflow.org"
[[params.versions]]
version = "v0.2"
url = "https://v0-2.kubeflow.org"
[[params.versions]]
version = "v0.3"
url = "https://v0-3.kubeflow.org"
params:
versions:
- version: master
url: 'https://master.kubeflow.org'
- version: v0.2
url: 'https://v0-2.kubeflow.org'
- version: v0.3
url: 'https://v0-3.kubeflow.org'
{
"params": {
"versions": [
{
"version": "master",
"url": "https://master.kubeflow.org"
},
{
"version": "v0.2",
"url": "https://v0-2.kubeflow.org"
},
{
"version": "v0.3",
"url": "https://v0-3.kubeflow.org"
}
]
}
}
Remember to add your current version so that users can navigate back!
The default title for the version drop-down menu is Releases. To change the
title, change the version_menu
parameter in config.toml
/config.yaml
/config.json
:
version_menu = "Releases"
version_menu: 'Releases'
"version_menu": "Releases"
If you set the version_menu_pagelinks
parameter to true
, then links in the version drop-down menu
point to the current page in the other version, instead of the main page.
This can be useful if the document doesn’t change much between the different versions.
Note that if the current page doesn’t exist in the other version, the link will be broken.
You can read more about Docsy menus in the guide to navigation and search.
Displaying a banner on archived doc sites
If you create archived snapshots for older versions of your docs, you can add a note at the top of every page in the archived docs to let readers know that they’re seeing an unmaintained snapshot and give them a link to the latest version.
For example, see the archived docs for Kubeflow v0.6:
To add the banner to your doc site, make the following changes in your
config.toml
/config.yaml
/config.json
file:
Set the
archived_version
parameter totrue
:archived_version = true
archived_version: true
"archived_version": true
Set the
version
parameter to the version of the archived doc set. For example, if the archived docs are for version 0.1:version = "0.1"
version: '0.1'
"version": "0.1"
Make sure that
url_latest_version
contains the URL of the website that you want to point readers to. In most cases, this should be the URL of the latest version of your docs:url_latest_version = "https://your-latest-doc-site.com"
url_latest_version: 'https://your-latest-doc-site.com'
"url_latest_version": "https://your-latest-doc-site.com"
5 - Docsy Shortcodes
Rather than writing all your site pages from scratch, Hugo lets you define and use shortcodes. These are reusable snippets of content that you can include in your pages, often using HTML to create effects that are difficult or impossible to do in simple Markdown. Shortcodes can also have parameters that let you, for example, add your own text to a fancy shortcode text box. As well as Hugo’s built-in shortcodes, Docsy provides some shortcodes of its own to help you build your pages.
Shortcode blocks
The theme comes with a set of custom Page Block shortcodes that can be used to compose landing pages, about pages, and similar.
These blocks share some common parameters:
- height
- A pre-defined height of the block container. One of
min
,med
,max
,full
, orauto
. Setting it tofull
will fill the Viewport Height, which can be useful for landing pages. - color
- The block will be assigned a color from the theme palette if not provided, but you can set your own if needed. You can use all of Bootstrap’s color names, theme color names or a grayscale shade. Some examples would be
primary
,white
,dark
,warning
,light
,success
,300
,blue
,orange
. This will become the background color of the block, but text colors will adapt to get proper contrast.
blocks/cover
The blocks/cover shortcode creates a landing page type of block that fills the top of the page.
{{< blocks/cover title="Welcome!" image_anchor="center" height="full" color="primary" >}}
<div class="mx-auto">
<a class="btn btn-lg btn-primary mr-3 mb-4" href="{{< relref "/docs" >}}">
Learn More <i class="fa-solid fa-circle-right ml-2"></i>
</a>
<a class="btn btn-lg btn-secondary mr-3 mb-4" href="https://example.org">
Download <i class="fa-brands fa-github ml-2 "></i>
</a>
<p class="lead mt-5">This program is now available in <a href="#">AppStore!</a></p>
<div class="mx-auto mt-5">
{{< blocks/link-down color="info" >}}
</div>
</div>
{{< /blocks/cover >}}
Note that the relevant shortcode parameters above will have sensible defaults, but is included here for completeness.
Hugo Tip
Using the bracket styled shortcode delimiter,
>}}
, tells Hugo that the inner content is HTML/plain text and needs no further processing. Changing the delimiter to%}}
means Hugo will treat the content as Markdown. You can use both styles in your pages.
Parameter | Default | Description |
---|---|---|
title | The main display title for the block. | |
image_anchor | ||
height | See above. | |
color | See above. | |
byline | Byline text on featured image. |
To set the background image, place an image with the word “background” in the name in the page’s Page Bundle. For example, in our the example site the background image in the home page’s cover block is featured-background.jpg
, in the same directory.
Tip
If you also include the word featured in the image name, e.g.my-featured-background.jpg
, it will also be used as the Twitter Card image when shared.For available icons, see Font Awesome.
blocks/lead
The blocks/lead block shortcode is a simple lead/title block with centred text and an arrow down pointing to the next section.
{{% blocks/lead color="dark" %}}
TechOS is the OS of the future.
Runs on **bare metal** in the **cloud**!
{{% /blocks/lead %}}
Parameter | Default | Description |
---|---|---|
height | See above. | |
color | See above. |
blocks/section
The blocks/section shortcode is meant as a general-purpose content container. It comes in two “flavors”, one for general content and one with styling more suitable for wrapping a horizontal row of feature sections.
The example below shows a section wrapping 3 feature sections.
{{< blocks/section color="dark" >}}
{{% blocks/feature icon="fa-lightbulb" title="Fastest OS **on the planet**!" %}}
The new **TechOS** operating system is an open source project. It is a new project, but with grand ambitions.
Please follow this space for updates!
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-brands fa-github" title="Contributions welcome!" url="https://github.com/gohugoio/hugo" %}}
We do a [Pull Request](https://github.com/gohugoio/hugo/pulls) contributions workflow on **GitHub**. New users are always welcome!
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-brands fa-twitter" title="Follow us on Twitter!" url="https://twitter.com/GoHugoIO" %}}
For announcement of latest features etc.
{{% /blocks/feature %}}
{{< /blocks/section >}}
Parameter | Default | Description |
---|---|---|
height | See above. | |
color | See above. | |
type | Specify “section” if you want a general container, omit this parameter if you want this section to contain a horizontal row of features. |
blocks/feature
{{% blocks/feature icon="fa-brands fa-github" title="Contributions welcome!" url="https://github.com/gohugoio/hugo" %}}
We do a [Pull Request](https://github.com/gohugoio/hugo/pulls) contributions workflow on **GitHub**. New users are always welcome!
{{% /blocks/feature %}}
Parameter | Default | Description |
---|---|---|
title | The title to use. | |
url | The URL to link to. | |
icon | The icon class to use. |
blocks/link-down
The blocks/link-down shortcode creates a navigation link down to the next section. It’s meant to be used in combination with the other blocks shortcodes.
<div class="mx-auto mt-5">
{{< blocks/link-down color="info" >}}
</div>
Parameter | Default | Description |
---|---|---|
color | info | See above. |
Shortcode helpers
alert
The alert shortcode creates an alert block that can be used to display notices or warnings.
{{% alert title="Warning" color="warning" %}}
This is a warning.
{{% /alert %}}
Renders to:
Warning
This is a warning.Parameter | Default | Description |
---|---|---|
color | primary | One of the theme colors, eg primary , info , warning etc. |
pageinfo
The pageinfo shortcode creates a text box that you can use to add banner information for a page: for example, letting users know that the page contains placeholder content, that the content is deprecated, or that it documents a beta feature.
{{% pageinfo color="primary" %}}
This is placeholder content.
{{% /pageinfo %}}
Renders to:
This is placeholder content
Parameter | Default | Description |
---|---|---|
color | primary | One of the theme colors, eg primary , info , warning etc. |
imgproc
The imgproc shortcode finds an image in the current Page Bundle and scales it given a set of processing instructions.
{{< imgproc spruce Fill "400x450" >}}
Norway Spruce Picea abies shoot with foliage buds.
{{< /imgproc >}}
The example above has also a byline with photo attribution added. When using illustrations with a free license from WikiMedia and similar, you will in most situations need a way to attribute the author or licensor. You can add metadata to your page resources in the page front matter. The byline
param is used by convention in this theme:
+++
[[resources]]
src = "**spruce*.jpg"
[resources.params]
byline = "Photo: Bjørn Erik Pedersen / CC-BY-SA"
+++
---
resources:
- src: "**spruce*.jpg"
params:
byline: "Photo: Bjørn Erik Pedersen / CC-BY-SA"
---
{
"resources": [
{
"src": "**spruce*.jpg",
"params": {
"byline": "Photo: Bjørn Erik Pedersen / CC-BY-SA"
}
}
]
}
Parameter | Description |
---|---|
1 | The image filename or enough of it to identify it (we do Glob matching) |
2 | Command. One of Fit , Resize or Fill . See Image Processing Methods. |
3 | Processing options, e.g. 400x450 . See Image Processing Options. |
swaggerui
The swaggerui
shortcode can be placed anywhere inside a page with the swagger
layout; it renders Swagger UI using any OpenAPI YAML or JSON file as source. This file can be hosted anywhere you like, for example in your site’s root /static
folder.
+++
title = "Pet Store API"
type = "swagger"
weight = 1
description = "Reference for the Pet Store API"
+++
{{< swaggerui src="/openapi/petstore.yaml" >}}
---
title: "Pet Store API"
type: swagger
weight: 1
description: Reference for the Pet Store API
---
{{< swaggerui src="/openapi/petstore.yaml" >}}
{
"title": "Pet Store API",
"type": "swagger",
"weight": 1,
"description": "Reference for the Pet Store API"
}
{{< swaggerui src="/openapi/petstore.yaml" >}}
You can customize Swagger UI’s look and feel by overriding Swagger’s CSS or by editing and compiling a Swagger UI dist yourself and replace themes/docsy/static/css/swagger-ui.css
.
redoc
The redoc
shortcode uses the open-source Redoc tool to render reference API documentation from an OpenAPI YAML or JSON file. This can be hosted anywhere you like, for example in your site’s root /static
folder, but you can use a URL as well, for example:
---
title: "Pet Store API"
type: docs
weight: 1
description: Reference for the Pet Store API
---
{{< redoc "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v2.0/yaml/petstore.yaml" >}}
iframe
With this shortcode you can embed external content into a Docsy page as an inline frame (iframe
) - see: https://www.w3schools.com/tags/tag_iframe.asp
Parameter | Default | Description |
---|---|---|
src | URL of external content | |
width | 100% | Width of iframe |
tryautoheight | true | If true the shortcode tries to calculate the needed height for the embedded content using JavaScript, as described here: https://stackoverflow.com/a/14618068. This is only possible if the embedded content is on the same domain. Note that even if the embedded content is on the same domain, it depends on the structure of the content if the height can be calculated correctly. |
style | min-height:98vh; border:none; | CSS styles for the iframe. min-height:98vh; is a backup if tryautoheight doesn’t work. border:none; removes the border from the iframe - this is useful if you want the embedded content to look more like internal content from your page. |
sandbox | false | You can switch the sandbox completely on by setting sandbox = true or allow specific functionality with the common values for the iframe parameter sandbox defined in the HTML standard. |
name | iframe-name | Specify the name of the iframe. |
id | iframe-id | Sets the ID of the iframe. |
class | Optional parameter to set the classes of the iframe. | |
sub | Your browser cannot display embedded frames. You can access the embedded page via the following link: | The text displayed (in addition to the embedded URL) if the user’s browser can’t display embedded frames. |
Warning
You can only embed external content from a server when its X-Frame-Options
is not set or if it specifically allows embedding for your site. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options for details.
There are several tools you can use to check if a website can be embedded via iframe - e.g.: https://gf.dev/x-frame-options-test. Be aware that when this test says “Couldn’t find the X-Frame-Options header in the response headers.” you CAN embed it, but when the test says “Great! X-Frame-Options header was found in the HTTP response headers as highlighted below.”, you CANNOT - unless it has been explicitly enabled for your site.
Tabbed panes
Sometimes it’s very useful to have tabbed panes when authoring content. One common use-case is to show multiple syntax highlighted code blocks that showcase the same problem, and how to solve it in different programming languages. As an example, the tabbed pane below shows the language-specific variants of the famous Hello world!
program one usually writes first when learning a new programming language:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Hello World!");
return EXIT_SUCCESS;
}
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
package main
import "fmt"
func main() {
fmt.Printf("Hello World!\n")
}
class HelloWorld {
static public void main( String args[] ) {
System.out.println( "Hello World!" );
}
}
fun main(args : Array<String>) {
println("Hello, world!")
}
print "Hello world"
<?php
echo 'Hello World!';
?>
print("Hello World!")
puts "Hello World!"
object HelloWorld extends App {
println("Hello world!")
}
The Docsy template provides two shortcodes tabpane
and tab
that let you easily create tabbed panes. To see how to use them, have a look at the following code block, which renders to a right aligned pane with one disabled and three active tabs:
{{< tabpane text=true right=true >}}
{{% tab header="**Languages**:" disabled=true /%}}
{{% tab header="English" lang="en" %}}
![Flag United Kingdom](flags/uk.png)
Welcome!
{{% /tab %}}
{{< tab header="German" lang="de" >}}
<b>Herzlich willkommen!</b>
<img src="flags/de.png" alt="Flag Germany" style="float: right; padding: 0 0 0 0px">
{{< /tab >}}
{{% tab header="Swahili" lang="sw" %}}
![Flag Tanzania](flags/tz.png)
**Karibu sana!**
{{% /tab %}}
{{< /tabpane >}}
This code translates to the right aligned tabbed pane below, showing a Welcome!
greeting in English, German or Swahili:
Welcome!
Karibu sana!
Shortcode details
Tabbed panes are implemented using two shortcodes:
- The
tabpane
shortcode, which is the container element for the tabs. This shortcode can hold the optional named parameterslang
,highlight
andright
. The value of the optional parameterslang
andhighlight
are passed on as secondLANG
and thirdOPTIONS
arguments to Hugo’s built-inhighlight
function which is used to render the code blocks of the individual tabs. Specifyright=true
if you want to right align your tabs. In case the header text of the tab equals the language used in the tab’s code block (as in the first tabbed pane example above), you may specifylangEqualsHeader=true
in the surroundingtabpane
shortcode. Then, the header text of the individual tab is automatically set aslang
parameter of the respective tab. - The various
tab
shortcodes represent the tabs you would like to show. Specify the named parameterheader
for each tab in order to set the header text of the tab. If theheader
parameter is the only parameter inside your tab shortcode, you can specify the header as unnamed parameter, something like{ tab "My header" }} … {{ /tab }}
. If yourtab
shortcode does not have any parameters, the header of the tab will default toTab n
. To split the panes into a left aligned and a right aligned tab group, specifyright=true
in the dividing tab. By givingright=true
several times, you can even render multiple tab groups. You can disable a tab by specifying the parameterdisabled=true
. For enabled tabs, there are two modes for content display,code
representation and textual representation:- By default, the tab’s content is rendered as
code block
. In order to get proper syntax highlighting, specify the named parameterlang
–and optionally the parameterhighlight
– for each tab. Parameters set in the parenttabpane
shortcode will be overwritten. - If the contents of your tabs should be rendered as text with different styles and with optional images, specify
text=true
as parameter of yourtabpane
(or yourtab
). If your content is markdown, use the percent sign%
as outermost delimiter of yourtab
shortcode, your markup should look like{{% tab %}}
Your **markdown** content{{% /tab %}}
. In case of HTML content, use square brackets<>
as outermost delimiters:{{< tab >}}
Your <b>HTML</b> content{{< /tab >}}
.
- By default, the tab’s content is rendered as
Info
By default, the language of the selected tab is stored and preserved between different browser sessions. If the content length within your tabs differs greatly, this may lead to unwanted scrolling when switching between tabs. To disable this unwanted behaviour, specifypersistLang=false
within your tabpane
shortcode.Card panes
When authoring content, it’s sometimes very useful to put similar text blocks or code fragments on card like elements, which can be optionally presented side by side. Let’s showcase this feature with the following sample card group which shows the first four Presidents of the United States:
*1732 †1799
President: 1789 – 1797
* 1735 † 1826
President: 1797 – 1801
* 1743 † 1826
President: 1801 – 1809
* 1751 † 1836
President: 1809 – 1817
Docsy supports creating such card panes via different shortcodes:
- The
cardpane
shortcode which is the container element for the various cards to be presented. - The
card
shortcodes, with each shortcode representing an individual card. While cards are often presented inside a card group, a single card may stand on its own, too. Acard
shortcode can hold text, images or any other arbitrary kind of markdown or HTML markup as content. If your content is programming code, you are advised to make use of thecard-code
shortcode, a special kind of card with code-highlighting and other optional features like line numbers, highlighting of certain lines, ….
Shortcode card
(for text, images, …)
As stated above, a card is coded using one of the shortcode card
or card-code
.
If your content is any kind of text other than programming code, use the universal card
shortcode. The following code sample demonstrates how to code a card element:
{{< card header="**Imagine**" title="Artist and songwriter: John Lennon" subtitle="Co-writer: Yoko Ono"
footer="![SignatureJohnLennon](https://server.tld/…/signature.png 'Signature John Lennon')">}}
Imagine there's no heaven, It's easy if you try<br/>
No hell below us, above us only sky<br/>
Imagine all the people living for today…
…
{{< /card >}}
This code translates to the left card shown below, showing the lyrics of John Lennon’s famous song Imagine
. A second explanatory card element to the right indicates and explains the individual components of a card:
Artist and songwriter: John Lennon
Co-writer: Yoko Ono
Imagine there’s no heaven, It’s easy if you try
No hell below us, above us only sky
Imagine all the people living for today…
Imagine there’s no countries, it isn’t hard to do
Nothing to kill or die for, and no religion too
Imagine all the people living life in peace…
Imagine no possessions, I wonder if you can
No need for greed or hunger - a brotherhood of man
Imagine all the people sharing all the world…
You may say I’m a dreamer, but I’m not the only one
I hope someday you’ll join us and the world will live as one
Header
Card title: specified via named parameter title
Card subtitle: specified via named parameter subtitle
Content: inner content of the shortcode, this may be formatted text, images, videos, … . If the extension of your page file equals .md
, markdown format is expected, otherwise, your content will be treated as plain HTML.
While the main content of the card is taken from the inner markup of the card
shortcode, the optional elements footer
, header
, title
, and subtitle
are all specified as named parameters of the shortcode.
Shortcode card-code
(for programming code)
In case you want to display programming code on your card, a special shortcode card-code
is provided for this purpose. The following sample demonstrates how to code a card element with the famous Hello world!
application coded in C:
{{< card-code header="**C**" lang="C" >}}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Hello World!");
return EXIT_SUCCESS;
}
{{< /card-code >}}
This code translates to the card shown below:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
puts("Hello World!");
return EXIT_SUCCESS;
}
The card-code
shortcode can optionally hold the named parameters lang
and/or highlight
. The values of these optional parameters are passed on as second LANG
and third OPTIONS
arguments to Hugo’s built-in highlight
function which is used to render the code block presented on the card.
Card groups
Displaying two ore more cards side by side can be easily achieved by putting them between the opening and closing elements of a cardpane
shortcode.
The general markup of a card group resembles closely the markup of a tabbed pane:
{{< cardpane >}}
{{< card header="Header card 1" >}}
Content card 1
{{< /card >}}
{{< card header="Header card 2" >}}
Content card 2
{{< /card >}}
{{< card header="Header card 3" >}}
Content card 3
{{< /card >}}
{{< /cardpane >}}
Contrary to tabs, cards are presented side by side, however. This is especially useful it you want to compare different programming techniques (traditional vs. modern) on two cards, like demonstrated in the example above:
File[] hiddenFiles = new File("directory_name")
.listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isHidden();
}
});
File[] hiddenFiles = new File("directory_name")
.listFiles(File::isHidden);
Include external files
Sometimes there’s content that is relevant for several documents, or that is
maintained in a file that is not necessarily a document. For situations like
these, the readfile
shortcode allows you to import the contents of an external
file into a document.
Reuse documentation
In case you want to reuse some content in several documents, you can write said content in a separate file and include it wherever you need it.
For example, suppose you have a file called installation.md
with the following
contents:
## Installation
{{% alert title="Note" color="primary" %}}
Check system compatibility before proceeding.
{{% /alert %}}
1. Download the installation files.
1. Run the installation script
`sudo sh install.sh`
1. Test that your installation was successfully completed.
You can import this section into another document:
The following section explains how to install the database:
{{% readfile "installation.md" %}}
This is rendered as if the instructions were in the parent document. Hugo v0.101.0+ is required for imported files containing shortcodes to be rendered correctly.
The following section explains how to install the database:
Installation
Note
Check system compatibility before proceeding.
Download the installation files.
Run the installation script
sudo sh install.sh
Test that your installation was successfully completed.
The parameter is the relative path to the file. Only relative paths under the parent file’s working directory are supported.
For files outside the current working directory you can use an absolute path
starting with /
. The root directory is the /content
folder.
Include code files
Suppose you have an includes
folder containing several code samples you want
to use as part of your documentation. You can use readfile
with some
additional parameters:
To create a new pipeline, follow the next steps:
1. Create a configuration file `config.yaml`:
{{< readfile file="includes/config.yaml" code="true" lang="yaml" >}}
1. Apply the file to your cluster `kubectl apply config.yaml`
This code automatically reads the content of import/config.yaml
and inserts it
into the document. The rendered text looks like this:
To create a new pipeline, follow the next steps:
Create a configuration file
config.yaml
:apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: hello spec: steps: - name: echo image: alpine script: | #!/bin/sh echo "Hello World"
Apply the file to your cluster
kubectl apply config.yaml
Warning
You must use{{< >}}
delimiters for the code highlighting to work
correctly.The “file” parameter is the relative path to the file. Only relative paths under the parent file’s working directory are supported.
For files outside the current working directory you can use an absolute path
starting with /
. The root directory is the /content
folder.
Parameter | Default | Description |
---|---|---|
file | Path of external file | |
code | false | Boolean value. If true the contents is treated as code |
lang | plain text | Programming language |
Conditional text
The conditional-text
shortcode allows you to show or hide parts of your content depending on the value of the buildCondition
parameter set in your configuration file. This can be useful if you are generating different builds from the same source, for example, using a different product name. This shortcode helps you handle the minor differences between these builds.
{{% conditional-text include-if="foo" %}}
This text appears in the output only if `buildCondition = "foo" is set in your config file`.
{{% /conditional-text %}}
{{% conditional-text exclude-if="bar" %}}
This text does not appear in the output if `buildCondition = "bar" is set in your config file`.
{{% /conditional-text %}}
If you are using this shortcode, note that when evaluating the conditions, substring matches are matches as well. That means, if you set include-if="foobar"
, and buildcondition = "foo"
, you have a match!
6 - Logos and Images
Add your logo
By default, Docsy shows a site logo at the start of the navbar, that is, at the
extreme left. Place your project’s SVG logo in assets/icons/logo.svg
. This
overrides the default Docsy logo in the theme.
If you don’t want a logo to appear in the navbar, then set navbar_logo
to
false
in your project’s config:
navbar_logo = false
navbar_logo: false
{
"navbar_logo": false
}
For information about styling your logo, see Styling your project logo and name.
Use icons
Docsy includes the free FontAwesome icons by default, including logos for sites like GitHub and Stack Overflow. You can view all available icons in the FontAwesome documentation, including the FontAwesome version when the icon was added and whether it is available for free tier users. Check Docsy’s package.json
and release notes for Docsy’s currently included version of FontAwesome.
You can add FontAwesome icons to your top-level menu, section menu, or anywhere in your text.
Add your favicons
The easiest way to do this is to create a set of favicons via http://cthedot.de/icongen (which lets you create a huge range of icon sizes and options from a single image) and/or https://favicon.io, and put them in your site project’s static/favicons
directory. This will override the default favicons from the theme.
Note that https://favicon.io doesn’t create as wide a range of sizes as Icongen but does let you quickly create favicons from text: if you want to create text favicons you can use this site to generate them, then use Icongen to create more sizes (if necessary) from your generated .png
file.
If you have special favicon requirements, you can create your own layouts/partials/favicons.html
with your links.
Add images
Landing pages
Docsy’s blocks/cover
shortcode make it easy to add large cover images to your landing pages. The shortcode looks for an image with the word “background” in the name inside the landing page’s Page Bundle - so, for example, if you’ve copied the example site, the landing page image in content/en/_index.html
is content/en/featured-background.jpg
.
You specify the preferred display height of a cover block container (and hence its image) using the block’s height
parameter. For a full viewport height, use full
:
{{< blocks/cover title="Welcome to the Docsy Example Project!" image_anchor="top" height="full" color="orange" >}}
...
{{< /blocks/cover >}}
For a shorter image, as in the example site’s About page, use one of min
, med
, max
or auto
(the actual height of the image):
{{< blocks/cover title="About the Docsy Example" image_anchor="bottom" height="min" >}}
...
{{< /blocks/cover >}}
Other pages
To add inline images to other pages, use the imgproc
shortcode. Alternatively, if you prefer, just use regular Markdown or HTML images and add your image files to your project’s static
directory. You can find out more about using this directory in Adding static content.
Images used on this site
Images used as background images in this site are in the public domain and can be used freely. The porridge image in the example site is by iha31 from Pixabay.
7 - Print Support
Individual documentation pages print well from most browsers as the layouts have been styled to omit navigational chrome from the printed output.
On some sites, it can be useful to enable a “print entire section” feature (as seen in this user guide). Selecting this option renders the entire current top-level section (such as Content and Customization for this page) with all of its child pages and sections in a format suited to printing, complete with a table of contents for the section.
To enable this feature, add the “print” output format in your site’s config.toml
/config.yaml
/config.json
file for the “section” type:
[outputs]
section = [ "HTML", "RSS", "print" ]
outputs:
section:
- HTML
- RSS
- print
{
"outputs": {
"section": [
"HTML",
"RSS",
"print"
]
}
}
The site should then show a “Print entire section” link in the right hand navigation.
Further Customization
Disabling the ToC
To disable showing the the table of contents in the printable view, set the disable_toc
param to true
, either in the page front matter, or in config.toml
/config.yaml
/config.json
:
+++
…
disable_toc = true
…
+++
---
…
disable_toc: true
…
---
{
…,
"disable_toc": true,
…
}
[params.print]
disable_toc = true
params:
print:
disable_toc: true
{
"params": {
"print": {
"disable_toc": true
}
}
}
Layout hooks
A number of layout partials and hooks are defined that can be used to customize the printed format. These can be found in layouts/partials/print
.
Hooks can be defined on a per-type basis. For example, you may want to customize the layouts of heading for “blog” pages vs “docs”. This can be achieved by creating layouts/partials/print/page-heading-<type>.html
- eg. page-heading-blog.html
. It defaults to using the page title and description as a heading.
Similarly, the formatting for each page can be customized by creating layouts/partials/print/content-<type>.html
.
8 - Analytics, User Feedback, and SEO
Adding Analytics
The Docsy theme builds upon Hugo’s support for Google Analytics, which Hugo provides through internal templates. Once you set up analytics as described below, usage information for your site (such as page views) is sent to your Google Analytics account.
Prerequisites
You will need an analytics ID for your website before proceeding (technically it’s called a measurement ID or property ID but we’ll use the term “analytics ID” in this guide). If you don’t have one, see the How to get started section of Introducing Google Analytics 4 (GA4).
Tip
Your project’s analytics ID is a string that starts withG-
(a GA4
measurement ID) or UA-
(a universal analytics property ID).Setup
Enable Google Analytics by adding your project’s analytics ID to the site configuration file. For details, see Configure Google Analytics.
By default, Docsy uses the gtag.js analytics library for both GA4 (which
requires gtag.js
) and Universal Analytics (UA) site tags. If you prefer using
the older analytics.js
library for your UA site tag, then set
params.disableGtagForUniversalAnalytics
to true in your project’s config.
Warning
You can configure your project’s analytics ID by setting either the top-level
googleAnalytics
config parameter or services.googleAnalytics.id
. Do not
define both, otherwise this can result in unexpected behavior. For
details, see Is services.googleAnalytics.id an alias for
googleAnalytics.
Production-only feature!
Analytics are enabled only for production builds (called “environments” in Hugo terminology). For information about Hugo environments and how to set them, see the following discussion.User Feedback
By default Docsy puts a “was this page helpful?” feedback widget at the bottom of every documentation page, as shown in Figure 1.
After clicking Yes the user should see a response like Figure 2. You can
configure the response text in config.toml
.
How is this data useful?
When you have a lot of documentation, and not enough time to update it all, you can use the “was this page helpful?” feedback data to help you decide which pages to prioritize. In general, start with the pages with a lot of pageviews and low ratings. “Low ratings” in this context means the pages where users are clicking No — the page wasn’t helpful — more often than Yes — the page was helpful. You can also study your highly-rated pages to develop hypotheses around why your users find them helpful.
In general, you can develop more certainty around what patterns your users find helpful or unhelpful if you introduce isolated changes in your documentation whenever possible. For example, suppose that you find a tutorial that no longer matches the product. You update the instructions, check back in a month, and the score has improved. You now have a correlation between up-to-date instructions and higher ratings. Or, suppose you study your highly-rated pages and discover that they all start with code samples. You find 10 other pages with their code samples at the bottom, move the samples to the top, and discover that each page’s score has improved. Since this was the only change you introduced on each page, it’s more reasonable to believe that your users find code samples at the top of pages helpful. The scientific method, applied to technical writing, in other words!
Setup
Open
config.toml
/config.yaml
/config.json
.Ensure that Google Analytics is enabled, as described above.
Set the response text that users see after clicking Yes or No.
[params.ui.feedback] enable = true yes = 'Glad to hear it! Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">tell us how we can improve</a>.' no = 'Sorry to hear that. Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new">tell us how we can improve</a>.'
params: ui: feedback: enable: true 'yes': >- Glad to hear it! Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new"> tell us how we can improve</a>. 'no': >- Sorry to hear that. Please <a href="https://github.com/USERNAME/REPOSITORY/issues/new"> tell us how we can improve</a>.
{ "params": { "ui": { "feedback": { "enable": true, "yes": "Glad to hear it! Please <a href=\"https://github.com/USERNAME/REPOSITORY/issues/new\"> tell us how we can improve</a>.", "no": "Sorry to hear that. Please <a href=\"https://github.com/USERNAME/REPOSITORY/issues/new\"> tell us how we can improve</a>." } } } }
Save and close
config.toml
/config.yaml
/config.json
.
Access the feedback data
This section assumes basic familiarity with Google Analytics. For example, you should know how to check pageviews over a certain time range and navigate between accounts if you have access to multiple documentation sites.
- Open Google Analytics.
- Open Behavior > Events > Overview.
- In the Event Category table click the Helpful row. Click view full report if you don’t see the Helpful row.
- Click Event Label. You now have a page-by-page breakdown of ratings.
Here’s what the 4 columns represent:
- Total Events is the total number of times that users clicked either Yes or No.
- Unique Events provides a rough indication of how frequently users are rating your pages per session. For example, suppose your Total Events is 5000, and Unique Events is 2500. This means that you have 2500 users who are rating 2 pages per session.
- Event Value isn’t that useful.
- Avg. Value is the aggregated rating for that page. The value is always between 0 and 1. When users click No a value of 0 is sent to Google Analytics. When users click Yes a value of 1 is sent. You can think of it as a percentage. If a page has an Avg. Value of 0.67, it means that 67% of users clicked Yes and 33% clicked No.
The underlying Google Analytics infrastructure that stores the “was this page
helpful?” data is called Events. See docsy pull request #1 to
see exactly what happens when a user clicks Yes or No. It’s just a
click
event listener that fires the Google Analytics JavaScript function for
logging an Event, disables the Yes and No buttons, and shows the
response text.
Disable feedback on a single page
Add the parameter hide_feedback
to the page’s front matter and set it to
true
.
+++
hide_feedback = true
+++
---
hide_feedback: true
---
{
"hide_feedback": true
}
Disable feedback on all pages
Set params.ui.feedback.enable
to false
in
config.toml
/config.yaml
/config.json
:
[params.ui.feedback]
enable = false
params:
ui:
feedback:
enable: false
{
"params": {
"ui": {
"feedback": {
"enable": false
}
}
}
}
Add a contact form with Fabform
You can create a contact form for your site and collect your form submissions at fabform.io. To use this feature, you first need to sign up for an account with Fabform. The following example shows how to add a simple form that collects the user’s email address to your site source:
<form action="https://fabform.io/f/{form-id}" method="post">
<label for="email">Your Email</label>
<input name="email" type="email">
<button type="submit">Submit</button>
</form>
For more details, see Add a Hugo contact form in the Fabform documentation.
Search Engine Optimization meta tags
To learn how to optimize your site for SEO see, Search Engine Optimization (SEO) Starter Guide.
Google
recommends
using the description
meta tag to tell search engines what your page is about.
For each generated page, Docsy will set the content of the meta description
by
using the first of the following that is defined:
- The page
description
frontmatter field - For non-index pages, the page summary, as computed by Hugo
- The site description taken from the site
params
For the template code used to perform this computation, see layouts/partials/page-description.html.
Add more meta tags as needed to your project’s copy of the head-end.html
partial. For details, see Customizing templates.
9 - Repository Links
The Docsy docs and blog layouts include links for readers to edit the page or create issues for your docs or project via your site’s source repository. The current generated links for each docs or blog page are:
- View page source: Brings the user to the page source in your docs repo.
- Edit this page: Brings the user to an editable version of the page content in their fork (if available) of your docs repo. If the user doesn’t have a current fork of your docs repo, they are invited to create one before making their edit. The user can then create a pull request for your docs.
- Create child page: Brings the user to a create new file form in their fork of your docs repo. The new file will be located as a child of the page they clicked the link on. The form will be pre-populated with a template the user can edit to create their page. You can change this by adding
assets/stubs/new-page-template.md
to your own project. - Create documentation issue: Brings the user to a new issue form in your docs repo with the name of the current page as the issue’s title.
- Create project issue (optional): Brings the user to a new issue form in your project repo. This can be useful if you have separate project and docs repos and your users want to file issues against the project feature being discussed rather than your docs.
This page shows you how to configure these links.
Currently, Docsy supports only GitHub repository links “out of the box”. Since GitLab can handle the same link scheme, it should work as well. If you are using another repository such as Bitbucket and would like generated repository links, feel free to add a feature request or update our theme.
Link configuration
There are four variables you can configure in config.toml
/config.yaml
/config.json
to set up links, as well as one in your page metadata.
github_repo
The URL for your site’s source repository. This is used to generate the Edit this page, Create child page, and Create documentation issue links.
github_repo = "https://github.com/google/docsy"
github_repo: 'https://github.com/google/docsy'
{
"github_repo": "https://github.com/google/docsy"
}
github_subdir
(optional)
Specify a value here if your content directory is not in your repo’s root directory. For example, this site is in the userguide
subdirectory of its repo. Setting this value means that your edit links will go to the right page.
github_subdir = "userguide"
github_subdir: 'userguide'
{
"github_subdir": "userguide"
}
github_project_repo
(optional)
Specify a value here if you have a separate project repo and you’d like your users to be able to create issues against your project from the relevant docs. The Create project issue link appears only if this is set.
github_project_repo = "https://github.com/google/docsy"
github_project_repo: 'https://github.com/google/docsy'
{
"github_project_repo": "https://github.com/google/docsy"
}
github_branch
(optional)
Specify a value here if you have would like to reference a different branch for the other github settings like Edit this page or Create project issue.
github_branch = "release"
github_branch: 'release'
{
"github_branch": "release"
}
path_base_for_github_subdir
(optional)
Suppose that the source files for all of the pages under content/some-section
come from another repo, such as a git submodule. Add settings like these to
the section’s index page so that the repository links for all pages in that
section refer to the originating repo:
+++
title = "Some super section"
[cascade]
github_repo = "https://github.com/some-username/another-repo/"
github_subdir = "docs"
path_base_for_github_subdir = "content/some-section"
…
+++
---
title: Some super section
cascade:
github_repo: https://github.com/some-username/another-repo/
github_subdir: docs
path_base_for_github_subdir: content/some-section
…
---
{
"title": "Some super section",
"cascade": {
"github_repo": "https://github.com/some-username/another-repo/",
"github_subdir": "docs",
"path_base_for_github_subdir": "content/some-section"
}
}
As an example, consider a page at the path
content/some-section/subpath/some-page.md
with github_branch
globally set to
main
. The index page settings above will generate the following edit link for
some-page.md
:
https://github.com/some-username/another-repo/edit/main/docs/subpath/some-page.md
If you only have a single page originating from another repo, then omit the
cascade
key and write, at the top-level, the same settings as illustrated
above.
If you’d like users to create project issues in the originating repo as well,
then also set github_project_repo
, something like this:
---
...
cascade:
github_repo: &repo https://github.com/some-username/another-repo/
github_project_repo: *repo
...
---
+++
…
[cascade]
github_repo = "https://github.com/some-username/another-repo/"
github_project_repo = "https://github.com/some-username/another-repo/"
…
+++
---
…
cascade:
github_repo: &repo https://github.com/some-username/another-repo/
github_project_repo: *repo
…
---
{
"cascade": {
"github_repo": "https://github.com/some-username/another-repo/",
"github_project_repo": "https://github.com/some-username/another-repo/"
}
}
Tip
Please note that the YAML code fragment makes use of Yaml anchor. Use of Yaml anchors is optional, but it helps keep the settings DRY.The path_base_for_github_subdir
setting is a regular expression, so you can
use it even if you have a site with multiple languages for example:
+++
…
path_base_for_github_subdir = "content/\w+/some-section"
…
+++
---
…
path_base_for_github_subdir: content/\w+/some-section
…
---
{
…
"path_base_for_github_subdir": "content/\w+/some-section"
…
}
In situations where a page originates from a file under a different name, you
can specify from
and to
path-rename settings. Here’s an example where an
index file is named README.md
in the originating repo:
+++
…
github_repo = "https://github.com/some-username/another-repo/"
github_subdir = "docs"
[path_base_for_github_subdir]
from = "content/some-section/(.*?)/_index.md"
to = "$1/README.md"
…
+++
---
…
github_repo: https://github.com/some-username/another-repo/
github_subdir: docs
path_base_for_github_subdir:
from: content/some-section/(.*?)/_index.md
to: $1/README.md
…
---
{
…
"github_repo": "https://github.com/some-username/another-repo/",
"github_subdir": "docs",
"path_base_for_github_subdir": {
"from": "content/some-section/(.*?)/_index.md",
"to": "$1/README.md"
},
…
}
github_url
(optional)
Deprecation note
This setting is deprecated. Use path_base_for_github_subdir instead.Specify a value for this in your page metadata to set a specific edit URL for this page, as in the following example:
+++
title = "Some page"
github_url = "https://github.com/some-username/another-repo/edit/main/README.md"
…
+++
---
title: Some page
github_url: https://github.com/some-username/another-repo/edit/main/README.md
…
---
{
"title": "Some page",
"github_url": "https://github.com/some-username/another-repo/edit/main/README.md",
…
}
This can be useful if you have page source files in multiple Git repositories, or require a non-GitHub URL. Pages using this value have Edit this page links only.
Disabling links
You can use CSS to selectively disable (hide) links. For example, add the
following to your projects’s _styles_project.scss
file
to hide Create child page links from all pages:
.td-page-meta--child { display: none !important; }
Each link kind has an associated unique class named .td-page-meta--KIND
, as
defined by the following table:
Link kind | Class name |
---|---|
View page source | .td-page-meta--view |
Edit this page | .td-page-meta--edit |
Create child page | .td-page-meta--child |
Create documentation issue | .td-page-meta--issue |
Create project issue | .td-page-meta--project-issue |
Of course, you can also use these classes to give repository links unique styles for your project.
10 - Taxonomy Support
Docsy supports Hugo’s Taxonomies (see: https://gohugo.io/content-management/taxonomies/) in its docs and blog section. You can see the default layout and can test the behavior of the generated links on this page.
Terminology
To understand the usage of taxonomies you should understand the following terminology:
- Taxonomy
- a categorization that can be used to classify content - e.g.: Tags, Categories, Projects, People
- Term
- a key within the taxonomy - e.g. within projects: Project A, Project B
- Value
- a piece of content assigned to a term - e.g. a page of your site, that belongs to a specific project
A example taxonomy for a movie website you can find in the official Hugo docs: https://gohugo.io/content-management/taxonomies/#example-taxonomy-movie-website
Parameters
There are various parameter to control the functionality of taxonomies in the config.toml
.
By default taxonomies for tags
and categories
are enabled in Hugo (see: https://gohugo.io/content-management/taxonomies/#default-taxonomies). In Docsy taxonomies are disabled by default in the config.toml
/config.yaml
/config.json
:
disableKinds = ["taxonomy", "taxonomyTerm"]
disableKinds:
- taxonomy
- taxonomyTerm
{
"disableKinds": [
"taxonomy",
"taxonomyTerm"
]
}
If you want to enable taxonomies in Docsy you have to delete (or comment out) this line in your projects config.toml
/config.yaml
/config.json
. Then the taxonomy pages for tags
and categories
will be generated by Hugo. If you want to use other taxonomies you have to define them in your config.toml
. If you want to use beside your own taxonomies also the default taxonomies tags
and categories
, you also have to define them beside your own taxonomies. You need to provide both the plural and singular labels for each taxonomy.
With the following example you define a additional taxonomy projects
beside the default taxonomies tags
and categories
:
[taxonomies]
tag = "tags"
category = "categories"
project = "projects"
taxonomies:
tag: tags
category: categories
project: projects
{
"taxonomies": {
"tag": "tags",
"category": "categories",
"project": "projects"
}
}
You can use the following parameters in your projects config.toml
/config.yaml
/config.json
to control the output of the assigned taxonomy terms for each article resp. page of your docs and/or blog section in Docsy or a “tag cloud” in Docsy’s right sidebar:
[params.taxonomy]
taxonomyCloud = ["projects", "tags"] # set taxonomyCloud = [] to hide taxonomy clouds
taxonomyCloudTitle = ["Our Projects", "Tag Cloud"] # if used, must have same length as taxonomyCloud
taxonomyPageHeader = ["tags", "categories"] # set taxonomyPageHeader = [] to hide taxonomies on the page headers
params:
taxonomy:
taxonomyCloud:
- projects # remove all entries
- tags # to hide taxonomy clouds
taxonomyCloudTitle: # if used, must have the same
- Our Projects # number of entries as taxonomyCloud
- Tag Cloud
taxonomyPageHeader:
- tags # remove all entries
- categories # to hide taxonomy clouds
{
"params": {
"taxonomy": {
"taxonomyCloud": [
"projects",
"tags"
],
"taxonomyCloudTitle": [
"Our Projects",
"Tag Cloud"
],
"taxonomyPageHeader": [
"tags",
"categories"
]
}
}
}
The settings above would only show a taxonomy cloud for projects
and tags
(with the headlines “Our Projects” and “Tag Cloud”) in Docsy’s right sidebar and the assigned terms for the taxonomies tags
and categories
for each page.
To disable any taxonomy cloud you have to set the Parameter taxonomyCloud = []
resp. if you don’t want to show the assigned terms you have to set taxonomyPageHeader = []
.
As default the plural label of a taxonomy is used as it cloud title. You can overwrite the default cloud title with taxonomyCloudTitle
. But if you do so, you have to define a manual title for each enabled taxonomy cloud (taxonomyCloud
and taxonomyCloudTitle
must have the same length!).
If you don’t set the parameters taxonomyCloud
resp. taxonomyPageHeader
the taxonomy clouds resp. assigned terms for all defined taxonomies will be generated.
Partials
The by default used partials for displaying taxonomies are so defined, that you should be able to use them also easily in your own layouts.
taxonomy_terms_article
The partial taxonomy_terms_article
shows all assigned terms of an given taxonomy (partial parameter taxo
) of an article respectively page (partial parameter context
, most of the time the current page or context .
).
Example usage in layouts/docs/list.html
for the header of each page in the docs section:
{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
{{ partial "taxonomy_terms_article.html" (dict "context" $context "taxo" $taxo ) }}
{{ end }}
This will gave you for each in the current page (resp. context) defined taxonomy a list with all assigned terms:
<div class="taxonomy taxonomy-terms-article taxo-categories">
<h5 class="taxonomy-title">Categories:</h5>
<ul class="taxonomy-terms">
<li><a class="taxonomy-term" href="//localhost:1313/categories/taxonomies/" data-taxonomy-term="taxonomies"><span class="taxonomy-label">Taxonomies</span></a></li>
</ul>
</div>
<div class="taxonomy taxonomy-terms-article taxo-tags">
<h5 class="taxonomy-title">Tags:</h5>
<ul class="taxonomy-terms">
<li><a class="taxonomy-term" href="//localhost:1313/tags/tagging/" data-taxonomy-term="tagging"><span class="taxonomy-label">Tagging</span></a></li>
<li><a class="taxonomy-term" href="//localhost:1313/tags/structuring-content/" data-taxonomy-term="structuring-content"><span class="taxonomy-label">Structuring Content</span></a></li>
<li><a class="taxonomy-term" href="//localhost:1313/tags/labelling/" data-taxonomy-term="labelling"><span class="taxonomy-label">Labelling</span></a></li>
</ul>
</div>
taxonomy_terms_article_wrapper
The partial taxonomy_terms_article_wrapper
is a wrapper for the partial taxonomy_terms_article
with the only parameter context
(most of the time the current page or context .
) and checks the taxonomy parameters of your project’s config.toml
/config.yaml
/config.json
to loop threw all listed taxonomies in the parameter taxonomyPageHeader
resp. all defined taxonomies of your page, if taxonomyPageHeader
isn’t set.
taxonomy_terms_cloud
The partial taxonomy_terms_cloud
shows all used terms of an given taxonomy (partial parameter taxo
) for your site (partial parameter context
, most of the time the current page or context .
) and with the parameter title
as headline.
Example usage in partial taxonomy_terms_clouds
for showing all defined taxonomies and its terms:
{{ $context := . }}
{{ range $taxo, $taxo_map := .Site.Taxonomies }}
{{ partial "taxonomy_terms_cloud.html" (dict "context" $context "taxo" $taxo "title" ( humanize $taxo ) ) }}
{{ end }}
As an example this will gave you for following HTML markup for the taxonomy categories
:
<div class="taxonomy taxonomy-terms-cloud taxo-categories">
<h5 class="taxonomy-title">Cloud of Categories</h5>
<ul class="taxonomy-terms">
<li><a class="taxonomy-term" href="//localhost:1313/categories/category-1/" data-taxonomy-term="category-1"><span class="taxonomy-label">category 1</span><span class="taxonomy-count">3</span></a></li>
<li><a class="taxonomy-term" href="//localhost:1313/categories/category-2/" data-taxonomy-term="category-2"><span class="taxonomy-label">category 2</span><span class="taxonomy-count">1</span></a></li>
<li><a class="taxonomy-term" href="//localhost:1313/categories/category-3/" data-taxonomy-term="category-3"><span class="taxonomy-label">category 3</span><span class="taxonomy-count">2</span></a></li>
<li><a class="taxonomy-term" href="//localhost:1313/categories/category-4/" data-taxonomy-term="category-4"><span class="taxonomy-label">category 4</span><span class="taxonomy-count">6</span></a></li>
</ul>
</div>
taxonomy_terms_clouds
The partial taxonomy_terms_clouds
is a wrapper for the partial taxonomy_terms_cloud
with the only parameter context
(most of the time the current page or context .
) and checks the taxonomy parameters of your project’s config.toml
/config.yaml
/config.json
to loop threw all listed taxonomies in the parameter taxonomyCloud
resp. all defined taxonomies of your page, if taxonomyCloud
isn’t set.
Multi language support for taxonomies
The taxonomy terms associated content gets only counted and linked WITHIN the language! The control parameters for the taxonomy support can also get assigned language specific.
11 - Diagrams and Formulae
Docsy has built-in support for a number of diagram creation and typesetting tools you can use to add rich content to your site, including \(\KaTeX\), Mermaid, Diagrams.net, PlantUML, and MarkMap.
\(\LaTeX\) support with \(\KaTeX\)
\(\LaTeX\) is a high-quality typesetting system for the production of technical and scientific documentation. Due to its excellent math typesetting capabilities, \(\TeX\) became the de facto standard for the communication and publication of scientific documents, especially if these documents contain a lot of mathematical formulae. Designed and mostly written by Donald Knuth, the initial version was released in 1978. Dating back that far, \(\LaTeX\) has pdf
as its primary output target and is not particularly well suited for producing HTML output for the Web. Fortunately, with \(\KaTeX\) there exists a fast and easy-to-use JavaScript library for \(\TeX\) math rendering on the web, which was integrated into the Docsy theme.
With \(\KaTeX\) support enabled in Docsy, you can include complex mathematical formulae into your web page, either inline or centred on its own line. Since \(\KaTeX\) relies on server side rendering, it produces the same output regardless of your browser or your environment. Formulae can be shown either inline or in display mode:
Inline formulae
The following code sample produces a text line with three inline formulae:
When \\(a \ne 0\\), there are two solutions to \\(ax^2 + bx + c= 0\\) and they are \\(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\\).
When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c= 0\) and they are \(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\).
Formulae in display mode
The following code sample produces an introductory text line followed by a formula numbered as (1)
residing on its own line:
The probability of getting \\(k\\) heads when flipping \\(n\\) coins is:
```math
\tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k}
```
The formula itself is written inside a GLFM math block. The above code fragment renders to:
The probability of getting \(k\) heads when flipping \(n\) coins is:
$$ \tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k} $$
Warning
math
code blocks are only supported as of hugo version 0.93.
In case of hugo version 0.92 or lower, use this code snippet to display the formula:
$$
\tag*{(1)} P(E) = {n \choose k} p^k (1-p)^{n-k}
$$
Tip
This wiki page provides in-depth information about typesetting mathematical formulae using the \(\LaTeX\) typesetting system.Activating and configuring \(\KaTeX\) support
Auto activation
As soon as you use a math
code block on your page, support of \(\KaTeX\) is automatically enabled.
Manual activation (no math
code block present or hugo 0.92 or lower)
If you want to use inline formulae and don’t have a math
code block present in your page which triggers auto activation, you need to manually activate \(\KaTeX\) support. The easiest way to do so is to add a math
attribute to the frontmatter of your page and set it to true
:
+++
math = true
+++
---
math: true
---
{
"math": true
}
If you use formulae in most of your pages, you can also enable sitewide \(\KaTeX\) support inside the Docsy theme. To do so update config.toml
/config.yaml
/config.json
:
[params.katex]
enable = true
params:
katex:
enable: true
{
"params": {
"katex": {
"enable": true
}
}
}
Additionally, you can customize various \(\KaTeX\) options inside config.toml
/config.yaml
/config.json
, if needed:
[params.katex]
# enable/disable KaTeX support
enable = true
# Element(s) scanned by auto render extension. Default: document.body
html_dom_element = "document.body"
[params.katex.options]
# If true (the default), KaTeX will throw a ParseError when it encounters an
# unsupported command or invalid LaTeX. If false, KaTeX will render unsupported
# commands as text, and render invalid LaTeX as its source code with hover text
# giving the error, in the color given by errorColor.
throwOnError = false
errorColor = "#CD5C5C"
# This is a list of delimiters to look for math, processed in the same order as
# the list. Each delimiter has three properties:
# left: A string which starts the math expression (i.e. the left delimiter).
# right: A string which ends the math expression (i.e. the right delimiter).
# display: Whether math in the expression should be rendered in display mode.
[[params.katex.options.delimiters]]
left = "$$"
right = "$$"
display = true
[[params.katex.options.delimiters]]
left = "$"
right = "$"
display = false
[[params.katex.options.delimiters]]
left = "\\("
right = "\\)"
display = false
[[params.katex.options.delimiters]]
left = "\\["
right = "\\]"
display = true
params:
katex:
enable: true # enable/disable KaTeX support
html_dom_element: document.body # Element(s) scanned by auto render extension. Default: document.body
options:
# If true (the default), KaTeX will throw a ParseError when it encounters an
# unsupported command or invalid LaTeX. If false, KaTeX will render unsupported
# commands as text, and render invalid LaTeX as its source code with hover text
# giving the error, in the color given by errorColor.
throwOnError: false
errorColor: '#CD5C5C'
# This is a list of delimiters to look for math, processed in the same order as
# the list. Each delimiter has three properties:
# left: A string which starts the math expression (i.e. the left delimiter).
# right: A string which ends the math expression (i.e. the right delimiter).
# display: Whether math in the expression should be rendered in display mode.
delimiters:
- left: $$
right: $$
display: true
- left: $
right: $
display: false
- left: \(
right: \)
display: false
- left: \[
right: \]
display: true
{
"params": {
"katex": {
"enable": true,
"html_dom_element": "document.body",
"options": {
"throwOnError": false,
"errorColor": "#CD5C5C",
"delimiters": [
{
"left": "$$",
"right": "$$",
"display": true
},
{
"left": "$",
"right": "$",
"display": false
},
{
"left": "\\(",
"right": "\\)",
"display": false
},
{
"left": "\\[",
"right": "\\]",
"display": true
}
]
}
}
}
}
For a complete list of options and their detailed description, have a look at the documentation of \({\KaTeX}’s\) Rendering API options and of \({\KaTeX}’s\) configuration options.
Display of Chemical Equations and Physical Units
mhchem is a \(\LaTeX\) package for typesetting chemical molecular formulae and equations. Fortunately, \(\KaTeX\) provides the mhchem
extension that makes the mhchem
package accessible when authoring content for the web. With mhchem
extension enabled, you can easily include chemical equations into your page. An equation can be shown either inline or can reside on its own line. The following code sample produces a text line including a chemical equation:
*Precipitation of barium sulfate:* \\(\ce{SO4^2- + Ba^2+ -> BaSO4 v}\\)
Precipitation of barium sulfate: \(\ce{SO4^2- + Ba^2+ -> BaSO4 v}\)
More complex equations need to be displayed on their own line. Use a code block adorned with chem
in order to achieve this:
```chem
\tag*{(2)} \ce{Zn^2+ <=>[+ 2OH-][+ 2H+] $\underset{\text{amphoteric hydroxide}}{\ce{Zn(OH)2 v}}$ <=>[+ 2OH-][+ 2H+] $\underset{\text{tetrahydroxozincate}}{\ce{[Zn(OH)4]^2-}}$}
```
\tag*{(2)} \ce{Zn^2+ <=>[+ 2OH-][+ 2H+] $\underset{\text{amphoteric hydroxide}}{\ce{Zn(OH)2 v}}$ <=>[+ 2OH-][+ 2H+] $\underset{\text{tetrahydroxozincate}}{\ce{[Zn(OH)4]^2-}}$}
Warning
chem
code blocks are only supported as of hugo version 0.93.
In case of hugo version 0.92 or lower, use this code snippet to display the formula:
$$
\tag*{(2)} \ce{Zn^2+ <=>[+ 2OH-][+ 2H+] $\underset{\text{amphoteric hydroxide}}{\ce{Zn(OH)2 v}}$ <=>[+ 2OH-][+ 2H+] $\underset{\text{tetrahydroxozincate}}{\ce{[Zn(OH)4]^2-}}$}
$$
Note
The manual for mchem’s input syntax provides in-depth information about typesetting chemical formulae and physical units using themhchem
tool.Use of mhchem
is not limited to the authoring of chemical equations, using the included \pu
command, pretty looking physical units can be written with ease, too. The following code sample produces two text lines with four numbers plus their corresponding physical units:
* Scientific number notation: \\(\pu{1.2e3 kJ}\\) or \\(\pu{1.2E3 kJ}\\) \\
* Divisions: \\(\pu{123 kJ/mol}\\) or \\(\pu{123 kJ//mol}\\)
- Scientific number notation: \(\pu{1.2e3 kJ}\) or \(\pu{1.2E3 kJ}\)
- Divisions: \(\pu{123 kJ/mol}\) or \(\pu{123 kJ//mol}\)
For a complete list of options when authoring physical units, have a look at the section on physical units in the mhchem
documentation.
Activating rendering support for chemical formulae
Auto activation
As soon as you use a chem
code block on your page, rendering support for chemical equations is automatically enabled.
Manual activation (no chem
code block present or hugo 0.92 or lower)
If you want to use chemical formulae inline and don’t have a chem
code block present in your page which triggers auto activation, you need to manually activate rendering support for chemical formulae. The easiest way to do so is to add a chem
attribute to the frontmatter of your page and set it to true
:
+++
chem = true
+++
---
chem: true
---
{
"chem": true
}
If you use formulae in most of your pages, you can also enable sitewide rendering support for chemical formulae inside the Docsy theme. To do so, enable mhchem
inside your config.toml
/config.yaml
/config.json
:
[params.katex]
enable = true
[params.katex.mhchem]
enable = true
params:
katex:
enable: true
mhchem:
enable: true
{
"params": {
"katex": {
"enable": true,
"mhchem": {
"enable": true
}
}
}
}
Diagrams with Mermaid
Mermaid is a Javascript library for rendering simple text definitions to useful diagrams in the browser. It can generate a variety of different diagram types, including flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, user journey diagrams, Gantt charts and pie charts.
With Mermaid support enabled in Docsy, you can include the text definition of a Mermaid diagram inside a code block, and it will automatically be rendered by the browser as soon as the page loads.
The great advantage of this is anyone who can edit the page can now edit the diagram - no more hunting for the original tools and version to make a new edit.
For example, the following defines a simple flowchart:
```mermaid
graph TD
Start --> Need{"Hugo version >= 0.93.0"}
Need -- No --> Off["Set params.mermaid.enable = true"]
Off --> Author
Need -- Yes --> Author[Insert mermaid codeblock]
```
Automatically renders to:
graph TD
Start --> Need{"Hugo version >= 0.93.0"}
Need -- No --> Off["Set params.mermaid.enable = true"]
Off --> Author
Need -- Yes --> Author[Insert mermaid codeblock]
With hugo version 0.93 or higher, support of Mermaid diagrams is automatically enabled as soon as you use a mermaid
code block on your page.
If you are using hugo version 0.92 or lower, you need to enable Mermaid manually by updating your config.toml
/config.yaml
/config.json
:
[params.mermaid]
enable = true
params:
mermaid:
enable: true
{
"params": {
"mermaid": {
"enable": true
}
}
}
If needed, you can define custom settings for your diagrams, such as themes, padding in your config.toml
/config.yaml
/config.json
.
[params.mermaid]
theme = "neutral"
[params.mermaid.flowchart]
diagramPadding = 6
params:
mermaid:
theme: neutral
flowchart:
diagramPadding: 6
{
"params": {
"mermaid": {
"theme": "neutral",
"flowchart": {
"diagramPadding": 6
}
}
}
}
See the Mermaid documentation for a list of defaults that can be overridden.
Settings can also be overridden on a per-diagram basis by making use of the %%init%%
header at the start of the diagram definition. See the Mermaid theming documentation.
UML Diagrams with PlantUML
PlantUML is an alternative to Mermaid that lets you quickly create UML diagrams, including sequence diagrams, use case diagrams, and state diagrams. Unlike Mermaid diagrams, which are entirely rendered in the browser, PlantUML uses a PlantUML server to create diagrams. You can use the provided default demo server (not recommended for production use), or run a server yourself. PlantUML offers a wider range of image types than Mermaid, so may be a better choice for some use cases.
Diagrams are defined using a simple and intuitive language. (see PlantUML Language Reference Guide).
The following example shows a use case diagram:
```plantuml
participant participant as Foo
actor actor as Foo1
boundary boundary as Foo2
control control as Foo3
entity entity as Foo4
database database as Foo5
collections collections as Foo6
queue queue as Foo7
Foo -> Foo1 : To actor
Foo -> Foo2 : To boundary
Foo -> Foo3 : To control
Foo -> Foo4 : To entity
Foo -> Foo5 : To database
Foo -> Foo6 : To collections
Foo -> Foo7: To queue
```
Automatically renders to:
participant participant as Foo
actor actor as Foo1
boundary boundary as Foo2
control control as Foo3
entity entity as Foo4
database database as Foo5
collections collections as Foo6
queue queue as Foo7
Foo -> Foo1 : To actor
Foo -> Foo2 : To boundary
Foo -> Foo3 : To control
Foo -> Foo4 : To entity
Foo -> Foo5 : To database
Foo -> Foo6 : To collections
Foo -> Foo7: To queue
To enable/disable PlantUML, update config.toml
/config.yaml
/config.json
:
[params.plantuml]
enable = true
params:
plantuml:
enable: true
{
"params": {
"plantuml": {
"enable": true
}
}
}
Other optional settings are:
[params.plantuml]
enable = true
theme = "default"
# Set url to plantuml server
# default is http://www.plantuml.com/plantuml/svg/
svg_image_url = "https://www.plantuml.com/plantuml/svg/"
# By default the plantuml implementation uses <img /> tags to display UML diagrams.
# When svg is set to true, diagrams are displayed using <svg /> tags, maintaining functionality like links e.g.
# default = false
svg = true
params:
plantuml:
enable: true
theme: default
# Set url to plantuml server
# default is http://www.plantuml.com/plantuml/svg/
svg_image_url: 'https://www.plantuml.com/plantuml/svg/'
# By default the plantuml implementation uses <img /> tags to display UML diagrams.
# When svg is set to true, diagrams are displayed using <svg /> tags, maintaining functionality like links e.g.
# default = false
svg: true
{
"params": {
"plantuml": {
"enable": true,
"theme": "default",
"svg_image_url": "https://www.plantuml.com/plantuml/svg/",
"svg": true
}
}
}
MindMap support with MarkMap
MarkMap is a Javascript library for rendering simple text definitions to MindMap in the browser.
For example, the following defines a simple MindMap:
```markmap
# markmap
## Links
- <https://markmap.js.org/>
- [GitHub](https://github.com/gera2ld/markmap)
## Related
- [coc-markmap](https://github.com/gera2ld/coc-markmap)
- [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap)
## Features
- links
- **inline** ~~text~~ *styles*
- multiline
text
- `inline code`
-
```js
console.log('code block');
```
- Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
```
Automatically renders to:
# markmap
## Links
- <https://markmap.js.org/>
- [GitHub](https://github.com/gera2ld/markmap)
## Related
- [coc-markmap](https://github.com/gera2ld/coc-markmap)
- [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap)
## Features
- links
- **inline** ~~text~~ *styles*
- multiline
text
- `inline code`
-
```js
console.log('code block');
```
- Katex - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
To enable/disable MarkMap, update config.toml
/config.yaml
/config.json
:
[params.markmap]
enable = true
params:
markmap:
enable: true
{
"params": {
"markmap": {
"enable": true
}
}
}
Diagrams with Diagrams.net
Diagrams.net (aka draw.io) provides a free and open source diagram editor that can generate a wider range of diagrams than Mermaid or PlantUML using a web or desktop editor.
SVG and PNG files exported with the tool contain the source code of the original diagram by default, which allows the diagrams.net site to import those images again for edit in the future. Docsy can detect this and automatically add an “edit” button over any image that can be edited using the online site.
Hover over the image below and click edit to instantly start working with it. Clicking the “Save” button will cause the edited diagram to be exported using the same filename and filetype, and downloaded to your browser.
Note
If you’re creating a new diagram, be sure to File -> Export in either svg or png format (svg is usually the best choice) and ensure the “Include a copy of my diagram” is selected so it can be edited again later.As the diagram data is transported via the browser, the diagrams.net server does not need to access the content on your Docsy server directly at all.
To disable detection of diagrams, update config.toml
/config.yaml
/config.json
:
[params.drawio]
enable = false
params:
drawio:
enable: false
{
"params": {
"drawio": {
"enable": false
}
}
}
You can also deploy and use your own server for editing diagrams, in which case update the configuration to point to that server:
[params.drawio]
drawio_server = "https://app.mydrawioserver.example.com"
params:
drawio:
drawio_server: 'https://app.mydrawioserver.example.com'
{
"params": {
"drawio": {
"drawio_server": "https://app.mydrawioserver.example.com"
}
}
}