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