├── README.adoc ├── archetypes └── default.md ├── config.toml ├── content └── post │ ├── article.adoc │ ├── creating-a-new-theme.adoc │ ├── go-is-for-lovers.adoc │ ├── hugo-is-for-lovers.md │ ├── migrate-from-jekyll.md │ └── welcome.adoc └── static ├── .gitkeep ├── css ├── ie8.css ├── images │ └── overlay.png └── main.css ├── images ├── avatar.jpg ├── bg.jpg ├── fulls │ ├── 01.jpg │ ├── 02.jpg │ ├── 03.jpg │ ├── 04.jpg │ ├── 05.jpg │ └── 06.jpg ├── screenshot-atom-editor-thumbnail.png ├── screenshot-atom-editor.png ├── screenshot-folders.png ├── screenshot-homepage.png ├── screenshot-server.png └── thumbs │ ├── 01.jpg │ ├── 02.jpg │ ├── 03.jpg │ ├── 04.jpg │ ├── 05.jpg │ └── 06.jpg └── js ├── ie ├── PIE.htc ├── backgroundsize.min.htc ├── html5shiv.js └── respond.min.js ├── jquery.min.js ├── jquery.poptrox.min.js ├── main.js ├── skel.min.js └── util.js /README.adoc: -------------------------------------------------------------------------------- 1 | 2 | :Author: Andy Thornton 3 | :Email: andy.thornton@redhat.com 4 | 5 | == Creating a blog using Asciidoc and Hugo 6 | This repo contains source materials to accompany the article on opensource.com for getting started with Hugo and asciidoc as a web development platform. 7 | 8 | [#img-homepage] 9 | .The server 10 | [link=https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-homepage.png] 11 | image::https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-homepage.png[Demo Website] 12 | 13 | ==== Installing Asciidoc and Asciidoctor. 14 | .Ubuntu 15 | Asciidoc is available in the default repos. 16 | [source,bash] 17 | ---- 18 | sudo apt-get install asciidoc asciidoctor -y 19 | ---- 20 | 21 | .Fedora 22 | Asciidoctor can be installed using the gem command. Asciidoc is installed through the standard repos. 23 | [source,bash] 24 | ---- 25 | yum install asciidoc 26 | gem install asciidoctor 27 | ---- 28 | 29 | For more detailed installation information, visit the following guides. 30 | 31 | .Installation Guides 32 | * http://asciidoc.org/INSTALL.html[Asciidoc]. 33 | * http://asciidoctor.org/docs/install-toolchain/[Asciidoctor]. 34 | 35 | ==== Installing Hugo 36 | The best guide for https://gohugo.io/getting-started/installing/[installing Hugo] is on their website. I found it was worth following this guide rather than use the package maintained in the Ubuntu repo as it was older and caused problems with modern themes. 37 | 38 | ==== How do I use these files? 39 | The repo contains a demo website with some sample articles in Asciidoc. The following folders are useful starting points. 40 | 41 | .Clone the repo 42 | [source,bash] 43 | ---- 44 | git clone git@github.com:opensourceway/asciidoc-blog.git 45 | ---- 46 | [#img-folders] 47 | .Folder Structure 48 | [link=https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-folders.png] 49 | image::https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-folders.png[Folders Overview] 50 | 51 | For more information, checkout the documentation on the https://gohugo.io/getting-started/directory-structure/[Hugo Homepage] 52 | 53 | .Starting the server 54 | From the root directory of the cloned repo: 55 | [source,bash] 56 | ---- 57 | hugo server --buildDrafts 58 | ---- 59 | 60 | This will run the server where you can see your website locally on http://localhost:1313[http://localhost:1313]. 61 | 62 | [#img-server] 63 | .The server 64 | [link=https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-server.png] 65 | image::https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-server.png[Server Window] 66 | 67 | To make changes to the setup, you can edit the config.toml file and set your website preferences up. The site contains initial setup parameters. 68 | 69 | Content is available under the folder content/post. There are some example articles available to get you started. 70 | 71 | == Working with Asciidoc 72 | My personal preference is to use http://www.vim.org/download.php[Vim] for working with http://asciidoc.org/[Asciidoc], 73 | there are a number of plugins which make working with Asciidoc easier as well as a http://www.vim.org/scripts/script.php?script_id=1832[syntax file] for highlighting your document. 74 | 75 | If you are looking for something more visual, I would recommend the https://atom.io/[Atom editor] from GitHub. 76 | It has plugins which provide a real-time preview of your work and makes it easier to work with GitHub. 77 | Using Hugo, Asciidoc and the Atom editor, you have a complete publishing system with real time previews and a local server to run validation against. 78 | 79 | [#img-atom] 80 | .Atom Editor, click for full screen 81 | [link=https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-atom-editor.png] 82 | image::https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-atom-editor-thumbnail.png[Atom Editor with preview plugin] 83 | 84 | == Where to go from here? 85 | You can tailor the site in the config.toml file to personalise your setup. There are a number of https://themes.gohugo.io/[themes] available to further customise your site. 86 | The language behind the more dynamic elements is very well implemented and there's excellent documentation on the Hugo website on how to get started working with https://gohugo.io/templates/[content and theming]. The theme used in this demo is the https://themes.gohugo.io/strata/[Strata Theme] by https://github.com/digitalcraftsman[Digitalcraftsman] which has detailed documentation on configuration options available on it's https://github.com/digitalcraftsman/hugo-strata-theme[github page]. 87 | 88 | == Thanks and credit due. 89 | 90 | Thanks to http://spf13.com[Steve Francia] for https://gohugo.io/[Hugo], for producing a fun platform to play with. 91 | The https://github.com/digitalcraftsman/hugo-strata-theme[Strata theme] port and the https://discourse.gohugo.io/[Hugo community]. 92 | 93 | Useful resources 94 | ++++++++++++++++ 95 | 96 | .Hugo 97 | * https://gohugo.io/[Hugo] 98 | - https://gohugo.io/getting-started/installing/[Installation] 99 | - https://gohugo.io/getting-started/quick-start/[Quick Start Guide] 100 | - https://github.com/gohugoio/hugo[Github Repo] 101 | - https://gohugo.io/tools/starter-kits/[Starter Kits] 102 | * https://themes.gohugo.io/[Hugo Themes] 103 | * https://discourse.gohugo.io/[Community] 104 | 105 | .Asciidoc 106 | * http://asciidoc.org/[Asciidoc] 107 | - http://asciidoc.org/#_overview_and_examples[Code Examples] 108 | - http://asciidoc.org/userguide.html[User Guide] 109 | - http://powerman.name/doc/asciidoc[Cheat Sheet] 110 | * http://asciidoctor.org/[Asciidoctor] 111 | 112 | .Editors and Frontends 113 | * https://atom.io/[Atom Editor] 114 | * Vim Plugins 115 | - http://www.vim.org/scripts/script.php?script_id=1832[Asciidoc Syntax] 116 | - http://www.vim.org/scripts/script.php?script_id=2882[Markdown Syntax] 117 | 118 | Demo and source materials 119 | +++++++++++++++++++++++++ 120 | * https://themes.gohugo.io/strata/[Strata Theme] 121 | * http://spf13.com/[Steve Francia's homepage] maintainer of Hugo 122 | -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | baseurl = "https://example.org/" 2 | languageCode = "en-us" 3 | title = "opensource.com" 4 | theme = "hugo-strata-theme" 5 | disqusShortname = "opensource.com" 6 | # Enable Google Analytics by inserting your tracking code 7 | googleAnalytics = "" 8 | # Define how many posts should appear on a site 9 | paginate = 10 10 | 11 | [params] 12 | # To provide some metadata for search engines feel free to add a few 13 | # information about you and your website. 14 | name = "Opensource.com" 15 | description = "Sample Website showing Hugo & Asciidoc" 16 | 17 | # Format dates with Go's time formatting 18 | date_format = "2006-01-02" 19 | 20 | # Add custom assets with their paths relative to the static folder 21 | custom_js = [] 22 | custom_css = [] 23 | 24 | 25 | [params.sidebar] 26 | # Replace the avatar with a picture of your own under static/images 27 | avatar = "avatar.jpg" 28 | # Use Markdown to format the string. This works nearly all over the theme 29 | bio = "**Welcome**, demo of a simple
responsive blog using Hugo and articles
written in Asciidoc." 30 | # The icons will be shown if you enter your username 31 | twitter = "opensourceway" 32 | github = "opensourceway/asciidoc-blog" 33 | gitlab = "" 34 | dribbble = "" 35 | facebook = "opensourceway" 36 | googleplus = "" 37 | flickr = "" 38 | linkedin = "" 39 | 40 | copyright = [ 41 | "© John Doe", 42 | "Design: [HTML5 UP](//html5up.net)", 43 | "Demo Images: [Unsplash](//unsplash.com/)" 44 | ] 45 | 46 | 47 | [params.about] 48 | hide = false 49 | title = "Ipsum lorem dolor aliquam ante commodo magna sed accumsan arcu neque." 50 | content = "Accumsan orci faucibus id eu lorem semper. Eu ac iaculis ac nunc nisi lorem vulputate lorem neque cubilia ac in adipiscing in curae lobortis tortor primis integer massa adipiscing id nisi accumsan pellentesque commodo blandit enim arcu non at amet id arcu magna. Accumsan orci faucibus id eu lorem semper nunc nisi lorem vulputate lorem neque cubilia." 51 | 52 | 53 | [params.portfolio] 54 | hide = false 55 | title = "Recent Work" 56 | 57 | # The images and thumbnails are stored under static/images 58 | # Create and change subfolders as you like 59 | [[params.portfolio.gallery]] 60 | image = "fulls/01.jpg" 61 | thumb = "thumbs/01.jpg" 62 | title = "Lorem ipsum dolor." 63 | description = "Lorem ipsum dolor sit amet." 64 | 65 | [[params.portfolio.gallery]] 66 | image = "fulls/02.jpg" 67 | thumb = "thumbs/02.jpg" 68 | title = "Lorem ipsum dolor." 69 | description = "Lorem ipsum dolor sit amet." 70 | 71 | [[params.portfolio.gallery]] 72 | image = "fulls/03.jpg" 73 | thumb = "thumbs/03.jpg" 74 | title = "Lorem ipsum dolor." 75 | description = "Lorem ipsum dolor sit amet." 76 | 77 | [[params.portfolio.gallery]] 78 | image = "fulls/04.jpg" 79 | thumb = "thumbs/04.jpg" 80 | title = "Lorem ipsum dolor." 81 | description = "Lorem ipsum dolor sit amet." 82 | 83 | [[params.portfolio.gallery]] 84 | image = "fulls/05.jpg" 85 | thumb = "thumbs/05.jpg" 86 | title = "Lorem ipsum dolor." 87 | description = "Lorem ipsum dolor sit amet." 88 | 89 | [[params.portfolio.gallery]] 90 | image = "fulls/06.jpg" 91 | thumb = "thumbs/06.jpg" 92 | title = "Lorem ipsum dolor." 93 | description = "Lorem ipsum dolor sit amet." 94 | 95 | [params.recentposts] 96 | hide = false 97 | title = "Recent blog posts" 98 | 99 | [params.contact] 100 | hide = false 101 | title = "Get In Touch" 102 | content = "Accumsan pellentesque commodo blandit enim arcu non at amet id arcu magna. Accumsan orci faucibus id eu lorem semper nunc nisi lorem vulputate lorem neque lorem ipsum dolor." 103 | 104 | address = [ 105 | "1234 Somewhere Rd.", 106 | "Nashville, TN 00000", 107 | "United States" 108 | ] 109 | phone = "000-000-0000" 110 | 111 | # Since this template is static, the contact form uses www.formspree.io as a 112 | # proxy. The form makes a POST request to their servers to send the actual 113 | # email. Visitors can send up to a 1000 emails each month for free. 114 | # 115 | # What you need to do for the setup? 116 | # 117 | # - set your email address under 'email' below 118 | # - upload the generated site to your server 119 | # - send a dummy email yourself to confirm your account 120 | # - click the confirm link in the email from www.formspree.io 121 | # - you're done. Happy mailing! 122 | email = "hello@example.com" 123 | 124 | [params.contact.form] 125 | # Set custom strings for the form if your native 126 | # language isn't English 127 | name = "Name" 128 | email = "Email" 129 | message = "Message" 130 | submit = "Send message" 131 | 132 | 133 | # Menu links that appear on the left sidebar 134 | [[menu.main]] 135 | name = "Home" 136 | url = "/" 137 | weight = 0 138 | 139 | [[menu.main]] 140 | name = "Blog" 141 | url = "post/" 142 | weight = 10 143 | -------------------------------------------------------------------------------- /content/post/article.adoc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using Asciidoc for Web Development" 3 | date: 2017-07-28T15:06:07-04:00 4 | draft: false 5 | categories: ["Lorem"] 6 | --- 7 | 8 | = A different kind of development platform 9 | 10 | During the day, I work with content management tools and support documentation writers who's preferred language of choice is Asciidoc. 11 | It has a simple syntax, but enough features to keep even a hard core documentation nerd happy. With Asciidoc, you can write documentation in a more 12 | natural way and mark it up cleanly for presentation on the web or as a PDF. This got me thinking, "Wouldn't it be handy to be able 13 | to maintain a website purely with Asciidoc?" 14 | 15 | Some quick Googling and chatting with colleagues and I was introduced to https://gohugo.io/[Hugo] which is a publishing platform 16 | which can transform articles written in MarkDown or Asciidoc into usable content for the web. 17 | The platform has a rich language for working with templates and theming. As well as organising content and can be used to build a 18 | blog with enough functionality to keep me happy, but without the need for a database. 19 | The pages are rendered HTML so the site is blazingly fast and very easy to maintain. It even comes with it's own 20 | server so I can test my site while I work on it. 21 | 22 | The lack of a database or the need for a language such as PHP makes it especially handy if you're working on a site relating to 23 | security by reducing the risk of SQL injection. It also means the website is much faster than a traditional blog platform. 24 | As long as your server can deliver HTML, you're good to go. Combining this with a CDN and you have a very fast website. 25 | 26 | Hugo also supports tasks which are normally driven by your blogging platform, such as RSS feeds which can be generated 27 | automatically when a new article is added. You can maintain articles in a "draft" state which will show up on your local machine, but 28 | won't be published until you mark them as ready for the world. Combining this with a Git branching strategy means multiple authors can 29 | work on articles and book them back into your main branch when ready to publish. Everyone can run a copy of the site locally 30 | while they work on their articles. Other interactive elements such as comments, can be included using disqus. Hugo is a very feature rich 31 | platform and a lot of fun to work with. 32 | 33 | When I work on a blog, I approach it with the idea of "Content First" and try not to get tied up with working on the platform. 34 | Which is a fine idea, but the reality is that I find myself constantly tweaking the site. Then I tweak it a little more, 35 | then a weekend is gone and I haven't written anything! I ended up just playing with the theme or working on back end services. 36 | Hugo has a decent template system and I can do a lot more with a lot less code. Because my articles are written in Asciidoc, 37 | I can focus on content rather than presentation. Asciidoc helps me write a document with a nice structure and through the use of Asciidoctor, I can 38 | convert the pages into other formats. Such as PDF or Linux manpages. so I can preview them locally as HTML. 39 | 40 | Asciidoctor is a digital swiss army knife for Asciidoc. Hugo uses Asciidoctor to convert the documents as you write them. 41 | It also helps me identify places my content needs work. Running Hugo in a console, I can see issues with my document whenever I save it. 42 | So I can fix them and move on. Which is different to my usual routine .. 43 | 44 | [quote, Me at 3am on very little sleep and too much coffee'] 45 | ____ 46 | My blog post is done! and now to send my masterpiece to the world! .... 47 | wait a minute, why is all my text a H1...... I hate myself. 48 | ____ 49 | 50 | == Documentation workflow 51 | I normally write my first drafts in plain English, to get everything started. I use a new branch in git for each article 52 | which keeps things nice and simple until I am ready to publish. Once I have that done and given it a couple of passes to make sure 53 | everything flows well, I add asciidoc markup so Hugo can format the article as clean HTML. When the article is ready to publish, 54 | I merge it back into my master branch. 55 | 56 | If I need to add the same text repeatedly, I use an include to contain boilerplate text as reusable content. 57 | These can be setup in my template or I can define content types which automatically add them depending on the type of page I am working on. 58 | I can include a standard license statement or a paragraph about getting support if I am writing a techinical article. It's also handy if 59 | This is handy if you are writing a document with standard sections, such as a company description, or an installation guide. You can insert 60 | them into your document making it more modular and easier to maintain. 61 | 62 | You can also define metadata which can later be used by your theme to help organise content. Tagging articles and grouping content as an example. Handy if you 63 | want to define a page as a "solution" or a "FAQ". The template language provides a feature rich system for grouping and working with content. This is especially 64 | handy with Asciidoc as the header of a document will have standard metadata section which may be different between an article and a blog post. I can define them 65 | within Hugo and it does the work for me when I create a new piece of content. 66 | 67 | == Working with Asciidoc 68 | My default editor of choice is Vim, which has syntax files available for Asciidoc. If you are looking for a more visual approach to working with 69 | content, I would recommend the Atom editor with an asciidoc preview plugin which makes working with Asciidoc very easy. It helps check your document as well as provide 70 | a real-time preview of your page. As the editor was created by GitHub, it has built in support for working with Git, so working on documents across different 71 | branches becomes straight forward. 72 | 73 | [#img-atom] 74 | .Atom Editor, click for full screen 75 | [link=https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-atom-editor.png] 76 | image::https://raw.githubusercontent.com/opensourceway/asciidoc-blog/master/static/images/screenshot-atom-editor-thumbnail.png[Atom Editor with preview plugin] 77 | 78 | Overall, I am very happy with Hugo and Asciidoc. My process becomes more "content focused". I have a great work flow with git and the performance on the site is 79 | noticeable when compared to a traditional php / mysql CMS. 80 | 81 | == How can I play with this setup? 82 | If you are interested in getting started with Hugo and Asciidoc, I put together a demo website with content and a theme along with notes on how to get up and running. 83 | It is available from the https://github.com/opensourceway/asciidoc-blog[Opensourceway's Github] page. Rather than filling this article with step by step instructions 84 | on how to download and configure Hugo and how to write with Asciidoc. I have put notes into the website along with links to resources on-line to help get you started. 85 | 86 | Have fun with Asciidoc and Hugo, post links in the comments to any projects you produce with Hugo. 87 | -------------------------------------------------------------------------------- /content/post/creating-a-new-theme.adoc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Creating a theme" 3 | date: 2017-07-26T14:31:37-04:00 4 | draft: false 5 | categories: ["Lorem"] 6 | date: "2016-08-03T13:39:46+02:00" 7 | --- 8 | [[introduction]] 9 | Introduction 10 | ~~~~~~~~~~~~ 11 | 12 | This tutorial will show you how to create a simple theme in Hugo. I 13 | assume that you are familiar with HTML, the bash command line, and that 14 | you are comfortable using Markdown to format content. I'll explain how 15 | Hugo uses templates and how you can organize your templates to create a 16 | theme. I won't cover using CSS to style your theme. 17 | 18 | We'll start with creating a new site with a very basic template. Then 19 | we'll add in a few pages and posts. With small variations on that, you 20 | will be able to create many different types of web sites. 21 | 22 | In this tutorial, commands that you enter will start with the "$" 23 | prompt. The output will follow. Lines that start with "#" are comments 24 | that I've added to explain a point. When I show updates to a file, the 25 | ":wq" on the last line means to save the file. 26 | 27 | Here's an example: 28 | 29 | .... 30 | ## this is a comment 31 | $ echo this is a command 32 | this is a command 33 | 34 | ## edit the file 35 | $vi foo.md 36 | +++ 37 | date = "2014-09-28" 38 | title = "creating a new theme" 39 | +++ 40 | 41 | bah and humbug 42 | :wq 43 | 44 | ## show it 45 | $ cat foo.md 46 | +++ 47 | date = "2014-09-28" 48 | title = "creating a new theme" 49 | +++ 50 | 51 | bah and humbug 52 | $ 53 | .... 54 | 55 | [[some-definitions]] 56 | Some Definitions 57 | ~~~~~~~~~~~~~~~~ 58 | 59 | There are a few concepts that you need to understand before creating a 60 | theme. 61 | 62 | [[skins]] 63 | Skins 64 | ^^^^^ 65 | 66 | Skins are the files responsible for the look and feel of your site. It’s 67 | the CSS that controls colors and fonts, it’s the Javascript that 68 | determines actions and reactions. It’s also the rules that Hugo uses to 69 | transform your content into the HTML that the site will serve to 70 | visitors. 71 | 72 | You have two ways to create a skin. The simplest way is to create it in 73 | the `layouts/` directory. If you do, then you don’t have to worry about 74 | configuring Hugo to recognize it. The first place that Hugo will look 75 | for rules and files is in the `layouts/` directory so it will always 76 | find the skin. 77 | 78 | Your second choice is to create it in a sub-directory of the `themes/` 79 | directory. If you do, then you must always tell Hugo where to search for 80 | the skin. It’s extra work, though, so why bother with it? 81 | 82 | The difference between creating a skin in `layouts/` and creating it in 83 | `themes/` is very subtle. A skin in `layouts/` can’t be customized 84 | without updating the templates and static files that it is built from. A 85 | skin created in `themes/`, on the other hand, can be and that makes it 86 | easier for other people to use it. 87 | 88 | The rest of this tutorial will call a skin created in the `themes/` 89 | directory a theme. 90 | 91 | Note that you can use this tutorial to create a skin in the `layouts/` 92 | directory if you wish to. The main difference will be that you won’t 93 | need to update the site’s configuration file to use a theme. 94 | 95 | [[the-home-page]] 96 | The Home Page 97 | ^^^^^^^^^^^^^ 98 | 99 | The home page, or landing page, is the first page that many visitors to 100 | a site see. It is the index.html file in the root directory of the web 101 | site. Since Hugo writes files to the public/ directory, our home page is 102 | public/index.html. 103 | 104 | [[site-configuration-file]] 105 | Site Configuration File 106 | ^^^^^^^^^^^^^^^^^^^^^^^ 107 | 108 | When Hugo runs, it looks for a configuration file that contains settings 109 | that override default values for the entire site. The file can use TOML, 110 | YAML, or JSON. I prefer to use TOML for my configuration files. If you 111 | prefer to use JSON or YAML, you’ll need to translate my examples. You’ll 112 | also need to change the name of the file since Hugo uses the extension 113 | to determine how to process it. 114 | 115 | Hugo translates Markdown files into HTML. By default, Hugo expects to 116 | find Markdown files in your `content/` directory and template files in 117 | your `themes/` directory. It will create HTML files in your `public/` 118 | directory. You can change this by specifying alternate locations in the 119 | configuration file. 120 | 121 | [[content]] 122 | Content 123 | ^^^^^^^ 124 | 125 | Content is stored in text files that contain two sections. The first 126 | section is the “front matter,” which is the meta-information on the 127 | content. The second section contains Markdown that will be converted to 128 | HTML. 129 | 130 | [[front-matter]] 131 | Front Matter 132 | ++++++++++++ 133 | 134 | The front matter is information about the content. Like the 135 | configuration file, it can be written in TOML, YAML, or JSON. Unlike the 136 | configuration file, Hugo doesn’t use the file’s extension to know the 137 | format. It looks for markers to signal the type. TOML is surrounded by 138 | “`+++`”, YAML by “`---`”, and JSON is enclosed in curly braces. I prefer 139 | to use TOML, so you’ll need to translate my examples if you prefer YAML 140 | or JSON. 141 | 142 | The information in the front matter is passed into the template before 143 | the content is rendered into HTML. 144 | 145 | [[markdown]] 146 | Markdown 147 | ++++++++ 148 | 149 | Content is written in Markdown which makes it easier to create the 150 | content. Hugo runs the content through a Markdown engine to create the 151 | HTML which will be written to the output file. 152 | 153 | [[template-files]] 154 | Template Files 155 | ^^^^^^^^^^^^^^ 156 | 157 | Hugo uses template files to render content into HTML. Template files are 158 | a bridge between the content and presentation. Rules in the template 159 | define what content is published, where it's published to, and how it 160 | will rendered to the HTML file. The template guides the presentation by 161 | specifying the style to use. 162 | 163 | There are three types of templates: single, list, and partial. Each type 164 | takes a bit of content as input and transforms it based on the commands 165 | in the template. 166 | 167 | Hugo uses its knowledge of the content to find the template file used to 168 | render the content. If it can’t find a template that is an exact match 169 | for the content, it will shift up a level and search from there. It will 170 | continue to do so until it finds a matching template or runs out of 171 | templates to try. If it can’t find a template, it will use the default 172 | template for the site. 173 | 174 | Please note that you can use the front matter to influence Hugo’s choice 175 | of templates. 176 | 177 | [[single-template]] 178 | Single Template 179 | +++++++++++++++ 180 | 181 | A single template is used to render a single piece of content. For 182 | example, an article or post would be a single piece of content and use a 183 | single template. 184 | 185 | [[list-template]] 186 | List Template 187 | +++++++++++++ 188 | 189 | A list template renders a group of related content. That could be a 190 | summary of recent postings or all articles in a category. List templates 191 | can contain multiple groups. 192 | 193 | The homepage template is a special type of list template. Hugo assumes 194 | that the home page of your site will act as the portal for the rest of 195 | the content in the site. 196 | 197 | [[partial-template]] 198 | Partial Template 199 | ++++++++++++++++ 200 | 201 | A partial template is a template that can be included in other 202 | templates. Partial templates must be called using the “partial” template 203 | command. They are very handy for rolling up common behavior. For 204 | example, your site may have a banner that all pages use. Instead of 205 | copying the text of the banner into every single and list template, you 206 | could create a partial with the banner in it. That way if you decide to 207 | change the banner, you only have to change the partial template. 208 | 209 | [[create-a-new-site]] 210 | Create a New Site 211 | ~~~~~~~~~~~~~~~~~ 212 | 213 | Let's use Hugo to create a new web site. I'm a Mac user, so I'll create 214 | mine in my home directory, in the Sites folder. If you're using Linux, 215 | you might have to create the folder first. 216 | 217 | The "new site" command will create a skeleton of a site. It will give 218 | you the basic directory structure and a useable configuration file. 219 | 220 | .... 221 | $ hugo new site ~/Sites/zafta 222 | $ cd ~/Sites/zafta 223 | $ ls -l 224 | total 8 225 | drwxr-xr-x 7 quoha staff 238 Sep 29 16:49 . 226 | drwxr-xr-x 3 quoha staff 102 Sep 29 16:49 .. 227 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes 228 | -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml 229 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content 230 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts 231 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static 232 | $ 233 | .... 234 | 235 | Take a look in the content/ directory to confirm that it is empty. 236 | 237 | The other directories (archetypes/, layouts/, and static/) are used when 238 | customizing a theme. That's a topic for a different tutorial, so please 239 | ignore them for now. 240 | 241 | [[generate-the-html-for-the-new-site]] 242 | Generate the HTML For the New Site 243 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 244 | 245 | Running the `hugo` command with no options will read all the available 246 | content and generate the HTML files. It will also copy all static files 247 | (that's everything that's not content). Since we have an empty site, it 248 | won't do much, but it will do it very quickly. 249 | 250 | .... 251 | $ hugo --verbose 252 | INFO: 2014/09/29 Using config file: config.toml 253 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 254 | WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] 255 | WARN: 2014/09/29 Unable to locate layout: [404.html] 256 | 0 draft content 257 | 0 future content 258 | 0 pages created 259 | 0 tags created 260 | 0 categories created 261 | in 2 ms 262 | $ 263 | .... 264 | 265 | The "`--verbose`" flag gives extra information that will be helpful when 266 | we build the template. Every line of the output that starts with "INFO:" 267 | or "WARN:" is present because we used that flag. The lines that start 268 | with "WARN:" are warning messages. We'll go over them later. 269 | 270 | We can verify that the command worked by looking at the directory again. 271 | 272 | .... 273 | $ ls -l 274 | total 8 275 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes 276 | -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml 277 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content 278 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts 279 | drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public 280 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static 281 | $ 282 | .... 283 | 284 | See that new public/ directory? Hugo placed all generated content there. 285 | When you're ready to publish your web site, that's the place to start. 286 | For now, though, let's just confirm that we have what we'd expect from a 287 | site with no content. 288 | 289 | .... 290 | $ ls -l public 291 | total 16 292 | -rw-r--r-- 1 quoha staff 416 Sep 29 17:02 index.xml 293 | -rw-r--r-- 1 quoha staff 262 Sep 29 17:02 sitemap.xml 294 | $ 295 | .... 296 | 297 | Hugo created two XML files, which is standard, but there are no HTML 298 | files. 299 | 300 | [[test-the-new-site]] 301 | Test the New Site 302 | ^^^^^^^^^^^^^^^^^ 303 | 304 | Verify that you can run the built-in web server. It will dramatically 305 | shorten your development cycle if you do. Start it by running the 306 | "server" command. If it is successful, you will see output similar to 307 | the following: 308 | 309 | .... 310 | $ hugo server --verbose 311 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 312 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 313 | WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] 314 | WARN: 2014/09/29 Unable to locate layout: [404.html] 315 | 0 draft content 316 | 0 future content 317 | 0 pages created 318 | 0 tags created 319 | 0 categories created 320 | in 2 ms 321 | Serving pages from /Users/quoha/Sites/zafta/public 322 | Web Server is available at http://localhost:1313 323 | Press Ctrl+C to stop 324 | .... 325 | 326 | Connect to the listed URL (it's on the line that starts with "Web 327 | Server"). If everything is working correctly, you should get a page that 328 | shows the following: 329 | 330 | .... 331 | index.xml 332 | sitemap.xml 333 | .... 334 | 335 | That's a listing of your public/ directory. Hugo didn't create a home 336 | page because our site has no content. When there's no index.html file in 337 | a directory, the server lists the files in the directory, which is what 338 | you should see in your browser. 339 | 340 | Let’s go back and look at those warnings again. 341 | 342 | .... 343 | WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] 344 | WARN: 2014/09/29 Unable to locate layout: [404.html] 345 | .... 346 | 347 | That second warning is easier to explain. We haven’t created a template 348 | to be used to generate “page not found errors.” The 404 message is a 349 | topic for a separate tutorial. 350 | 351 | Now for the first warning. It is for the home page. You can tell because 352 | the first layout that it looked for was “index.html.” That’s only used 353 | by the home page. 354 | 355 | I like that the verbose flag causes Hugo to list the files that it's 356 | searching for. For the home page, they are index.html, 357 | _default/list.html, and _default/single.html. There are some rules that 358 | we'll cover later that explain the names and paths. For now, just 359 | remember that Hugo couldn't find a template for the home page and it 360 | told you so. 361 | 362 | At this point, you've got a working installation and site that we can 363 | build upon. All that’s left is to add some content and a theme to 364 | display it. 365 | 366 | [[create-a-new-theme]] 367 | Create a New Theme 368 | ~~~~~~~~~~~~~~~~~~ 369 | 370 | Hugo doesn't ship with a default theme. There are a few available (I 371 | counted a dozen when I first installed Hugo) and Hugo comes with a 372 | command to create new themes. 373 | 374 | We're going to create a new theme called "zafta." Since the goal of this 375 | tutorial is to show you how to fill out the files to pull in your 376 | content, the theme will not contain any CSS. In other words, ugly but 377 | functional. 378 | 379 | All themes have opinions on content and layout. For example, Zafta uses 380 | "post" over "blog". Strong opinions make for simpler templates but 381 | differing opinions make it tougher to use themes. When you build a 382 | theme, consider using the terms that other themes do. 383 | 384 | [[create-a-skeleton]] 385 | Create a Skeleton 386 | ^^^^^^^^^^^^^^^^^ 387 | 388 | Use the hugo "new" command to create the skeleton of a theme. This 389 | creates the directory structure and places empty files for you to fill 390 | out. 391 | 392 | .... 393 | $ hugo new theme zafta 394 | 395 | $ ls -l 396 | total 8 397 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes 398 | -rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml 399 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content 400 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts 401 | drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public 402 | drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static 403 | drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes 404 | 405 | $ find themes -type f | xargs ls -l 406 | -rw-r--r-- 1 quoha staff 1081 Sep 29 17:31 themes/zafta/LICENSE.md 407 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/archetypes/default.md 408 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html 409 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html 410 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html 411 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html 412 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html 413 | -rw-r--r-- 1 quoha staff 93 Sep 29 17:31 themes/zafta/theme.toml 414 | $ 415 | .... 416 | 417 | The skeleton includes templates (the files ending in .html), license 418 | file, a description of your theme (the theme.toml file), and an empty 419 | archetype. 420 | 421 | Please take a minute to fill out the theme.toml and LICENSE.md files. 422 | They're optional, but if you're going to be distributing your theme, it 423 | tells the world who to praise (or blame). It's also nice to declare the 424 | license so that people will know how they can use the theme. 425 | 426 | .... 427 | $ vi themes/zafta/theme.toml 428 | author = "michael d henderson" 429 | description = "a minimal working template" 430 | license = "MIT" 431 | name = "zafta" 432 | source_repo = "" 433 | tags = ["tags", "categories"] 434 | :wq 435 | 436 | ## also edit themes/zafta/LICENSE.md and change 437 | ## the bit that says "YOUR_NAME_HERE" 438 | .... 439 | 440 | Note that the the skeleton's template files are empty. Don't worry, 441 | we'll be changing that shortly. 442 | 443 | .... 444 | $ find themes/zafta -name '*.html' | xargs ls -l 445 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html 446 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html 447 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html 448 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html 449 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html 450 | $ 451 | .... 452 | 453 | [[update-the-configuration-file-to-use-the-theme]] 454 | Update the Configuration File to Use the Theme 455 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 456 | 457 | Now that we've got a theme to work with, it's a good idea to add the 458 | theme name to the configuration file. This is optional, because you can 459 | always add "-t zafta" on all your commands. I like to put it the 460 | configuration file because I like shorter command lines. If you don't 461 | put it in the configuration file or specify it on the command line, you 462 | won't use the template that you're expecting to. 463 | 464 | Edit the file to add the theme, add a title for the site, and specify 465 | that all of our content will use the TOML format. 466 | 467 | .... 468 | $ vi config.toml 469 | theme = "zafta" 470 | baseurl = "" 471 | languageCode = "en-us" 472 | title = "zafta - totally refreshing" 473 | MetaDataFormat = "toml" 474 | :wq 475 | 476 | $ 477 | .... 478 | 479 | [[generate-the-site]] 480 | Generate the Site 481 | ^^^^^^^^^^^^^^^^^ 482 | 483 | Now that we have an empty theme, let's generate the site again. 484 | 485 | .... 486 | $ hugo --verbose 487 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 488 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 489 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 490 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 491 | 0 draft content 492 | 0 future content 493 | 0 pages created 494 | 0 tags created 495 | 0 categories created 496 | in 2 ms 497 | $ 498 | .... 499 | 500 | Did you notice that the output is different? The warning message for the 501 | home page has disappeared and we have an additional information line 502 | saying that Hugo is syncing from the theme's directory. 503 | 504 | Let's check the public/ directory to see what Hugo's created. 505 | 506 | .... 507 | $ ls -l public 508 | total 16 509 | drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 css 510 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:56 index.html 511 | -rw-r--r-- 1 quoha staff 407 Sep 29 17:56 index.xml 512 | drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 js 513 | -rw-r--r-- 1 quoha staff 243 Sep 29 17:56 sitemap.xml 514 | $ 515 | .... 516 | 517 | Notice four things: 518 | 519 | 1. Hugo created a home page. This is the file public/index.html. 520 | 2. Hugo created a css/ directory. 521 | 3. Hugo created a js/ directory. 522 | 4. Hugo claimed that it created 0 pages. It created a file and copied 523 | over static files, but didn't create any pages. That's because it 524 | considers a "page" to be a file created directly from a content file. It 525 | doesn't count things like the index.html files that it creates 526 | automatically. 527 | 528 | [[the-home-page-1]] 529 | The Home Page 530 | +++++++++++++ 531 | 532 | Hugo supports many different types of templates. The home page is 533 | special because it gets its own type of template and its own template 534 | file. The file, layouts/index.html, is used to generate the HTML for the 535 | home page. The Hugo documentation says that this is the only required 536 | template, but that depends. Hugo's warning message shows that it looks 537 | for three different templates: 538 | 539 | .... 540 | WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] 541 | .... 542 | 543 | If it can't find any of these, it completely skips creating the home 544 | page. We noticed that when we built the site without having a theme 545 | installed. 546 | 547 | When Hugo created our theme, it created an empty home page template. 548 | Now, when we build the site, Hugo finds the template and uses it to 549 | generate the HTML for the home page. Since the template file is empty, 550 | the HTML file is empty, too. If the template had any rules in it, then 551 | Hugo would have used them to generate the home page. 552 | 553 | .... 554 | $ find . -name index.html | xargs ls -l 555 | -rw-r--r-- 1 quoha staff 0 Sep 29 20:21 ./public/index.html 556 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 ./themes/zafta/layouts/index.html 557 | $ 558 | .... 559 | 560 | [[the-magic-of-static]] 561 | The Magic of Static 562 | +++++++++++++++++++ 563 | 564 | Hugo does two things when generating the site. It uses templates to 565 | transform content into HTML and it copies static files into the site. 566 | Unlike content, static files are not transformed. They are copied 567 | exactly as they are. 568 | 569 | Hugo assumes that your site will use both CSS and JavaScript, so it 570 | creates directories in your theme to hold them. Remember opinions? Well, 571 | Hugo's opinion is that you'll store your CSS in a directory named css/ 572 | and your JavaScript in a directory named js/. If you don't like that, 573 | you can change the directory names in your theme directory or even 574 | delete them completely. Hugo's nice enough to offer its opinion, then 575 | behave nicely if you disagree. 576 | 577 | .... 578 | $ find themes/zafta -type d | xargs ls -ld 579 | drwxr-xr-x 7 quoha staff 238 Sep 29 17:38 themes/zafta 580 | drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes/zafta/archetypes 581 | drwxr-xr-x 5 quoha staff 170 Sep 29 17:31 themes/zafta/layouts 582 | drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/_default 583 | drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/partials 584 | drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/static 585 | drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/css 586 | drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/js 587 | $ 588 | .... 589 | 590 | [[the-theme-development-cycle]] 591 | The Theme Development Cycle 592 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 593 | 594 | When you're working on a theme, you will make changes in the theme's 595 | directory, rebuild the site, and check your changes in the browser. Hugo 596 | makes this very easy: 597 | 598 | 1. Purge the public/ directory. 599 | 2. Run the built in web server in watch mode. 600 | 3. Open your site in a browser. 601 | 4. Update the theme. 602 | 5. Glance at your browser window to see changes. 603 | 6. Return to step 4. 604 | 605 | I’ll throw in one more opinion: never work on a theme on a live site. 606 | Always work on a copy of your site. Make changes to your theme, test 607 | them, then copy them up to your site. For added safety, use a tool like 608 | Git to keep a revision history of your content and your theme. Believe 609 | me when I say that it is too easy to lose both your mind and your 610 | changes. 611 | 612 | Check the main Hugo site for information on using Git with Hugo. 613 | 614 | [[purge-the-public-directory]] 615 | Purge the public/ Directory 616 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 617 | 618 | When generating the site, Hugo will create new files and update existing 619 | ones in the `public/` directory. It will not delete files that are no 620 | longer used. For example, files that were created in the wrong directory 621 | or with the wrong title will remain. If you leave them, you might get 622 | confused by them later. I recommend cleaning out your site prior to 623 | generating it. 624 | 625 | Note: If you're building on an SSD, you should ignore this. Churning on 626 | a SSD can be costly. 627 | 628 | [[hugos-watch-option]] 629 | Hugo's Watch Option 630 | ^^^^^^^^^^^^^^^^^^^ 631 | 632 | Hugo's "`--watch`" option will monitor the content/ and your theme 633 | directories for changes and rebuild the site automatically. 634 | 635 | [[live-reload]] 636 | Live Reload 637 | ^^^^^^^^^^^ 638 | 639 | Hugo's built in web server supports live reload. As pages are saved on 640 | the server, the browser is told to refresh the page. Usually, this 641 | happens faster than you can say, "Wow, that's totally amazing." 642 | 643 | [[development-commands]] 644 | Development Commands 645 | ^^^^^^^^^^^^^^^^^^^^ 646 | 647 | Use the following commands as the basis for your workflow. 648 | 649 | .... 650 | ## purge old files. hugo will recreate the public directory. 651 | ## 652 | $ rm -rf public 653 | ## 654 | ## run hugo in watch mode 655 | ## 656 | $ hugo server --watch --verbose 657 | .... 658 | 659 | Here's sample output showing Hugo detecting a change to the template for 660 | the home page. Once generated, the web browser automatically reloaded 661 | the page. I've said this before, it's amazing. 662 | 663 | .... 664 | $ rm -rf public 665 | $ hugo server --watch --verbose 666 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 667 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 668 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 669 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 670 | 0 draft content 671 | 0 future content 672 | 0 pages created 673 | 0 tags created 674 | 0 categories created 675 | in 2 ms 676 | Watching for changes in /Users/quoha/Sites/zafta/content 677 | Serving pages from /Users/quoha/Sites/zafta/public 678 | Web Server is available at http://localhost:1313 679 | Press Ctrl+C to stop 680 | INFO: 2014/09/29 File System Event: ["/Users/quoha/Sites/zafta/themes/zafta/layouts/index.html": MODIFY|ATTRIB] 681 | Change detected, rebuilding site 682 | 683 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 684 | 0 draft content 685 | 0 future content 686 | 0 pages created 687 | 0 tags created 688 | 0 categories created 689 | in 1 ms 690 | .... 691 | 692 | [[update-the-home-page-template]] 693 | Update the Home Page Template 694 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 695 | 696 | The home page is one of a few special pages that Hugo creates 697 | automatically. As mentioned earlier, it looks for one of three files in 698 | the theme's layout/ directory: 699 | 700 | 1. index.html 701 | 2. _default/list.html 702 | 3. _default/single.html 703 | 704 | We could update one of the default templates, but a good design decision 705 | is to update the most specific template available. That's not a hard and 706 | fast rule (in fact, we'll break it a few times in this tutorial), but it 707 | is a good generalization. 708 | 709 | [[make-a-static-home-page]] 710 | Make a Static Home Page 711 | ^^^^^^^^^^^^^^^^^^^^^^^ 712 | 713 | Right now, that page is empty because we don't have any content and we 714 | don't have any logic in the template. Let's change that by adding some 715 | text to the template. 716 | 717 | .... 718 | $ vi themes/zafta/layouts/index.html 719 | 720 | 721 | 722 |

hugo says hello!

723 | 724 | 725 | :wq 726 | 727 | $ 728 | .... 729 | 730 | Build the web site and then verify the results. 731 | 732 | .... 733 | $ hugo --verbose 734 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 735 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 736 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 737 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 738 | 0 draft content 739 | 0 future content 740 | 0 pages created 741 | 0 tags created 742 | 0 categories created 743 | in 2 ms 744 | 745 | $ find public -type f -name '*.html' | xargs ls -l 746 | -rw-r--r-- 1 quoha staff 78 Sep 29 21:26 public/index.html 747 | 748 | $ cat public/index.html 749 | 750 | 751 | 752 |

hugo says hello!

753 | 754 | .... 755 | 756 | [[live-reload-1]] 757 | Live Reload 758 | +++++++++++ 759 | 760 | Note: If you're running the server with the `--watch` option, you'll see 761 | different content in the file: 762 | 763 | .... 764 | $ cat public/index.html 765 | 766 | 767 | 768 |

hugo says hello!

769 | 773 | 774 | .... 775 | 776 | When you use `--watch`, the Live Reload script is added by Hugo. Look 777 | for live reload in the documentation to see what it does and how to 778 | disable it. 779 | 780 | [[build-a-dynamic-home-page]] 781 | Build a "Dynamic" Home Page 782 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 783 | 784 | "Dynamic home page?" Hugo's a static web site generator, so this seems 785 | an odd thing to say. I mean let's have the home page automatically 786 | reflect the content in the site every time Hugo builds it. We'll use 787 | iteration in the template to do that. 788 | 789 | [[create-new-posts]] 790 | Create New Posts 791 | ++++++++++++++++ 792 | 793 | Now that we have the home page generating static content, let's add some 794 | content to the site. We'll display these posts as a list on the home 795 | page and on their own page, too. 796 | 797 | Hugo has a command to generate a skeleton post, just like it does for 798 | sites and themes. 799 | 800 | .... 801 | $ hugo --verbose new post/first.md 802 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 803 | INFO: 2014/09/29 attempting to create post/first.md of post 804 | INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/default.md 805 | ERROR: 2014/09/29 Unable to Cast to map[string]interface{} 806 | 807 | $ 808 | .... 809 | 810 | That wasn't very nice, was it? 811 | 812 | The "new" command uses an archetype to create the post file. Hugo 813 | created an empty default archetype file, but that causes an error when 814 | there's a theme. For me, the workaround was to create an archetypes file 815 | specifically for the post type. 816 | 817 | .... 818 | $ vi themes/zafta/archetypes/post.md 819 | +++ 820 | Description = "" 821 | Tags = [] 822 | Categories = [] 823 | +++ 824 | :wq 825 | 826 | $ find themes/zafta/archetypes -type f | xargs ls -l 827 | -rw-r--r-- 1 quoha staff 0 Sep 29 21:53 themes/zafta/archetypes/default.md 828 | -rw-r--r-- 1 quoha staff 51 Sep 29 21:54 themes/zafta/archetypes/post.md 829 | 830 | $ hugo --verbose new post/first.md 831 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 832 | INFO: 2014/09/29 attempting to create post/first.md of post 833 | INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md 834 | INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/first.md 835 | /Users/quoha/Sites/zafta/content/post/first.md created 836 | 837 | $ hugo --verbose new post/second.md 838 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 839 | INFO: 2014/09/29 attempting to create post/second.md of post 840 | INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md 841 | INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/second.md 842 | /Users/quoha/Sites/zafta/content/post/second.md created 843 | 844 | $ ls -l content/post 845 | total 16 846 | -rw-r--r-- 1 quoha staff 104 Sep 29 21:54 first.md 847 | -rw-r--r-- 1 quoha staff 105 Sep 29 21:57 second.md 848 | 849 | $ cat content/post/first.md 850 | +++ 851 | Categories = [] 852 | Description = "" 853 | Tags = [] 854 | date = "2014-09-29T21:54:53-05:00" 855 | title = "first" 856 | 857 | +++ 858 | my first post 859 | 860 | $ cat content/post/second.md 861 | +++ 862 | Categories = [] 863 | Description = "" 864 | Tags = [] 865 | date = "2014-09-29T21:57:09-05:00" 866 | title = "second" 867 | 868 | +++ 869 | my second post 870 | 871 | $ 872 | .... 873 | 874 | Build the web site and then verify the results. 875 | 876 | .... 877 | $ rm -rf public 878 | $ hugo --verbose 879 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 880 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 881 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 882 | INFO: 2014/09/29 found taxonomies: map[string]string{"category":"categories", "tag":"tags"} 883 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 884 | 0 draft content 885 | 0 future content 886 | 2 pages created 887 | 0 tags created 888 | 0 categories created 889 | in 4 ms 890 | $ 891 | .... 892 | 893 | The output says that it created 2 pages. Those are our new posts: 894 | 895 | .... 896 | $ find public -type f -name '*.html' | xargs ls -l 897 | -rw-r--r-- 1 quoha staff 78 Sep 29 22:13 public/index.html 898 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/first/index.html 899 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/index.html 900 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/second/index.html 901 | $ 902 | .... 903 | 904 | The new files are empty because because the templates used to generate 905 | the content are empty. The homepage doesn't show the new content, 906 | either. We have to update the templates to add the posts. 907 | 908 | [[list-and-single-templates]] 909 | List and Single Templates 910 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 911 | 912 | In Hugo, we have three major kinds of templates. There's the home page 913 | template that we updated previously. It is used only by the home page. 914 | We also have "single" templates which are used to generate output for a 915 | single content file. We also have "list" templates that are used to 916 | group multiple pieces of content before generating output. 917 | 918 | Generally speaking, list templates are named "list.html" and single 919 | templates are named "single.html." 920 | 921 | There are three other types of templates: partials, content views, and 922 | terms. We will not go into much detail on these. 923 | 924 | [[add-content-to-the-homepage]] 925 | Add Content to the Homepage 926 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 927 | 928 | The home page will contain a list of posts. Let's update its template to 929 | add the posts that we just created. The logic in the template will run 930 | every time we build the site. 931 | 932 | .... 933 | $ vi themes/zafta/layouts/index.html 934 | 935 | 936 | 937 | {{ range first 10 .Data.Pages }} 938 |

{{ .Title }}

939 | {{ end }} 940 | 941 | 942 | :wq 943 | 944 | $ 945 | .... 946 | 947 | Hugo uses the Go template engine. That engine scans the template files 948 | for commands which are enclosed between "\{\{" and "}}". In our 949 | template, the commands are: 950 | 951 | 1. range 952 | 2. .Title 953 | 3. end 954 | 955 | The "range" command is an iterator. We're going to use it to go through 956 | the first ten pages. Every HTML file that Hugo creates is treated as a 957 | page, so looping through the list of pages will look at every file that 958 | will be created. 959 | 960 | The ".Title" command prints the value of the "title" variable. Hugo 961 | pulls it from the front matter in the Markdown file. 962 | 963 | The "end" command signals the end of the range iterator. The engine 964 | loops back to the top of the iteration when it finds "end." Everything 965 | between the "range" and "end" is evaluated every time the engine goes 966 | through the iteration. In this file, that would cause the title from the 967 | first ten pages to be output as heading level one. 968 | 969 | It's helpful to remember that some variables, like .Data, are created 970 | before any output files. Hugo loads every content file into the variable 971 | and then gives the template a chance to process before creating the HTML 972 | files. 973 | 974 | Build the web site and then verify the results. 975 | 976 | .... 977 | $ rm -rf public 978 | $ hugo --verbose 979 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 980 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 981 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 982 | INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} 983 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 984 | 0 draft content 985 | 0 future content 986 | 2 pages created 987 | 0 tags created 988 | 0 categories created 989 | in 4 ms 990 | $ find public -type f -name '*.html' | xargs ls -l 991 | -rw-r--r-- 1 quoha staff 94 Sep 29 22:23 public/index.html 992 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/first/index.html 993 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/index.html 994 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/second/index.html 995 | $ cat public/index.html 996 | 997 | 998 | 999 | 1000 |

second

1001 | 1002 |

first

1003 | 1004 | 1005 | 1006 | $ 1007 | .... 1008 | 1009 | Congratulations, the home page shows the title of the two posts. The 1010 | posts themselves are still empty, but let's take a moment to appreciate 1011 | what we've done. Your template now generates output dynamically. Believe 1012 | it or not, by inserting the range command inside of those curly braces, 1013 | you've learned everything you need to know to build a theme. All that's 1014 | really left is understanding which template will be used to generate 1015 | each content file and becoming familiar with the commands for the 1016 | template engine. 1017 | 1018 | And, if that were entirely true, this tutorial would be much shorter. 1019 | There are a few things to know that will make creating a new template 1020 | much easier. Don't worry, though, that's all to come. 1021 | 1022 | [[add-content-to-the-posts]] 1023 | Add Content to the Posts 1024 | ^^^^^^^^^^^^^^^^^^^^^^^^ 1025 | 1026 | We're working with posts, which are in the content/post/ directory. That 1027 | means that their section is "post" (and if we don't do something weird, 1028 | their type is also "post"). 1029 | 1030 | Hugo uses the section and type to find the template file for every piece 1031 | of content. Hugo will first look for a template file that matches the 1032 | section or type name. If it can't find one, then it will look in the 1033 | _default/ directory. There are some twists that we'll cover when we get 1034 | to categories and tags, but for now we can assume that Hugo will try 1035 | post/single.html, then _default/single.html. 1036 | 1037 | Now that we know the search rule, let's see what we actually have 1038 | available: 1039 | 1040 | .... 1041 | $ find themes/zafta -name single.html | xargs ls -l 1042 | -rw-r--r-- 1 quoha staff 132 Sep 29 17:31 themes/zafta/layouts/_default/single.html 1043 | .... 1044 | 1045 | We could create a new template, post/single.html, or change the default. 1046 | Since we don't know of any other content types, let's start with 1047 | updating the default. 1048 | 1049 | Remember, any content that we haven't created a template for will end up 1050 | using this template. That can be good or bad. Bad because I know that 1051 | we're going to be adding different types of content and we're going to 1052 | end up undoing some of the changes we've made. It's good because we'll 1053 | be able to see immediate results. It's also good to start here because 1054 | we can start to build the basic layout for the site. As we add more 1055 | content types, we'll refactor this file and move logic around. Hugo 1056 | makes that fairly painless, so we'll accept the cost and proceed. 1057 | 1058 | Please see the Hugo documentation on template rendering for all the 1059 | details on determining which template to use. And, as the docs mention, 1060 | if you're building a single page application (SPA) web site, you can 1061 | delete all of the other templates and work with just the default single 1062 | page. That's a refreshing amount of joy right there. 1063 | 1064 | [[update-the-template-file]] 1065 | Update the Template File 1066 | ++++++++++++++++++++++++ 1067 | 1068 | .... 1069 | $ vi themes/zafta/layouts/_default/single.html 1070 | 1071 | 1072 | 1073 | {{ .Title }} 1074 | 1075 | 1076 |

