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