IN THIS ARTICLE
O3DE Documentation Contribution with Hugo
The Open 3D Engine (O3DE) documentation website uses the Hugo static site generator and deploys using Netlify .
Refer to the o3de.org README.md for build instructions and prerequisites, and the Git workflow for more information on how the project works.
Adding new pages
Navigate to the directory under
/content/docs
for the new page.Create a new markdown file for the page:
- If the page is a new sub-section of documentation, create a directory for that subsection and then create a file titled
_index.md
. - If the page is adding to an existing section of documentation, create a file with an appropriate title.
In both cases, the markdown file name and directory name are a part of the page’s URL.
- If the page is a new sub-section of documentation, create a directory for that subsection and then create a file titled
At a minimum, add the following front matter at the top of your file:
--- title: Page title toc: true ---
This will add the page to the main docs menu as well as generate a table of contents on each page.
Some sections use the
weight
frontmatter property to order pages and thedescription
property. For more information, see Hugo’s documentation .
Adding new guides
Only add new guides with approval from maintainers or if you are a maintainer yourself.
Add a new directory directly under
/content/docs
and create an_index.md
file in that directory.Add the following frontmatter:
--- linktitle: Title that appears in the left hand navigation title: Title that appears at the top of the page description: Short description of the page weight: Numerical value menu_uuid: example //see below guide_img: "/images/example/guide_img.svg" //see below ---
The
menu_uuid
field is a short, unique identifier for the guide, with no spaces or special characters. This field is used for generating a CSS class for the menu’s accordion.The
guide_img
field is a relative URL to an image in the/static
directory which serves as the guide’s image on the Learn landing page.
Adding redirects
If you move or rename a page, it’s a good idea to add a redirect from the old page to the new one. This is done via the /static/_redirects
file. This file maps to a standard Apache redirects file (.htaccess) and uses the same syntax for adding redirects.
To add a redirect, add a line to the _redirects
file:
/old_url/partial/ /new_url/partial
Adding top navigation menu items
Add a new item to the top navigation via the config.toml
file in the root of the website repository:
[[menu.main]] // menu.main is the main navigation menu
name = "Learn" //name of the menu item
url = "#" // relative URL – for example, `/docs` links to the docs homepage
weight = 4 // menu ordering
identifier = "learn" // Identifier used for building menus with submenu items
For more information, see Hugo’s documentation on menus .
Menu subitems
If you want to have a menu with a dropdown of submenu items, define the label for the drop-down menu as a menu item, then define its subitems using the parent
field to point to the item they should appear under:
[[menu.main]]
name = "Community"
url = "#"
weight = 3 // menu ordering for the top nav itself
identifier = "community" //matches the parent fields below
[[menu.main]]
name = "Community subitem"
url = "#"
weight = 1 // menu ordering for items in the dropdown
parent = "community" //matches the identifier above
[[menu.main]]
name = "Community subitem 2"
url = "#"
weight = 2 // menu ordering for items in the dropdown
parent = "community" //matches the identifier above
Adding or updating social media accounts
Social media accounts are stored as data in the config.toml
file and read into the layouts via a loop. You can add any social media account you can find an icon for!
[[params.social]]
name = "Discord" // The name of the social media account
url = "#" // The URL to point to
icon = "fas fa-envelope" // the FontAwesome Icon classes
Icons for social media accounts are FontAwesome Icons . The social media parameters store the CSS classes used to fetch the icon from the FontAwesome library. To find these:
Navigate to the FontAwesome page for a specific icon. For example, Here’s Discord .
Locate the HTML snipped for the icon. in this case it’s the following:
<i class="fab fa-discord"></i>
Extract the two classes - for example,
fab fa-discord
.Add these to the
icon
field.
Updating top level pages
O3DE’s top level pages – /docs
, /download
and /community
– all use custom layouts. You’ll need basic knowledge of HTML and CSS (and
Bootstrap ) to update the look and feel of these pages.
In all cases, the following files are key:
/assets/sass/custom.sass
: Stores all custom SCSS for layouts./assets/js/app.js
: Stores Javascript for pages. This is important if you need to update the downloads page, which uses Javascript to parse the browser’s user agent./layouts/partials/javascript.html
: Adds Javascript files to pages. Important if you want to add a new script to the site.
Updating top level page content
The body content (free-form text) of each page is stored in the page’s /content/.../_index.md
file. This is regular markdown content and can be updated at will.
Updating top level page layout structure
This section is a very brief overview of Hugo’s layout/templating engine. For more information, see Hugo’s templating documentation .
Understanding Hugo layout structure
Hugo layouts follow a
lookup order . The /layouts/_default
directory contains the base layouts, which is what Hugo renders if nothing more specific is available. If Hugo finds a layout directory, for example /layouts/download
that matches the same file path as a content directory, /content/download
, it applies the layouts to that content page and its subpages. If it can’t find that, it applies a layout from /layouts/_default
.
Within a layout directory, Hugo looks for one of 4 basic types:
baseof.html
: The “base” template. Do not override this unless you know what you’re doing!section.html
: The template for_index.md
files, or section homepages.single.html
: The template for files in a directory which are not_index.md
files – i.e., regular pages.list.html
: The template for lists of subpages. As this gets a bit confusing withsection.html
, only use this layout for blog sections.
Most of the top level pages in the O3DE site are section.html
pages with no subpages.
Understanding Hugo layout inheritance
As described above, Hugo looks for progressively more specific layouts and applies the most specific one it can find. However, it also does this within layout files by allowing you to override a section called main
.
For example, let’s look at /layouts/_default/baseof.html
:
{{ $lang := site.LanguageCode }}
<!DOCTYPE html>
<html{{ with $lang }} lang="{{ . }}"{{ end }}>
<head>
<title>
{{ block "title" . }}
{{ site.Title }}
{{ end }}
</title>
{{ partial "css.html" . }}
{{ partial "favicon.html" . }}
</head>
<body>
{{ partial "navbar.html" . }}
<main>
{{ block "main" . }}
{{ end }}
</main>
{{ partial "javascript.html" }}
</body>
</html>
Next, let’s look at /layouts/_default/section.html
:
{{ define "main" }}
<div class="container">
<section class="row">
<section class="col col-8">
<h1 class="title">{{ .Page.Title | markdownify }}</h1>
{{ with .Content }}
<div class="content">
{{ . }}
</div>
{{ end }}
</section>
</section>
</div>
{{ end }}
Note that section.html
only defines the main
block. In absence of any other blocks, Hugo looks to baseof.html
to provide the rest of the page’s layout.
This works in a similar manner on other subpages, for example /layouts/download.html
:
{{ define "main" }}
{{ partial "download/hero.html" . }}
{{ with .Content }}
<section class="container-xl mt-5 pt-5">
<div class="row">
<div class="col-12">
{{ . }}
</div>
</div>
</section>
{{ end }}
{{ partial "footer.html" . }}
{{ end }}
In this case, the layout does the following:
- Overrides the
main
section of/layouts/_default/section.html
. - Calls the
/download/hero.html
partial (For more on layout partials, see Hugo’s partial template documentation ) - Adds a div for the body content (
{{ with .Content }}
) - Calls the
footer.html
partial
Hence, if you wanted to update the way the Downloads page works, you’d start with /layouts/downloads/section.html
. If you needed to add something to the <head>
section of the downloads page, however, you’d need to copy layouts/_default/baseof.html
to the /layouts/downloads
directory and override it there.