{{ .Title }}

1077 | {{ .Content }} 1078 | 1079 | 1080 | :wq 1081 | 1082 | $ 1083 | .... 1084 | 1085 | Build the web site and verify the results. 1086 | 1087 | .... 1088 | $ rm -rf public 1089 | $ hugo --verbose 1090 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 1091 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 1092 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 1093 | INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} 1094 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 1095 | 0 draft content 1096 | 0 future content 1097 | 2 pages created 1098 | 0 tags created 1099 | 0 categories created 1100 | in 4 ms 1101 | 1102 | $ find public -type f -name '*.html' | xargs ls -l 1103 | -rw-r--r-- 1 quoha staff 94 Sep 29 22:40 public/index.html 1104 | -rw-r--r-- 1 quoha staff 125 Sep 29 22:40 public/post/first/index.html 1105 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:40 public/post/index.html 1106 | -rw-r--r-- 1 quoha staff 128 Sep 29 22:40 public/post/second/index.html 1107 | 1108 | $ cat public/post/first/index.html 1109 | 1110 | 1111 | 1112 | first 1113 | 1114 | 1115 |

first

1116 |

my first post

1117 | 1118 | 1119 | 1120 | 1121 | $ cat public/post/second/index.html 1122 | 1123 | 1124 | 1125 | second 1126 | 1127 | 1128 |

