A note from the authors: Some of the information and instructions in this book are now out of date because of changes to Hugo and the blogdown package. If you have suggestions for improving this book, please file an issue in our GitHub repository. Thanks for your patience while we work to update the book, and please stay tuned for the revised version!

In the meantime, you can find an introduction to the changes and new features in the v1.0 release blog post and this "Up & running with blogdown in 2021" blog post.

— Yihui, Amber, & Alison

2.3 Content

The structure of the content/ directory can be arbitrary. A common structure is that there are a few static pages under the root of content/, and a subdirectory post/ containing blog posts:

├── _index.md
├── about.md
├── vitae.md
├── post/
   ├── 2017-01-01-foo.md
   ├── 2017-01-02-bar.md
   └── ...
└── ...

2.3.1 YAML metadata

Each page should start with YAML metadata specifying information like the title, date, author, categories, tags, and so on. Depending on the specific Hugo theme and templates you use, some of these fields may be optional.

Among all YAML fields, we want to bring these to your attention:

  • draft: You can mark a document as a draft by setting draft: true in its YAML metadata. Draft posts will not be rendered if the site is built via blogdown::build_site() or blogdown::hugo_build(), but will be rendered in the local preview mode (see Section D.3).

  • publishdate: You may specify a future date to publish a post. Similar to draft posts, future posts are only rendered in the local preview mode.

  • weight: This field can take a numeric value to tell Hugo the order of pages when sorting them, e.g., when you generate a list of all pages under a directory, and two posts have the same date, you may assign different weights to them to get your desired order on the list.

  • slug: A character string as the tail of the URL. It is particularly useful when you define custom rules for permanent URLs (see Section 2.2.2).

2.3.2 Body

As we mentioned in Section 1.6, your post can be written in either R Markdown or plain Markdown. Please be cautious about the syntax differences between the two formats when you write the body of a post.

2.3.3 Shortcode

Besides all Markdown features, Hugo provides a useful feature named “shortcodes.” You can use a shortcode in the body of your post. When Hugo renders the post, it can automatically generate an HTML snippet based on the parameters you pass to the shortcode. This is convenient because you do not have to type or embed a large amount of HTML code in your post. For example, Hugo has a built-in shortcode for embedding Twitter cards. Normally, this is how you embed a Twitter card (Figure 2.2) on a page:

<blockquote class="twitter-tweet">
  <p lang="en" dir="ltr">Anyone know of an R package for
    interfacing with Alexa Skills?
    <a href="https://twitter.com/thosjleeper">@thosjleeper</a>
    <a href="https://twitter.com/xieyihui">@xieyihui</a>
    <a href="https://twitter.com/drob">@drob</a>
    <a href="https://twitter.com/JennyBryan">@JennyBryan</a>
    <a href="https://twitter.com/HoloMarkeD">@HoloMarkeD</a> ?
  </p>
  &mdash; Jeff Leek (@jtleek)
  <a href="https://twitter.com/jtleek/status/852205086956818432">
    April 12, 2017
  </a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8">
</script>
A tweet by Jeff Leek.

FIGURE 2.2: A tweet by Jeff Leek.

If you use the shortcode, all you need in the Markdown source document is:

{{< tweet user="jtleek", id="852205086956818432" >}}

Basically, you only need to pass the username and ID of the tweet to a shortcode named tweet.19 Hugo will fetch the tweet automatically and render the HTML snippet for you. For more about shortcodes, see https://gohugo.io/extras/shortcodes/.

Shortcodes are supposed to work in plain Markdown documents only. To use shortcodes in R Markdown instead of plain Markdown, you have to call the function blogdown::shortcode(), e.g.,

```{r echo=FALSE}
blogdown::shortcode(
  "tweet", user = "jtleek", id = "852205086956818432"
)
```

  1. Before Hugo v0.89.0, you only need to pass the ID. Since Twitter has started to require the username since late 2021, this means that you have to use Hugo >= 0.89.0 and provide the username if you want to use the Twitter shortcode. For older versions of Hugo, the shortcodes will be broken, unfortunately.↩︎