c4210eb50a0668c0d70e4be9572ff057c16302e4
[kengrimes.com/content.git] / content / ox-hugo-tutorial.md
1 ---
2 title: "Using ox-hugo To Build Websites with Emacs"
3 author: ["Ken Grimes"]
4 date: 2018-04-19T18:06:00-07:00
5 tags: ["org", "emacs", "hugo"]
6 categories: ["tutorial"]
7 draft: false
8 header: "/img/org.png"
9 ---
10
11 This article explains in detail the process of setting up a bare-bones website
12 using Hugo and Org mode. My goal in writing this is to provide readers with a
13 superior understanding of the fundamentals of this workflow. It is by no means
14 an exhaustive explanation of Org mode or Emacs, but should give readers of any
15 skill level a strong foundation to apply their own knowledge and techniques to
16 the Emacs-Hugo toolchain.
17
18 I assume only beginner-level knowledge of Emacs.
19
20
21 # Intro & Setup {#intro-and-setup}
22
23 [Kaushal Modi](https://github.com/kaushalmodi) created ox-hugo on top of his ox-blackfriday package, providing an
24 impressive amount of features for organizing blog text and linked data with
25 Hugo. He maintains [great documentation](https://ox-hugo.scripter.co/) and ample [examples](https://github.com/kaushalmodi/ox-hugo/tree/master/test/site/content-org) for using the
26 package. I will explain my own workflow here, but for an exhaustive (though
27 terse) reference, I highly recommend Modi's [test site](https://ox-hugo.scripter.co/test/) and [post source](https://raw.githubusercontent.com/kaushalmodi/ox-hugo/master/test/site/content-org/all-posts.org) Org file,
28 which contain demonstrations and tests for all of ox-hugo's features.
29
30 After issuing the Emacs command `M-x package-install RET ox-hugo RET`, you'll
31 need to `require` it. You can do this by running `M-: (require 'ox-hugo)`, but
32 you'll want to add it to your configuration as explained [here](https://ox-hugo.scripter.co/doc/usage/). Once this is
33 done, using ox-hugo is just a matter of making an Org file and writing
34 content. Org's format is very straightforward, and is designed to make sense to
35 the reader even if they're unfamiliar with the formal syntax. For instance,
36
37 ```org
38 * My food
39 | Where's My Food? | Fridge | Counter | Mouth | Total |
40 | Oranges | 1 | 3 | 0 | :=vsum($2..$4) |
41 | Marshmallows | 0 | 100 | 20 | :=vsum($2..$4) |
42 | Brussel Sprouts | 32 | 4 | 0 | :=vsum($2..$4) |
43 ```
44
45 Produces a dynamic spreadsheet table in Org mode that exports to HTML like this:
46
47
48 ## My food {#my-food}
49
50 | Where's My Food? | Fridge | Counter | Mouth | Total |
51 |------------------|--------|---------|-------|-------|
52 | Oranges | 1 | 3 | 0 | 4 |
53 | Marshmallows | 0 | 100 | 20 | 120 |
54 | Brussel Sprouts | 32 | 4 | 0 | 36 |
55
56 If you're already familiar with Org mode, the benefits are obvious and creating
57 content is fairly trivial. Org mode is, however, a complex and expansive program
58 with many features, and its learning curve can appear daunting at first glance.
59 Using ox-hugo is a great way to learn the format, since it gives the author a
60 command-center view of their entire content hierarchy, much like a traditional
61 database, but in a flat format that's much easier to read and understand. Org
62 features present themselves naturally, and the author can easily visualize the
63 correspondence between the Org format and the output on their webpage.
64
65 Just take a look at the [Org file](https://www.kengrimes.com/gitweb/?p=kengrimes.com/content.git;a=blob_plain;f=content.org;hb=HEAD) for this webpage. Search for "ox-hugo is super
66 cool!" and you should find this very paragraph.
67
68 Eventually you'll want to [read the manual](https://orgmode.org/manual/), though. You may access it in Emacs
69 with `M-x org-info`.
70
71
72 # Making a New Blog {#making-a-new-blog}
73
74 Compared to a generic Org file, the only necessary data that ox-hugo needs to
75 properly export to Hugo is an `:EXPORT_FILE_NAME:` property in the
76 `:PROPERTIES:` block of an Org heading. `:PROPERTIES:` blocks are common in Org
77 for defining arbitrary metadata about sections, and ox-hugo uses them to
78 generate Hugo's [front matter](https://gohugo.io/content-management/front-matter/) (used for associating a title, header, or other
79 custom data with the page it generates). Providing an `:EXPORT_FILE_NAME:`
80 definition signals to ox-hugo that a particular heading is available for export
81 to Hugo. For example, the `:PROPERTIES:` block of the page you're currently
82 reading looks like this:
83
84 ```org
85 :PROPERTIES:
86 :EXPORT_FILE_NAME: ox-hugo-tutorial
87 :EXPORT_DESCRIPTION: Exporting to Hugo's Blackfriday Markdown from Orgmode
88 :EXPORT_HUGO_IMAGES: /img/org.png
89 :END:
90 ```
91
92 The `:EXPORT_HUGO_IMAGES:` and `:EXPORT_DESCRIPTION:` variables are optional
93 definitions allowed by the Speedy theme of this website, but the filename is the
94 only required property for ox-hugo. Our goal here is to organize the structure
95 of our website as a tree using Org headers. So, as a minimal example, here's
96 what a new site might look like in its entirety:
97
98 {{< highlight org "linenos=table, linenostart=1" >}}
99 #+hugo_base_dir: .
100 * My Blog
101 :PROPERTIES:
102 :EXPORT_HUGO_SECTION:
103 :END:
104 ** Home
105 :PROPERTIES:
106 :EXPORT_FILE_NAME: _index
107 :END:
108 This is the home of my blog!
109 ** One Bad Night
110 :PROPERTIES:
111 :EXPORT_FILE_NAME: bad-night
112 :END:
113 Someone gave me herpes! Oh no!
114 {{< /highlight >}}
115
116 The Org file can be placed in any directory so long as `HUGO_BASE_DIR` correctly
117 identifies the Hugo project's root directory. This path definition is required
118 for any valid ox-hugo file, and in the example above uses `#+hugo_base_dir: .`
119 to specify that the base directory will be the same path as this Org file. If
120 you saved this file as hugotest.org, exported it with Org's exporter `C-c C-e`
121 and selected the Hugo output `H` and the All Subtrees To Files option `A`, you'd
122 wind up with the following files in your directory:
123
124 ```nil
125 .
126 ├── content
127 │   ├── bad-night.md
128 │   └── _index.md
129 └── hugotest.org
130 ```
131
132 Most sites will be more than a blog, though, and will want multiple sections. In
133 fact, many sites are made up of nothing but a slew of sections that users
134 navigate between with some built-in menu. So a more functional minimal example
135 would be the following:
136
137 {{< highlight org "linenos=table, linenostart=1" >}}
138 #+hugo_base_dir: .
139 * Homepage
140 :PROPERTIES:
141 :EXPORT_HUGO_SECTION:
142 :EXPORT_FILE_NAME: _index
143 :EXPORT_HUGO_MENU: :menu "main"
144 :END:
145 This is the home of my blog!
146 * Blog Posts
147 :PROPERTIES:
148 :EXPORT_HUGO_SECTION: posts
149 :END:
150 ** My Blog Homepage
151 :PROPERTIES:
152 :EXPORT_HUGO_MENU: :menu "main"
153 :EXPORT_FILE_NAME: _index
154 :END:
155 Man, look at all my blog posts.
156 ** One Bad Night
157 :PROPERTIES:
158 :EXPORT_FILE_NAME: bad-night
159 :END:
160 Someone gave me herpes! Oh no!
161 {{< /highlight >}}
162
163 Which yields the following files on export:
164
165 ```nil
166 .
167 ├── content
168 │   ├── _index.md
169 │   └── posts
170 │   ├── bad-night.md
171 │   └── _index.md
172 └── hugotest.org
173 ```
174
175 As you might expect if you're already familiar with Hugo, this structure adheres
176 to the Hugo [content management](https://gohugo.io/content-management/organization/) scheme. Additionally, the index files have been
177 marked with menu metadata, which allows Hugo themes to automatically generate
178 navigation menus from the markdown files. Hereafter, making new blog posts is as
179 simple as adding new sub-headings under the "Blog Posts" heading, and
180 exporting. As you can see, this is suitable for defining the hierarchical
181 structure of any general website, not just blogs. Org mode and Hugo just make
182 creating new pages so simple and well-structured that providing content is all
183 that's required for a new page, blog entry, or entirely new site section. If you
184 can blog with ox-hugo, you can deftly deploy any manner of web content, or even
185 develop entire websites as naturally as you make blog posts. Any tool that can
186 turn blogging and web development into the same task is quite an achievement!
187
188 Of course, themes to style this content are another can of worms entirely, but
189 we'll get to that soon. It is sufficient for now to mention that Hugo makes
190 [using themes](https://gohugo.io/themes/installing-and-using-themes/) as easy as downloading one and specifying it in Hugo's config file.
191
192
193 ## Heading Management {#heading-management}
194
195 One question you may ask is why the blog's homepage is not defined in the **Blog
196 Posts** heading. This is a fair question! Any heading with an
197 `:EXPORT_FILE_NAME:` property will export _all_ of that heading's content,
198 _including subheadings_ beneath it. This allows Org headings to be used as part
199 of the content of a post, where they will be exported as markdown heading
200 levels, which translate to HTML heading elements `<h1>`, `<h2>`, `<h3>`,
201 etcetera.
202
203 Furthermore, properties other than `:EXPORT_FILE_NAME:` are _inherited_ by
204 sub-headings, including the `:EXPORT_HUGO_MENU:` properties. A
205 `:EXPORT_HUGO_MENU:` property at the section root would cause all exported files
206 within that section to be added to the menu specified. This might be intended by
207 the content creator, but most likely you don't want every single post you make
208 to be in the main menu. So it makes sense to define all your pages, including
209 the index, as a sub-heading of the section definition (which merely specifies
210 which sub-directory the content will output to).
211
212 To illustrate, let's assume you want to extend the previous site definition with
213 a section about fishsticks.
214
215 {{< highlight org "linenos=table, linenostart=24" >}}
216 * Fishsticks
217 :PROPERTIES:
218 :EXPORT_HUGO_SECTION: fishsticks
219 :EXPORT_HUGO_MENU: :menu "main"
220 :EXPORT_FILE_NAME: _index
221 :END:
222 This section devoted to Orson Wells, R.I.P.
223 ** Van De Camps
224 :PROPERTIES:
225 :EXPORT_FILE_NAME: van-de-camps
226 :END:
227 If this is fish, I'll be a monkey's uncle.
228 ** Gortons
229 :PROPERTIES:
230 :EXPORT_FILE_NAME: gortons
231 :END:
232 I think these gave me the herpes.
233 {{< /highlight >}}
234
235 In this example, we've defined the main homepage of the section inside the
236 tier-1 heading for Fishsticks. This is technically valid, and produces the
237 expected file output:
238
239 ```nil
240 .
241 ├── content
242 │   ├── fishsticks
243 │   │   ├── gortons.md
244 │   │   ├── _index.md
245 │   │   └── van-de-camps.md
246 │   ├── _index.md
247 │   └── posts
248 │   ├── bad-night.md
249 │   └── _index.md
250 └── hugotest.org
251 ```
252
253 But on inspection of the gortons.md file, we find the anomoly mentioned above:
254
255 {{< highlight markdown "linenos=table, linenostart=1" >}}
256 ---
257 title: "Gortons"
258 author: ["Ken Grimes"]
259 draft: false
260 menu:
261 main:
262 weight: 2002
263 identifier: "gortons"
264 ---
265
266 I think these gave me the herpes.
267 {{< /highlight >}}
268
269 Uh oh! Not only did these fishsticks give us herpes, they are now part of the
270 main menu. Worse, when the index page was exported, each of the subsequent posts
271 became part of its content:
272
273 {{< highlight markdown "linenos=table, linenostart=1" >}}
274 ---
275 title: "Fishsticks"
276 author: ["Ken Grimes"]
277 draft: false
278 menu:
279 main:
280 weight: 1001
281 identifier: "fishsticks"
282 ---
283
284 This section devoted to Orson Wells, R.I.P.
285
286
287 ## Van De Camps {#van-de-camps}
288
289 If this is fish, I'll be a monkey's uncle.
290
291
292 ## Gortons {#gortons}
293
294 I think these gave me the herpes.
295 {{< /highlight >}}
296
297 Tisk tisk. So be sure to put your index pages in subheadings (just as you do
298 with normal pages) so that the tier-1 heading can be used for "global"
299 definitions that affect all of the pages. A corrected section for fishsticks
300 would look like this:
301
302 {{< highlight org "linenos=table, linenostart=25" >}}
303 ** Fishsticks
304 :PROPERTIES:
305 :EXPORT_HUGO_SECTION: fishsticks
306 :END:
307 *** Fishsticks Home
308 :PROPERTIES:
309 :EXPORT_HUGO_MENU: :menu "main"
310 :EXPORT_FILE_NAME: _index
311 :END:
312 This section devoted to Orson Wells, R.I.P.
313 *** Van De Camps
314 :PROPERTIES:
315 :EXPORT_FILE_NAME: van-de-camps
316 :END:
317 If this is fish, I'll be a monkey's uncle.
318 *** Gortons
319 :PROPERTIES:
320 :EXPORT_FILE_NAME: gortons
321 :END:
322 I think these gave me the herpes.
323 {{< /highlight >}}
324
325
326 # Hugo Setup {#hugo-setup}
327
328 At this point, setting up Hugo and publishing is simple. [Installing](https://gohugo.io/getting-started/installing/) Hugo is
329 pretty straightforward on any Unix-like system with a package manager; it is
330 available on most distributions at this point. Windows installation is a bigger
331 pain in the ass, but you should be used to that if you're still in the
332 stone-age.
333
334 Using `hugo new site .` on the command-line will create a new hugo site in the
335 current directory, but `hugo` expects to be creating a new directory with this
336 command and will complain if it already exists. It also provides the `--force`
337 option to allow creating a new site in an extant directory, but this too will
338 fail if the **content** subdirectory already exists (which ox-hugo will create
339 when you export).
340
341 So you have three choices:
342
343 1. run `hugo new site /path/to/some-new-dir` and move your Org file to this new
344 directory
345 2. simply `rm -Rf content/` to remove the content directory ox-hugo created,
346 then run `hugo new site --force .`
347 3. don't even bother with the `hugo new site` command, and make a **config.toml**
348 file manually (the only file really required for Hugo to run).
349
350 It's convenient to do this through the `hugo` command because it will create
351 Hugo-specific subdirectories like archetypes, layouts, themes, etcetera, in
352 addition to populating a basic **config.toml** file. The subdirectories it creates
353 aren't necessary, but help illustrate Hugo's structure. In any case, you'll want
354 to wind up with a directory structure something like this (created with option 2
355 above, extending from previous examples):
356
357 ```nil
358 .
359 ├── archetypes
360 │   └── default.md
361 ├── config.toml
362 ├── content
363 ├── data
364 ├── hugotest.org
365 ├── layouts
366 ├── static
367 └── themes
368 ```
369
370 Exporting with ox-hugo using `C-c C-e H A` again will, as expected, fill the
371 content directory with our content.
372
373 ```nil
374 .
375 ├── archetypes
376 │   └── default.md
377 ├── config.toml
378 ├── content
379 │   ├── fishsticks
380 │   │   ├── gortons.md
381 │   │   ├── _index.md
382 │   │   └── van-de-camps.md
383 │   ├── _index.md
384 │   └── posts
385 │   ├── bad-night.md
386 │   └── _index.md
387 ├── data
388 ├── hugotest.org
389 ├── layouts
390 ├── static
391 └── themes
392 ```
393
394
395 ## Theming {#theming}
396
397 The last thing to do here is to download or create a theme for Hugo. As
398 mentioned before, installing a theme is very simple. This blog uses a custom
399 theme named Speedy that I have been developing to help myself learn Hugo's
400 internals, but for this example I'll be using Kaushal Modi's [bare-min theme](https://github.com/kaushalmodi/hugo-bare-min-theme). The
401 bare-min theme is the best starting place out there for making new themes, and
402 outputs basic HTML pages without any need to mess with CSS or JS. It also
403 provides easy debugging facilities and search features.
404
405 So let's install it! You can download the theme from its github page and extract
406 it to the themes folder, or much more easily use git to clone it to your themes
407 directory. `git clone https://github.com/kaushalmodi/hugo-bare-min-theme.git
408 themes/bare-min` Then open up your **config.toml** file, and add the theme.
409
410 {{< highlight toml "linenos=table, linenostart=1" >}}
411 baseURL = "http://example.org/"
412 languageCode = "en-us"
413 title = "My New Hugo Site"
414 # Adding a theme:
415 theme = "bare-min"
416 {{< /highlight >}}
417
418 Be sure that the theme's name matches the theme directory's name in the **themes/**
419 directory of your project base directory. (e.g. **themes/bare-min** here). That's it
420 for installing the theme.
421
422 Now, running the command `hugo` with no subcommands will invoke the Hugo
423 generator on the current directory, and output finalized content in the
424 **public/** directory.
425
426 ```nil
427 .
428 ├── archetypes
429 │   └── default.md
430 ├── config.toml
431 ├── content
432 │   ├── fishsticks
433 │   │   ├── gortons.md
434 │   │   ├── _index.md
435 │   │   └── van-de-camps.md
436 │   ├── _index.md
437 │   └── posts
438 │   ├── bad-night.md
439 │   └── _index.md
440 ├── data
441 ├── hugotest.org
442 ├── layouts
443 ├── public
444 │   ├── categories
445 │   │   ├── index.html
446 │   │   └── index.xml
447 │   ├── css
448 │   │   └── github_chroma.css
449 │   ├── fishsticks
450 │   │   ├── gortons
451 │   │   │   └── index.html
452 │   │   ├── index.html
453 │   │   ├── index.xml
454 │   │   └── van-de-camps
455 │   │   └── index.html
456 │   ├── index.html
457 │   ├── index.xml
458 │   ├── js
459 │   │   └── search.js
460 │   ├── page
461 │   │   └── 1
462 │   │   └── index.html
463 │   ├── posts
464 │   │   ├── bad-night
465 │   │   │   └── index.html
466 │   │   ├── index.html
467 │   │   └── index.xml
468 │   ├── sitemap.xml
469 │   └── tags
470 │   ├── index.html
471 │   └── index.xml
472 ├── static
473 └── themes ...
474 ```
475
476 Hugo, by default, generates xml files that are suitable for RSS feeds. With a
477 theme installed, Hugo will produce more suitable web content (usually HTML) to
478 be served over HTTP. The bare-min theme outputs HTML, provides CSS for doing
479 chroma-based syntax highlighting (in case you include code blocks), and inline
480 styles for basic page formatting. Generated pages also have a lot of useful
481 debugging information. You'll also notice that Hugo has generated folders for
482 "categories" and "tags". These are default organization labels for your content
483 called [taxonomies](https://gohugo.io/content-management/taxonomies/).
484
485
486 ## Taxonomies {#taxonomies}
487
488 The taxonomy index pages allow users to browse content by category or tag. These
489 taxonomies correspond to Org mode tags, and ox-hugo will automatically
490 associated tagged headings with the tags taxonomy, or the categories taxonomy if
491 prefixed with an @ symbol. You are free to define your own taxonomies, and even
492 disable the default "tags" and "categories" taxonomies, but since Org mode tags
493 directly translate to the default Hugo taxonomies, it makes sense to just use
494 the default taxonomies for now.
495
496 As an example of taxonomies, I'll add some tags and categories to our
497 **hugotest.org** file to create a complete blog structure with tags and categories:
498
499 {{< highlight org "linenos=table, linenostart=1" >}}
500 #+hugo_base_dir: .
501 * Homepage
502 :PROPERTIES:
503 :EXPORT_HUGO_SECTION:
504 :EXPORT_FILE_NAME: _index
505 :EXPORT_HUGO_MENU: :menu "main"
506 :END:
507 This is the home of my blog!
508 * Blog Posts
509 :PROPERTIES:
510 :EXPORT_HUGO_SECTION: posts
511 :END:
512 ** My Blog Homepage
513 :PROPERTIES:
514 :EXPORT_HUGO_MENU: :menu "main"
515 :EXPORT_FILE_NAME: _index
516 :END:
517 Man, look at all my blog posts.
518 ** One Bad Night :@updates:herpes:fear:
519 :PROPERTIES:
520 :EXPORT_FILE_NAME: bad-night
521 :END:
522 Someone gave me herpes! Oh no!
523 * Fishsticks
524 :PROPERTIES:
525 :EXPORT_HUGO_SECTION: fishsticks
526 :END:
527 ** Fishsticks Home
528 :PROPERTIES:
529 :EXPORT_HUGO_MENU: :menu "main"
530 :EXPORT_FILE_NAME: _index
531 :END:
532 This section devoted to Orson Wells, R.I.P.
533 ** Van De Camps :@reviews:fear:
534 :PROPERTIES:
535 :EXPORT_FILE_NAME: van-de-camps
536 :END:
537 If this is fish, I'll be a monkey's uncle.
538 ** Gortons :@reviews:herpes:
539 :PROPERTIES:
540 :EXPORT_FILE_NAME: gortons
541 :END:
542 I think these gave me the herpes.
543 {{< /highlight >}}
544
545 Exporting **hugotest.org** with `C-c C-e H A` and generating with `hugo` will yield
546 the same file structure as before, but this time we'll see that the categories
547 and tags directories have sections for our newly added taxonomies.
548
549 ```nil
550 .
551 └── public
552 ├── categories
553 │   ├── index.html
554 │   ├── index.xml
555 │   ├── reviews
556 │   │   ├── index.html
557 │   │   └── index.xml
558 │   └── updates
559 │   ├── index.html
560 │   └── index.xml
561 └── tags
562 ├── fear
563 │   ├── index.html
564 │   └── index.xml
565 ├── herpes
566 │   ├── index.html
567 │   └── index.xml
568 ├── index.html
569 └── index.xml
570 ```
571
572 The index pages of taxonomies provide a list of all available taxonomies of that
573 type, each with list pages that show all content associated with them. This
574 allows themes to easily build navigation pages for browsing or querying
575 taxonomies. Files like these are often useful to output as JSON (done by the
576 theme) to allow Javascript-driven dynamic search features, but a simpler scheme
577 can output HTML pages to browse taxonomies just as you would posts in a section
578 (i.e. Org mode heading).
579
580
581 ## Serving Content {#serving-content}
582
583 You can now serve the **public/** directory over an HTTP server. Hugo is packaged
584 with an internal [HTTP server](https://gohugo.io/commands/hugo_server/) to help with testing, which is quite convenient
585 because it can automatically refresh whenever content in its **content/** directory
586 is updated (so when you export from ox-hugo, you don't have to run `hugo`
587 again). To use it, simply run `hugo server` and point your browser at
588 <http://localhost:1313> (1313 is the default `--port` argument for `hugo server`).
589
590
591 # Additional Information {#additional-information}
592
593 Eventually you'll want to move on to [other themes](https://themes.gohugo.io/), or [develop your own](https://gohugo.io/themes/creating/), but at
594 this point you've got a fully functional blog publishing workflow from start to
595 finish that you can view in-browser as you develop.
596
597
598 ## Attaching Files, Capturing Information & Automation {#attaching-files-capturing-information-and-automation}
599
600 Once you have a basic site structured in your Org file, you're ready to start
601 throwing information in it. It is of course sufficient to open the Org file and
602 edit it, but most Org mode users prefer to automate _everything_, and being able
603 to use Org's capture feature to instantly populate new blog posts is extremely
604 convenient.
605
606 The [ox-hugo documentation](https://ox-hugo.scripter.co/) provides succinct explanations on how to do this,
607 including elisp snippets for [capture setup](https://ox-hugo.scripter.co/doc/org-capture-setup/), [image linking](https://ox-hugo.scripter.co/doc/images-in-content/), and [automating
608 exports](https://ox-hugo.scripter.co/doc/auto-export-on-saving/) when you save your Org file (so no more need to `C-c C-e H A` every
609 time, just save the file as usual with `C-x C-s`).
610
611
612 ## Indexes and Page Resources {#indexes-and-page-resources}
613
614 You may be wondering why our index pages are exported as **\_index** rather than
615 **index**. Hugo uses a concept called [Page Bundles](https://gohugo.io/content-management/page-bundles/) to organize exported
616 content. The gist of this is that a file named **index** is known as a "Leaf Node"
617 and cannot have any children. A file named **\_index** is considered a "Branch
618 Node" and allows nesting other bundles beneath it. In other words, an Org
619 heading with an exported file name of **index** will be treated as a single page
620 with no subfolders. This is useful for single pages, but a section index
621 (e.g. for a blog) with many subpages and other resources will more than likely
622 want to allow nested bundles beneath it.
623
624 You may export an Org heading as a Page Bundle by providing the Org property
625 `:EXPORT_HUGO_BUNDLE:` with an argument (string) that will become the name of
626 the folder created. If you do this, you will need to set the
627 `:EXPORT_FILE_NAME:` property to either **index** for Leaf Nodes, or **\_index** for
628 Branch Nodes.
629
630 The [capture setup](https://ox-hugo.scripter.co/doc/org-capture-setup/) provided by Kaushal Modi above provides methods to
631 automatically create either a normal page, or a leaf node bundle when invoking
632 Org Capture.
633
634
635 ## Drafts and Automatic Timestamps {#drafts-and-automatic-timestamps}
636
637 By default, Hugo will not build any markdown files whose front-matter properties
638 include `draft: true`. This is very convenient for in-progress posts that you
639 leave in your Org file, or in the **content/** directory. If you are using
640 archetypes (which define default front-matter for various resource types, and
641 may include Hugo templating directives), you can see that the primary archetype
642 in **archetypes/default.md** set the draft property to true on all content unless
643 the markdown file overrides this behavior:
644
645 ```markdown
646 ---
647 title: "{{ replace .Name "-" " " | title }}"
648 date: {{ .Date }}
649 draft: true
650 ---
651 ```
652
653 Ox-hugo will always fill out the draft property, overriding this archetype's
654 default value. By default, every exported header will have its draft property
655 set to **false**. However, ox-hugo conveniently links this behavior to the TODO
656 feature of Org. When you cycle a heading's TODO value with `S-<RIGHT>` (that's
657 Shift + Right Arrow Key), you will signal to ox-hugo to export this heading as
658 a draft (i.e. `draft: true`), which will prevent Hugo from building it into an
659 HTML page.
660
661 Better still, when a heading is cycled to the DONE state in Org, it will
662 automatically generate a timestamp for when the heading was closed. Ox-hugo will
663 export DONE headings with `draft: false` and, better still, will use Org's
664 timestamp to fill out the Date property in the markdown file. This makes it
665 trivial to manage writing multiple posts at once, and automatically timestamp
666 completion dates.
667
668 You may also explicitly set this date parameter with the `:EXPORT_DATE:`
669 property, but the convenience of using DONE-state switching is pretty hard to
670 pass up.
671
672
673 ## Renaming Tags and Other Properties {#renaming-tags-and-other-properties}
674
675 If a theme you are using has any idiosyncrasies about your naming conventions
676 (e.g. if you export your content to more than one site using more than one
677 theme), ox-hugo provides a [convenient way](https://ox-hugo.scripter.co/doc/replace-front-matter-keys/) to automatically replace any key
678 values on export. This can be done on a per-heading, or a per-file basis.
679
680 To replace keys for the entire file, simply add a property to the top of your
681 Org file. For example:
682
683 ```org
684 #+hugo_front_matter_key_replace: description>summary
685 ```
686
687 This will make any `:EXPORT_DESCRIPTION:` properties export, instead, to a
688 "summary" key in the front-matter of your output markdown file. It will also be
689 able to replace exported values in the Org body:
690
691 ```org
692 #+begin_description
693 This is the description, but will export as the Summary value in front-matter
694 #+end_description
695 ```
696
697 To do this on a per-heading basis, simply add the
698 `:EXPORT_HUGO_FRONT_MATTER_KEY_REPLACE:` property to a heading's property block,
699 and the replacements will only occur within that heading.