second

1129 |

my second post

1130 | 1131 | 1132 | 1133 | $ 1134 | .... 1135 | 1136 | Notice that the posts now have content. You can go to 1137 | localhost:1313/post/first to verify. 1138 | 1139 | [[linking-to-content]] 1140 | Linking to Content 1141 | ^^^^^^^^^^^^^^^^^^ 1142 | 1143 | The posts are on the home page. Let's add a link from there to the post. 1144 | Since this is the home page, we'll update its template. 1145 | 1146 | .... 1147 | $ vi themes/zafta/layouts/index.html 1148 | 1149 | 1150 | 1151 | {{ range first 10 .Data.Pages }} 1152 |

{{ .Title }}

1153 | {{ end }} 1154 | 1155 | 1156 | .... 1157 | 1158 | Build the web site and verify the results. 1159 | 1160 | .... 1161 | $ rm -rf public 1162 | $ hugo --verbose 1163 | INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml 1164 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ 1165 | INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ 1166 | INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} 1167 | WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] 1168 | 0 draft content 1169 | 0 future content 1170 | 2 pages created 1171 | 0 tags created 1172 | 0 categories created 1173 | in 4 ms 1174 | 1175 | $ find public -type f -name '*.html' | xargs ls -l 1176 | -rw-r--r-- 1 quoha staff 149 Sep 29 22:44 public/index.html 1177 | -rw-r--r-- 1 quoha staff 125 Sep 29 22:44 public/post/first/index.html 1178 | -rw-r--r-- 1 quoha staff 0 Sep 29 22:44 public/post/index.html 1179 | -rw-r--r-- 1 quoha staff 128 Sep 29 22:44 public/post/second/index.html 1180 | 1181 | $ cat public/index.html 1182 | 1183 | 1184 | 1185 | 1186 |

