Create Basic and Placeholder Hugo Pages
Through creating simple pages, we learn how hestiaHUGO operates. A step-by-step guide for hestiaHUGO — ZORALab's Hestia Hugo module.
Learning Objectives
At the end of this tutorial, you will learn:
How hestiaHUGO works with Hugo
How hestiaHUGO governs filesystem pathing and URL
How hestiaHUGO manage all designers' creating freedom via UI components
How hestiaHUGO design to counter the ever-changing W3C changes
How hestiaHUGO design its multiple outputs (HTML & JSON)
How hestiaHUGO handles internationalization by default
Prerequisite
This tutorial assumes you have a fresh hestiaHUGO equipped Hugo repository ready for deployment especially being created from the previous setup tutorial page. Otherwise, please complete that lesson and then revert back to this piece:
Setup Hugo TutorialUnderstand How hestiaHUGO Manage URL with Filesystem
hestiaHUGO natively supports its own multi-languages (a.k.a. 'i18n') feature by
default. IT USES DIRECTORY NAME AS URL PATH and the 1st level is
ISO639-1, ISO639-2, ISO639-3, ISO15924, and ISO3166 LANGUAGE CODE
or language independent pages (e.g. usually redirecting shortcuts). The rest are
the same as Hugo. We advise you to name your directory according to the URL
pattern (no space, small characters, and no funny symbols) and use it eventhough
the content is a single language to avoid building broken URL site in the
future.
PATTERN File path : content/[i18n]/url-compatible-pathing/file.extension URL : [http://baseURL]/[i18n]/url-compatible-pathing/file.extension?query=value#tags EXAMPLES content/ (https://hestia.zoralab.com/) redirects ➔ content/en (https://hestia.zoralab.com/en) redirects ➔ content/zh-hans (https://hestia.zoralab.com/zh-hans/) content/releases (https://hestia.zoralab.com/releases) redirects ➔ content/en/releases/ (https://hestia.zoralab.com/en/releases/) redirects ➔ content/zh-hans/releases/ (https://hestia.zoralab.com/zh-hans/releases/) content/en/releases/v1-0-0/ (https://hestia.zoralab.com/en/releases/v1-0-0/) content/en/releases/v1-1-0/ (https://hestia.zoralab.com/en/releases/v1-1-0/) content/en/releases/v1-2-0/ (https://hestia.zoralab.com/en/releases/v1-2-0/) content/en/releases/v1-2-0/index.html (https://hestia.zoralab.com/en/releases/v1-2-0/) content/en/releases/v1-2-0/index.json (https://hestia.zoralab.com/en/releases/v1-2-0/index.json) content/en/releases/v1-2-0/my-file.zip (https://hestia.zoralab.com/en/releases/v1-2-0/my-file.zip)
Create Hugo's Content Directory
We can now start by creating the Hugo's content directory. It is named inside
your config/_default/config.toml
under the field
contentDir
(usually called content
). You may alter it
as per your need. For this tutorial, we will just stick to the default
content
. After creating the directory, you will need to
restart your hugo server (hint: server.cmd
command). A complete
list of commands would be:
# LINUX / MACOS [ Kill the server with CTRL+C ] $ cd sites/ # your hugo repository if you're not inside it $ mkdir -p content $ ./server.cmd # refer pervious tutorial if you had forgotten # WINDOWS [ Kill the server with CTRL+C ] > cd sites/ # your hugo repository if you're not inside it > mkdir content > server.cmd # refer pervious tutorial if you had forgotten
Create Placeholder Page
We will begin by creating a single language placeholder landing page. We won't
be building this page now but we need it for the page we want to build: the 404
page. hestiaHUGO is designed in the way to be natively compatible with Hugo.
Since this is an English language tutorial, we can proceed to create
content/en
page with hugo command. Remember this important step
because we won't repeat it again and you will be using it a lot. The command is
as shown below:
PATTERN $ hugo new --kind hestia [filesystem path] COMMAND $ hugo new --kind hestia content/en
Understand How hestiaHUGO Manages Page Configurations
Before we continue, let's understand how hestiaHUGO manage page compilations.
If you take a look at the content/en
page, there are a lot of
double underscore TOML files. Due to the complexities of web connectivities
across the Internet, we do not have a choice but to split them into various
pieces of config data. One constant to remember: never touch the Hugo's original
_index.html
file. It is now ONLY USE for hugo to
discover and map the site directories. The way hestiaHUGO is designed
will rarely have any conflict with other Hugo themes. You're still
allowed to place any page associated files (e.g. images only this
page uses, docs, .csv
, etc) in the same directory. Each
known files' roles and responsibilities are listed below:
__assets.toml ➤ manage all CSS and JS files' inclusion or compilation __components.toml ➤ list out all hestiaHUGO UI components for compilation __content.hestiaCSS ➤ the page's final CSS asset for inlining into HTML __content.hestiaHTML ➤ the page's HTML output __content.hestiaJS ➤ the page's final JS asset for inlining into HTML __content.hestiaJSON ➤ the page's JSON output __content.hestiaLDJSON ➤ the page's LD+JSON output for inlining into HTML __contributors.toml ➤ designate list of contributors to this page __data.toml ➤ a page-level data file listed in __page.toml __i18n.toml ➤ a page-level data file listed in __page.toml _index.html ➤ hugo discovery file (**DO NOT TOUCH THIS AT ALL**) __languages.toml ➤ the page's alternate languages URL (translated pages) __page.toml ➤ the page's primary configurations __robots.toml ➤ the page's robots instructions for inlining into HTML __thumbnails.toml ➤ the page's thumbnails used in social media sharing __twitter.toml ➤ the page's Twitter configuration for sharing __wasm.toml ➤ the page's WASM configurations
Update the __page.toml
Don't worry, for placeholding page, you only need to deal
__page.toml
file. This is to setup the page's critical metadata.
A few critical fields you have to update are shown below:
... [Date] Created = 'Sat, 05 Mar 2023 11:22:21 +0800' # update to today's time obviously Published = 'Sat, 05 Mar 2023 11:22:21 +0800' # update to today's time obviously ... [Content] Title = 'My App Page' Keywords = [ 'My App Page', ] ... [Description] Pitch = ''' TBD. ''' Summary = ''' Will be back later. ''' ...
Git Commit Placeholder Page
Now that everything is in place, you can proceed to git commit the page and we
will proceed to deal with the real basic one: /en/404
page. If you
need assistance with Git, you can check out their offical book in the following
URL. Basically, the command is as follows:
$ git add . $ git commit -s --- EDIT IN YOUR EDITOR --- sites: added /en/ page as placeholder Since we need to build /en/404/ page, we have to create the /en/ page as placeholder for now. Hence, let's do this. This patch adds /en/ page as placeholder in sites/ directory. Signed-off-by: Name <EMAIL> --- EDIT IN YOUR EDITOR --- $ git push
Repeat Page Creation for 404 Page
Now that you get the hang of how to create a hestiaHUGO page and updating the
critical file, as a re-cap, please create /en/404 page
(hint:
content/en/404
path). For this page, please DO NOT commit
as we will begin this page creation in the next step.
HINT (1) $ hugo new --kind hestia [filesystem path] (2) $ update __page.toml with the appropriate values for 404 page (3) $ git add .
Update Page-level Twitter Settings
Unlike placeholder page, this time, if you have Twitter account, you can update
the content/en/404/__twitter.toml
config file. Since 404 page is
just a system notice page (and no one insane enough to visit it on purpose),
you only need to update the following:
... [Creator] Handle = 'yourTwitterHandle' # with or without @ is ok ...
Update Page-level Robots Settings
Due to this page being a 404 page, we do not want any search engine robots to
index it. Hence, let's update the content/en/404/__robots.toml
config file. These robot values will be compiled as the page's HTML output's
meta tags. An example would be as follows:
... [[Meta]] Name = 'googleBot' Content = 'noindex, nofollow' [[Meta]] Name = 'robots' Content = 'noindex, nofollow'
Update Page-level Languages Settings
As a good practice and to prevent massive copy-paste error in the future, it is
better we update the page-specific language settings in the
content/en/404/__languages.toml
config file. You're strongly
advised to use RFC3986
compliant relative URL. We will explain
further in the next step. Here's the data to be updated:
... [en] URL = '/en/404' ...
Understand How hestiaHUGO Process URL
hestiaHUGO deploys its own URL data processor (called
hestiaURL/Sanitize
partial function). We strongly encourage using
relative URL for pre-compilations (e.g. your page templates and etc) while
letting hestiaHUGO to compile it to absolute URL as output. Visitor should
always get the absolute URL in no matter what condition. The function is
RFC3986
compliant so be careful with your relative URL
construction. Here are the explanation examples:
EXAMPLE 1 - UNRELATED ABSOLUTE URL AS INPUT BASE URL : https://hestia.zoralab.com/default-path IN PAGE : https://hestia.zoralab.com/default-path/this-page/ INPUT : https://www.example.com/ OUTPUT : https://www.example.com/ EXAMPLE 2 - RELATIVE TO SITE AS INPUT BASE URL : https://hestia.zoralab.com/default-path/ IN PAGE : https://hestia.zoralab.com/default-path/this-page/ INPUT : /my-page OUTPUT : https://hestia.zoralab.com/default-path/my-page EXAMPLE 3 - RELATIVE TO PAGE (NOTE: NO LEADING FORWARD SLASH '/') BASE URL : https://hestia.zoralab.com/default-path/ IN PAGE : https://hestia.zoralab.com/default-path/this-page/ INPUT : my-page OUTPUT : https://hestia.zoralab.com/default-path/this-page/my-page
Create Page HTML Content
For hestiaHUGO, the corresponding file is specified in the
__page.toml
control file's Sources.HTML
field. The
default is the relative file __content.hestiaHTML
in the same
directory. Since we're beginner, we should use the default
__content.hestiaHTML
file. Let's open it and take a look. If
you're a seasoned Hugo developer, you will immediately notice that the Go
template (and Hugo's partial) functions are used instead of Hugo specific
Markdown and shortcodes. When using any ZORALab's Hestia product, we strive to
be as portable and nimble as possible across them with minimal learning cost. If
you're already familiar with Go template from Go Programming Language, then
every piece of your rendering knowledge is automatically and fully transferred
here. For this tutorial, let's update it with the following contents. Once done,
try visit the URL + /en/404/ web page presented by the Hugo server. You can
verify the HTML-only rendering of the page.
... {{- /* render outputs */ -}} <main> <section id='introduction' class='banner'> <h1>{{- .Titles.Page -}}</h1> <p>{{- .Descriptions.Page.Pitch }} {{ .Descriptions.Page.Summary -}}</p> {{- $ret := merge . (dict "Input" (dict "Data" "/en/")) -}} {{- $ret = partial "hestiaURL/Sanitize" $ret -}} <a class='button' href='{{- $ret -}}'>Back HOME</a> </section> </main>
Understand How hestiaHUGO Renders Page Data
Unlike Hugo requiring designer to guess a data field, hestiaHUGO employs its own
page data structure for designers to utilize. In fact, we have our some
design-adaptive debugger that shows the entire page data structure for debugging
or rendering purposes when Hugo is operating in server mode. Have you notice a
color button at the bottom right of the page? Try click on it and you can browse
your current page's entire usable datasets. Example, the rendering part of
{{- .Titles.Page -}}
was rendered as the value of
.Titles.Page
when viewed in the debugger console.
Understand hestiaHUGO Data Path
hestiaHUGO finalized its design by having content
directory
supplying the site URL and having each of its directory delivers the page data.
Remember the __i18n.toml
and __data.toml
in the page
directories? Those data files are listed in __page.toml
's
[[Data]]
array list. hestiaHUGO maintains absolute freedom for
page designer to construct the Page level data structure. After parsing and
merging all the data files, all the data can be accessed via
hestiaHUGO.Page
data field. Other config files are obviously
provide various different values for different data fields. Feel free to
explore around and check them via the on-screen debugger console. This is
how you source your data key:value
when designing your page.
The link below is the technical specification of the
hestiaHUGO.Page
data structure (browse when you're free, we
will move forward for now).
__data.toml + __i18n.toml + ... (NOTE: follows __page.toml data files list) ⤋ .Field.[...] ⤋ {{- .Field.[...] -}}
Understand How hestiaHUGO Empowers Hugo
hestiaHUGO supplies its own standard libraries just like other ZORALab's Hestia
components. Notice the use of hestiaURL.Sanitize
partial function
above? It converts a given ambigious URL into a proper full absolute URL
consistently in accoradance to hestiaHUGO URL management explained in
the 1st step. The sole purpose of preparing our own standard libraries
is to make sure we have absolute consistency as we grow ZORALab's Hestia
and not Hugo's output inconsitencies AND maintaining inter-operability
with other components. All ZORALab's Hestia libraries are documented in
the same context across all components in our specifications section.
You should explore all available hestiaHUGO API to advance your
development at your own time. For this tutorial, we will proceed further.
Create Page UI Components Styling List
Now that we verified the data shown in HTML-only page is correct, we can now
style it. hestiaHUGO uses the UI components approach to compile all necessary
proceed to edit /en/404/__components.toml
and add the following
components after the commented guide. Give the server a few moment and refresh
the web page. You can see it's being compiled with styling (especially the
call-to-action anchor link). Check out the CSS codes in the CSS.Inline section
of the debugger console. It's filled with the compiled CSS codes.
... [[List]] Name = "zoralabCORE" Include = true Variables = [ { "--body-scroll-behavior" = "smooth" }, ] [[List]] Name = "zoralabFONT_NOTOSANS" Include = true Variables = [] [[List]] Name = "zoralabANCHOR" Include = true Variables = [] [[List]] Name = "zoralabBUTTON" Include = true Variables = []
Understand How hestiaHUGO Manage Page Styling
Like Backbone, Angular, and React frameworks, hestiaHUGO componentized each UI but unlike them, hestiaHUGO only integrate each component's HTML, CSS, and JS codes as 1 set rather than split them and overloadingly manage everything via JavaScript. That way, via Hugo, hestiaHUGO can compile only the required CSS, CSS variables, and JavaScript codes into the assets and then embedded them into the HTML output file. This output HTML file is self-contained and not requiring external remote framework, fulfilling the vision where AMP project originally wants. It also seamlessly support PWA's offline feature as well and simplify the UI component designer maintenance workflow by only focusing on applying non-backward compatible updates introduced by W3C. 3 birds, 1 stone ⥤ definitely worth the effort.
UI Components CatalogUnderstand Why hestiaHUGO Containerized Page Styling
This is mainly for preventing a site-wide UI update from breaking pages like
a whack-a-mole nightmare from happening again especially large content website.
We tested it and find this compilation approach is the most optimized way. So,
to scale the same UI across other pages, you just have to copy-paste the
__components.toml
config file. For page designer regardless of
experiences, please feel safe and free to express your creativities and make
a safer mistake to gain experience with a site development.
Understand How hestiaHUGO UI Component Works
As stated earlier, the CSS codes are for defining the styling, the CSS variables
are for UI customziation, and the JS codes are for behavior control. When you
add an UI component, you are provided with an Include
switch for
design debugging purpose (better then delete large chunk of codes). At the
same time, you're allowed to overwrite existing CSS variables, making
hestiaHUGO to only generate 1 list of CSS variables for your HTML output
will do.
... [[List]] Name = "zoralabCORE" Include = true Variables = [ { "--body-scroll-behavior" = "smooth" }, # this overrides the default value 'none' ] ...
Understand Why ZORALab's Hestia Only Prioritize HTML & CSS
For 2 primary reasons:
Supporting privacy-first content rendering (JS disabled). In year 2022 during the Covid19 pandemic, everyone was concerned about privacy and data leak so having a complete JavaScript disabled use case is totally unsurprising. In that situation, your famous JS Frameworks and our WASM are completely unsable but the site is still expected present correctly; AND
ZORALab's Hestia intend to replace JavaScript entirely with WASM compiled using proper programming languages like Go or Nim in the future. It is a lot easier and seamless to port the HTML+CSS only UI component into the WASM counterpart (as in no JavaScript interference).
That being said, you can still use JavaScript (as shown in later steps). In ZORALab's Hestia, we don't do idiotic and autocratic goverance like some technology's governors did that restrict anyone freedom of use and artistic expression.
Understand ZORALab and JavaScript Relationship
Let's face it: JavaScript is the only programming language for web UI behavior packed with weird and inconsistencies. It's problematic weaknesses gave birth to various frameworks like Angular and Typescript of itself trying to workaround them but introduced their own. With the birth of WASM, ZORALab wants to solve the problem heads-on. We do not hate the language but finding development with it comes is very risky. A lot of outdated JS frameworks in the past trying to replace one another had already proven the point.
Understand hestiaHUGO Future
In order to realize our ultimate goal for web technologies, there are 3 specific use cases:
Discovery page like SEO & SMO
Single App - 1 WASM implements the entire site
Reactive Rendering (each page has its own WASM renderer)
hestiaHUGO fulfills primarily on use case: while facilitating WASM hosting for use cases (2) and (3). That's why we are still facilitating Hugo and so far it is still the best frontend static site generator (and now, a compiler).
Customize Page Styling with CSS
Now that the page is styled (that looks common across all users), you can
customize on top the currently compiled CSS codes. Simply edit the file
__content.hestiaCSS
and place your page-level CSS codes in it.
For this tutorial, we will be using the following CSS customization codes.
hestiaHUGO will recompile your CSS file as the last inline-type asset.
Once done, refresh the page and you'll observe your 404 page is
disco-ing with colors.
main { height: 100vh; width: 100vw; isplay: flex; justify-content: center; align-items: center; background: linear-gradient(245deg, #192fe3, #19e33b, #bbe319, #e35019, #e31919, #e319c1); background-size: 1200% 1200%; animation: BgDiscoFlasher 4s ease infinite; } @keyframes BgDiscoFlasher { 0%{background-position:0% 86%} 50%{background-position:100% 15%} 100%{background-position:0% 86%} } .banner { width: 50%; max-height: fit-content; padding: 5rem; border-radius: 2rem; display: flex; flex-direction: column; justify-content: center; align-items: center; background: rgba(255, 255, 255, .75); }
Customize Page with JavaScript
Likewise, you can also customize the page with JavaScript. The responsible file
is __content.hestiaJS
. While the page is no longer needing further
styling, for this education purpose, let's temporarily add the following code
block in and check out the browser' inspect console (F12 button). You should
observe a cat meowing. Same case: this JavaScript is the last inline JavaScript
to be included in the page.
window.onload = function() { console.log("\nMeow~~~~ ₍⌯ᴖⱅᴖ⌯ ^₎◞ ̑̑ෆ⃛ \n\n"); };
Update LD+JSON Data for SEO
hestiaHUGO has a built-in support for Schema.org complex data structuring of
your page. The responsible file is __content.hestiaLDJSON
. Since
this is a 404 page, we will add the following code block will do. Once the
Hugo server is fully updated, you can proceed to obtain the output from our
on-screen debugger console and validate at Schema.org validator site.
... {{- /* prepare variables for function */ -}} ... {{- /* execute function */ -}} {{- $dataList = merge $dataList (partial "hestiaJSON/schemaorgLDJSON/WebPage" .) -}} {{- /* render output */ -}} ...
Understand How hestiaHUGO Handles LD+JSON
To maintain balance between freedom of expression and rigidity for consistent output, there are 2 things to remember:
hestiaHUGO can only quickly help you process the base level dataset of known common data types (e.g. authors, page type, etc); and
you need to add in the page context-specific dataset (e.g. recipe steps, etc).
Stage the Current State
Now the HTML output is done deal, we should git stage it. However, we are not quite done yet. Proceed to next step:
HINT $ git add .
Create JSON Output
By default, hestiaHUGO supports JSON output type as secondary output format.
This is using the hestiaHUGO internal feature; not the Hugo one. Like LD+JSON,
you can construct a customer usable dataset using the Go template function.
Unlike LD+JSON, this is a pure JSON output (viewable by appending
index.json
at the end of the page URL) unrestricted by Schema.org
schematic. The responsible file defined by __page.toml
's
.Source.JSON
value (default is the relative
__content.hestiaJSON
). Since this is 404 page, we can leave
it as it is. You can study the default codes for educational purposes.
Understand Why hestiaHUGO Natively Supports JSON Output
5 main reasons:
Allows one to use hestiaHUGO as a CDN-driven open data API server; AND
A backup reason for using Hugo after search engine giants nearly destroyed SEO in the past solely for SMO ad revenues; AND
Provides alternatives and freedom compared to LD+JSON implementations; AND
making sure hestiaHUGO can support multiple output feature natively in a very consistent manner; AND
Facilitate a way to feed AI training data.
The default processor is configured in a way as an option for
those who do not want to use it so if you're not using it,
don't bother touching __content.hestiaJSON
file at all.
Commit and Push
At this point, we had completed designing a basic and simple 404 page. You can proceed to Git commit and push out.
HINT $ git add . $ git commit -s ---- ... write a good git message as shown in previous tutorial ... ---- $ git push
Remember the Strength of hestiaHUGO
If you haven't realize, hestiaHUGO only takes 1 set of input dataset and generated to various outputs type while supporting multiple languages at the same time. In fact, it generates more like page-level 'sitemap.xml' and 'sitemap-page.xml' as well. This is one of the problem we're trying to solve when using Hugo: 1 consistent input dataset to multiple outputs consistently. These are just a scratch of the surface. We will explore more as you go through the tutorials walkthrough.
What's Next?
Now that we had completed the hestiaHUGO setup, the next step is to make sure we support multilingual pages from the get go. Here's the URL for the next step:
Using Multilingual Pages from the Get GoEpilogue
Looks like we have arrived to the last station. Intrigued to get in touch? Please feel free to start contacting us via the following public channels:
GitHub Discussion Portal