second

1187 | 1188 |

first

1189 | 1190 | 1191 | 1192 | 1193 | $ 1194 | .... 1195 | 1196 | [[create-a-post-listing]] 1197 | Create a Post Listing 1198 | ^^^^^^^^^^^^^^^^^^^^^ 1199 | 1200 | We have the posts displaying on the home page and on their own page. We 1201 | also have a file public/post/index.html that is empty. Let's make it 1202 | show a list of all posts (not just the first ten). 1203 | 1204 | We need to decide which template to update. This will be a listing, so 1205 | it should be a list template. Let's take a quick look and see which list 1206 | templates are available. 1207 | 1208 | .... 1209 | $ find themes/zafta -name list.html | xargs ls -l 1210 | -rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html 1211 | .... 1212 | 1213 | As with the single post, we have to decide to update _default/list.html 1214 | or create post/list.html. We still don't have multiple content types, so 1215 | let's stay consistent and update the default list template. 1216 | 1217 | [[creating-top-level-pages]] 1218 | Creating Top Level Pages 1219 | ~~~~~~~~~~~~~~~~~~~~~~~~ 1220 | 1221 | Let's add an "about" page and display it at the top level (as opposed to 1222 | a sub-level like we did with posts). 1223 | 1224 | The default in Hugo is to use the directory structure of the content/ 1225 | directory to guide the location of the generated html in the public/ 1226 | directory. Let's verify that by creating an "about" page at the top 1227 | level: 1228 | 1229 | .... 1230 | $ vi content/about.md 1231 | +++ 1232 | title = "about" 1233 | description = "about this site" 1234 | date = "2014-09-27" 1235 | slug = "about time" 1236 | +++ 1237 | 1238 | ## about us 1239 | 1240 | i'm speechless 1241 | :wq 1242 | .... 1243 | 1244 | Generate the web site and verify the results. 1245 | 1246 | .... 1247 | $ find public -name '*.html' | xargs ls -l 1248 | -rw-rw-r-- 1 mdhender staff 334 Sep 27 15:08 public/about-time/index.html 1249 | -rw-rw-r-- 1 mdhender staff 527 Sep 27 15:08 public/index.html 1250 | -rw-rw-r-- 1 mdhender staff 358 Sep 27 15:08 public/post/first-post/index.html 1251 | -rw-rw-r-- 1 mdhender staff 0 Sep 27 15:08 public/post/index.html 1252 | -rw-rw-r-- 1 mdhender staff 342 Sep 27 15:08 public/post/second-post/index.html 1253 | .... 1254 | 1255 | Notice that the page wasn't created at the top level. It was created in 1256 | a sub-directory named 'about-time/'. That name came from our slug. Hugo 1257 | will use the slug to name the generated content. It's a reasonable 1258 | default, by the way, but we can learn a few things by fighting it for 1259 | this file. 1260 | 1261 | One other thing. Take a look at the home page. 1262 | 1263 | .... 1264 | $ cat public/index.html 1265 | 1266 | 1267 | 1268 |

creating a new theme

1269 |

about

1270 |

second

1271 |

first

1272 | 1276 | 1277 | .... 1278 | 1279 | Notice that the "about" link is listed with the posts? That's not 1280 | desirable, so let's change that first. 1281 | 1282 | .... 1283 | $ vi themes/zafta/layouts/index.html 1284 | 1285 | 1286 | 1287 |

posts

1288 | {{ range first 10 .Data.Pages }} 1289 | {{ if eq .Type "post"}} 1290 |

{{ .Title }}

1291 | {{ end }} 1292 | {{ end }} 1293 | 1294 |

pages

1295 | {{ range .Data.Pages }} 1296 | {{ if eq .Type "page" }} 1297 |

{{ .Title }}

1298 | {{ end }} 1299 | {{ end }} 1300 | 1301 | 1302 | :wq 1303 | .... 1304 | 1305 | Generate the web site and verify the results. The home page has two 1306 | sections, posts and pages, and each section has the right set of 1307 | headings and links in it. 1308 | 1309 | But, that about page still renders to about-time/index.html. 1310 | 1311 | .... 1312 | $ find public -name '*.html' | xargs ls -l 1313 | -rw-rw-r-- 1 mdhender staff 334 Sep 27 15:33 public/about-time/index.html 1314 | -rw-rw-r-- 1 mdhender staff 645 Sep 27 15:33 public/index.html 1315 | -rw-rw-r-- 1 mdhender staff 358 Sep 27 15:33 public/post/first-post/index.html 1316 | -rw-rw-r-- 1 mdhender staff 0 Sep 27 15:33 public/post/index.html 1317 | -rw-rw-r-- 1 mdhender staff 342 Sep 27 15:33 public/post/second-post/index.html 1318 | .... 1319 | 1320 | Knowing that hugo is using the slug to generate the file name, the 1321 | simplest solution is to change the slug. Let's do it the hard way and 1322 | change the permalink in the configuration file. 1323 | 1324 | .... 1325 | $ vi config.toml 1326 | [permalinks] 1327 | page = "/:title/" 1328 | about = "/:filename/" 1329 | .... 1330 | 1331 | Generate the web site and verify that this didn't work. Hugo lets "slug" 1332 | or "URL" override the permalinks setting in the configuration file. Go 1333 | ahead and comment out the slug in content/about.md, then generate the 1334 | web site to get it to be created in the right place. 1335 | 1336 | [[sharing-templates]] 1337 | Sharing Templates 1338 | ~~~~~~~~~~~~~~~~~ 1339 | 1340 | If you've been following along, you probably noticed that posts have 1341 | titles in the browser and the home page doesn't. That's because we 1342 | didn't put the title in the home page's template (layouts/index.html). 1343 | That's an easy thing to do, but let's look at a different option. 1344 | 1345 | We can put the common bits into a shared template that's stored in the 1346 | themes/zafta/layouts/partials/ directory. 1347 | 1348 | [[create-the-header-and-footer-partials]] 1349 | Create the Header and Footer Partials 1350 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1351 | 1352 | In Hugo, a partial is a sugar-coated template. Normally a template 1353 | reference has a path specified. Partials are different. Hugo searches 1354 | for them along a TODO defined search path. This makes it easier for 1355 | end-users to override the theme's presentation. 1356 | 1357 | .... 1358 | $ vi themes/zafta/layouts/partials/header.html 1359 | 1360 | 1361 | 1362 | {{ .Title }} 1363 | 1364 | 1365 | :wq 1366 | 1367 | $ vi themes/zafta/layouts/partials/footer.html 1368 | 1369 | 1370 | :wq 1371 | .... 1372 | 1373 | [[update-the-home-page-template-to-use-the-partials]] 1374 | Update the Home Page Template to Use the Partials 1375 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1376 | 1377 | The most noticeable difference between a template call and a partials 1378 | call is the lack of path: 1379 | 1380 | .... 1381 | {{ template "theme/partials/header.html" . }} 1382 | .... 1383 | 1384 | versus 1385 | 1386 | .... 1387 | {{ partial "header.html" . }} 1388 | .... 1389 | 1390 | Both pass in the context. 1391 | 1392 | Let's change the home page template to use these new partials. 1393 | 1394 | .... 1395 | $ vi themes/zafta/layouts/index.html 1396 | {{ partial "header.html" . }} 1397 | 1398 |

posts

1399 | {{ range first 10 .Data.Pages }} 1400 | {{ if eq .Type "post"}} 1401 |

{{ .Title }}

1402 | {{ end }} 1403 | {{ end }} 1404 | 1405 |

pages

1406 | {{ range .Data.Pages }} 1407 | {{ if or (eq .Type "page") (eq .Type "about") }} 1408 |

{{ .Type }} - {{ .Title }} - {{ .RelPermalink }}

1409 | {{ end }} 1410 | {{ end }} 1411 | 1412 | {{ partial "footer.html" . }} 1413 | :wq 1414 | .... 1415 | 1416 | Generate the web site and verify the results. The title on the home page 1417 | is now "your title here", which comes from the "title" variable in the 1418 | config.toml file. 1419 | 1420 | [[update-the-default-single-template-to-use-the-partials]] 1421 | Update the Default Single Template to Use the Partials 1422 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1423 | 1424 | .... 1425 | $ vi themes/zafta/layouts/_default/single.html 1426 | {{ partial "header.html" . }} 1427 | 1428 |

{{ .Title }}

1429 | {{ .Content }} 1430 | 1431 | {{ partial "footer.html" . }} 1432 | :wq 1433 | .... 1434 | 1435 | Generate the web site and verify the results. The title on the posts and 1436 | the about page should both reflect the value in the markdown file. 1437 | 1438 | [[add-date-published-to-posts]] 1439 | Add “Date Published” to Posts 1440 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1441 | 1442 | It's common to have posts display the date that they were written or 1443 | published, so let's add that. The front matter of our posts has a 1444 | variable named "date." It's usually the date the content was created, 1445 | but let's pretend that's the value we want to display. 1446 | 1447 | [[add-date-published-to-the-template]] 1448 | Add “Date Published” to the Template 1449 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1450 | 1451 | We'll start by updating the template used to render the posts. The 1452 | template code will look like: 1453 | 1454 | .... 1455 | {{ .Date.Format "Mon, Jan 2, 2006" }} 1456 | .... 1457 | 1458 | Posts use the default single template, so we'll change that file. 1459 | 1460 | .... 1461 | $ vi themes/zafta/layouts/_default/single.html 1462 | {{ partial "header.html" . }} 1463 | 1464 |

{{ .Title }}

1465 |

{{ .Date.Format "Mon, Jan 2, 2006" }}

1466 | {{ .Content }} 1467 | 1468 | {{ partial "footer.html" . }} 1469 | :wq 1470 | .... 1471 | 1472 | Generate the web site and verify the results. The posts now have the 1473 | date displayed in them. There's a problem, though. The "about" page also 1474 | has the date displayed. 1475 | 1476 | As usual, there are a couple of ways to make the date display only on 1477 | posts. We could do an "if" statement like we did on the home page. 1478 | Another way would be to create a separate template for posts. 1479 | 1480 | The "if" solution works for sites that have just a couple of content 1481 | types. It aligns with the principle of "code for today," too. 1482 | 1483 | Let's assume, though, that we've made our site so complex that we feel 1484 | we have to create a new template type. In Hugo-speak, we're going to 1485 | create a section template. 1486 | 1487 | Let's restore the default single template before we forget. 1488 | 1489 | .... 1490 | $ mkdir themes/zafta/layouts/post 1491 | $ vi themes/zafta/layouts/_default/single.html 1492 | {{ partial "header.html" . }} 1493 | 1494 |

{{ .Title }}

1495 | {{ .Content }} 1496 | 1497 | {{ partial "footer.html" . }} 1498 | :wq 1499 | .... 1500 | 1501 | Now we'll update the post's version of the single template. If you 1502 | remember Hugo's rules, the template engine will use this version over 1503 | the default. 1504 | 1505 | .... 1506 | $ vi themes/zafta/layouts/post/single.html 1507 | {{ partial "header.html" . }} 1508 | 1509 |

{{ .Title }}

1510 |

{{ .Date.Format "Mon, Jan 2, 2006" }}

1511 | {{ .Content }} 1512 | 1513 | {{ partial "footer.html" . }} 1514 | :wq 1515 | .... 1516 | 1517 | Note that we removed the date logic from the default template and put it 1518 | in the post template. Generate the web site and verify the results. 1519 | Posts have dates and the about page doesn't. 1520 | 1521 | [[dont-repeat-yourself]] 1522 | Don't Repeat Yourself 1523 | ^^^^^^^^^^^^^^^^^^^^^ 1524 | 1525 | DRY is a good design goal and Hugo does a great job supporting it. Part 1526 | of the art of a good template is knowing when to add a new template and 1527 | when to update an existing one. While you're figuring that out, accept 1528 | that you'll be doing some refactoring. Hugo makes that easy and fast, so 1529 | it's okay to delay splitting up a template. 1530 | -------------------------------------------------------------------------------- /content/post/go-is-for-lovers.adoc: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go!" 3 | date: 2017-07-26T14:31:37-04:00 4 | draft: false 5 | categories: ["Lorem"] 6 | date: "2016-08-03T13:39:46+02:00" 7 | --- 8 | 9 | == Go is for lovers! 10 | Hugo uses the excellent http://golang.org/[go] 11 | http://golang.org/pkg/html/template/[html/template] library for its 12 | template engine. It is an extremely lightweight engine that provides a 13 | very small amount of logic. In our experience that it is just the right 14 | amount of logic to be able to create a good static website. If you have 15 | used other template systems from different languages or frameworks you 16 | will find a lot of similarities in go templates. 17 | 18 | This document is a brief primer on using go templates. The 19 | http://golang.org/pkg/html/template/[go docs] provide more details. 20 | 21 | [[introduction-to-go-templates]] 22 | Introduction to Go Templates 23 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 | 25 | Go templates provide an extremely simple template language. It adheres 26 | to the belief that only the most basic of logic belongs in the template 27 | or view layer. One consequence of this simplicity is that go templates 28 | parse very quickly. 29 | 30 | A unique characteristic of go templates is they are content aware. 31 | Variables and content will be sanitized depending on the context of 32 | where they are used. More details can be found in the 33 | http://golang.org/pkg/html/template/[go docs]. 34 | 35 | [[basic-syntax]] 36 | Basic Syntax 37 | ~~~~~~~~~~~~ 38 | 39 | Go lang templates are html files with the addition of variables and 40 | functions. 41 | 42 | *Go variables and functions are accessible within \{\{ }}* 43 | 44 | Accessing a predefined variable "foo": 45 | 46 | .... 47 | {{ foo }} 48 | .... 49 | 50 | *Parameters are separated using spaces* 51 | 52 | Calling the add function with input of 1, 2: 53 | 54 | .... 55 | {{ add 1 2 }} 56 | .... 57 | 58 | *Methods and fields are accessed via dot notation* 59 | 60 | Accessing the Page Parameter "bar" 61 | 62 | .... 63 | {{ .Params.bar }} 64 | .... 65 | 66 | *Parentheses can be used to group items together* 67 | 68 | .... 69 | {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }} 70 | .... 71 | 72 | [[variables]] 73 | Variables 74 | ~~~~~~~~~ 75 | 76 | Each go template has a struct (object) made available to it. In hugo 77 | each template is passed either a page or a node struct depending on 78 | which type of page you are rendering. More details are available on the 79 | link:/layout/variables[variables] page. 80 | 81 | A variable is accessed by referencing the variable name. 82 | 83 | .... 84 | {{ .Title }} 85 | .... 86 | 87 | Variables can also be defined and referenced. 88 | 89 | .... 90 | {{ $address := "123 Main St."}} 91 | {{ $address }} 92 | .... 93 | 94 | [[functions]] 95 | Functions 96 | ~~~~~~~~~ 97 | 98 | Go template ship with a few functions which provide basic functionality. 99 | The go template system also provides a mechanism for applications to 100 | extend the available functions with their own. 101 | link:/layout/functions[Hugo template functions] provide some additional 102 | functionality we believe are useful for building websites. Functions are 103 | called by using their name followed by the required parameters separated 104 | by spaces. Template functions cannot be added without recompiling hugo. 105 | 106 | *Example:* 107 | 108 | .... 109 | {{ add 1 2 }} 110 | .... 111 | 112 | [[includes]] 113 | Includes 114 | ~~~~~~~~ 115 | 116 | When including another template you will pass to it the data it will be 117 | able to access. To pass along the current context please remember to 118 | include a trailing dot. The templates location will always be starting 119 | at the /layout/ directory within Hugo. 120 | 121 | *Example:* 122 | 123 | .... 124 | {{ template "chrome/header.html" . }} 125 | .... 126 | 127 | [[logic]] 128 | Logic 129 | ~~~~~ 130 | 131 | Go templates provide the most basic iteration and conditional logic. 132 | 133 | [[iteration]] 134 | Iteration 135 | ^^^^^^^^^ 136 | 137 | Just like in go, the go templates make heavy use of range to iterate 138 | over a map, array or slice. The following are different examples of how 139 | to use range. 140 | 141 | *Example 1: Using Context* 142 | 143 | .... 144 | {{ range array }} 145 | {{ . }} 146 | {{ end }} 147 | .... 148 | 149 | *Example 2: Declaring value variable name* 150 | 151 | .... 152 | {{range $element := array}} 153 | {{ $element }} 154 | {{ end }} 155 | .... 156 | 157 | *Example 2: Declaring key and value variable name* 158 | 159 | .... 160 | {{range $index, $element := array}} 161 | {{ $index }} 162 | {{ $element }} 163 | {{ end }} 164 | .... 165 | 166 | [[conditionals]] 167 | Conditionals 168 | ^^^^^^^^^^^^ 169 | 170 | If, else, with, or, & and provide the framework for handling conditional 171 | logic in Go Templates. Like range, each statement is closed with `end`. 172 | 173 | Go Templates treat the following values as false: 174 | 175 | * false 176 | * 0 177 | * any array, slice, map, or string of length zero 178 | 179 | *Example 1: If* 180 | 181 | .... 182 | {{ if isset .Params "title" }}

{{ index .Params "title" }}

{{ end }} 183 | .... 184 | 185 | *Example 2: If -> Else* 186 | 187 | .... 188 | {{ if isset .Params "alt" }} 189 | {{ index .Params "alt" }} 190 | {{else}} 191 | {{ index .Params "caption" }} 192 | {{ end }} 193 | .... 194 | 195 | *Example 3: And & Or* 196 | 197 | .... 198 | {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}} 199 | .... 200 | 201 | *Example 4: With* 202 | 203 | An alternative way of writing "if" and then referencing the same value 204 | is to use "with" instead. With rebinds the context `.` within its scope, 205 | and skips the block if the variable is absent. 206 | 207 | The first example above could be simplified as: 208 | 209 | .... 210 | {{ with .Params.title }}

{{ . }}

{{ end }} 211 | .... 212 | 213 | *Example 5: If -> Else If* 214 | 215 | .... 216 | {{ if isset .Params "alt" }} 217 | {{ index .Params "alt" }} 218 | {{ else if isset .Params "caption" }} 219 | {{ index .Params "caption" }} 220 | {{ end }} 221 | .... 222 | 223 | [[pipes]] 224 | Pipes 225 | ~~~~~ 226 | 227 | One of the most powerful components of go templates is the ability to 228 | stack actions one after another. This is done by using pipes. Borrowed 229 | from unix pipes, the concept is simple, each pipeline's output becomes 230 | the input of the following pipe. 231 | 232 | Because of the very simple syntax of go templates, the pipe is essential 233 | to being able to chain together function calls. One limitation of the 234 | pipes is that they only can work with a single value and that value 235 | becomes the last parameter of the next pipeline. 236 | 237 | A few simple examples should help convey how to use the pipe. 238 | 239 | *Example 1 :* 240 | 241 | .... 242 | {{ if eq 1 1 }} Same {{ end }} 243 | .... 244 | 245 | is the same as 246 | 247 | .... 248 | {{ eq 1 1 | if }} Same {{ end }} 249 | .... 250 | 251 | It does look odd to place the if at the end, but it does provide a good 252 | illustration of how to use the pipes. 253 | 254 | *Example 2 :* 255 | 256 | .... 257 | {{ index .Params "disqus_url" | html }} 258 | .... 259 | 260 | Access the page parameter called "disqus_url" and escape the HTML. 261 | 262 | *Example 3 :* 263 | 264 | .... 265 | {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}} 266 | Stuff Here 267 | {{ end }} 268 | .... 269 | 270 | Could be rewritten as 271 | 272 | .... 273 | {{ isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }} 274 | Stuff Here 275 | {{ end }} 276 | .... 277 | 278 | [[context-aka.-the-dot]] 279 | Context (aka. the dot) 280 | ~~~~~~~~~~~~~~~~~~~~~~ 281 | 282 | The most easily overlooked concept to understand about go templates is 283 | that \{\{ . }} always refers to the current context. In the top level of 284 | your template this will be the data set made available to it. Inside of 285 | a iteration it will have the value of the current item. When inside of a 286 | loop the context has changed. . will no longer refer to the data 287 | available to the entire page. If you need to access this from within the 288 | loop you will likely want to set it to a variable instead of depending 289 | on the context. 290 | 291 | *Example:* 292 | 293 | .... 294 | {{ $title := .Site.Title }} 295 | {{ range .Params.tags }} 296 |
  • {{ . }} - {{ $title }}
  • 297 | {{ end }} 298 | .... 299 | 300 | Notice how once we have entered the loop the value of \{\{ . }} has 301 | changed. We have defined a variable outside of the loop so we have 302 | access to it from within the loop. 303 | 304 | [[hugo-parameters]] 305 | Hugo Parameters 306 | --------------- 307 | 308 | Hugo provides the option of passing values to the template language 309 | through the site configuration (for sitewide values), or through the 310 | meta data of each specific piece of content. You can define any values 311 | of any type (supported by your front matter/config format) and use them 312 | however you want to inside of your templates. 313 | 314 | [[using-content-page-parameters]] 315 | Using Content (page) Parameters 316 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 317 | 318 | In each piece of content you can provide variables to be used by the 319 | templates. This happens in the link:/content/front-matter[front matter]. 320 | 321 | An example of this is used in this documentation site. Most of the pages 322 | benefit from having the table of contents provided. Sometimes the TOC 323 | just doesn't make a lot of sense. We've defined a variable in our front 324 | matter of some pages to turn off the TOC from being displayed. 325 | 326 | Here is the example front matter: 327 | 328 | .... 329 | --- 330 | title: "Permalinks" 331 | date: "2013-11-18" 332 | aliases: 333 | - "/doc/permalinks/" 334 | groups: ["extras"] 335 | groups_weight: 30 336 | notoc: true 337 | --- 338 | .... 339 | 340 | Here is the corresponding code inside of the template: 341 | 342 | .... 343 | {{ if not .Params.notoc }} 344 |
    345 | {{ .TableOfContents }} 346 |
    347 | {{ end }} 348 | .... 349 | 350 | [[using-site-config-parameters]] 351 | Using Site (config) Parameters 352 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 353 | 354 | In your top-level configuration file (eg, `config.yaml`) you can define 355 | site parameters, which are values which will be available to you in 356 | chrome. 357 | 358 | For instance, you might declare: 359 | 360 | [source,yaml] 361 | ---- 362 | params: 363 | CopyrightHTML: "Copyright © 2013 John Doe. All Rights Reserved." 364 | TwitterUser: "spf13" 365 | SidebarRecentLimit: 5 366 | ---- 367 | 368 | Within a footer layout, you might then declare a `