D.3 Building a website for local preview

The function blogdown::build_site() has an argument local that defaults to FALSE, which means building the website for publishing instead of local previewing. The mode local = TRUE is primarily for blogdown::serve_site() to serve the website locally. There are three major differences between local = FALSE and TRUE. When local = TRUE:

  • The baseurl option in config.toml is temporarily overridden by "/" even if you have set it to a full URL like "http://www.example.com/".46 This is because when a website is to be previewed locally, links should refer to local files. For example, /about/index.html should be used instead of the full link http://www.example.com/about/index.html; the function serve_site() knows that /about/index.html means the file under the public/ directory, and can fetch it and display the content to you, otherwise your browser will take you to the website http://www.example.com instead of displaying a local file.

  • Draft and future posts are always rendered when local = TRUE, but not when local = FALSE. This is for you to preview draft and future posts locally. If you know the Hugo command line, it means the hugo command is called with the flags -D -F, or equivalently, --buildDrafts --buildFuture.

  • There is a caching mechanism to speed up building your website: an Rmd file will not be recompiled when its *.html output file is newer (in terms of file modification time). If you want to force build_site(local = TRUE) to recompile the Rmd file even if it is older than the HTML output, you need to delete the HTML output, or edit the Rmd file so that its modification time will be newer. This caching mechanism does not apply to local = FALSE, i.e., build_site(local = FALSE) will always recompile all Rmd files, because when you want to publish a site, you may need to recompile everything to make sure the site is fully regenerated. If you have time-consuming code chunks in any Rmd files, you have to use either of these methods to save time:

    • Turn on knitr’s caching for time-consuming code chunks, i.e., the chunk option cache = TRUE.

    • Do not call build_site(), but blogdown::hugo_build() instead. The latter does not compile any Rmd files, but simply runs the hugo command to build the site. Please use this method only if you are sure that your Rmd files do not need to be recompiled.

You do not need to worry about these details if your website is automatically generated from source via a service like Netlify, which will make use of baseurl and not use -D -F by default. If you manually publish the public/ folder, you need to be more careful:

  • If your website does not work without the full baseurl, or you do not want the draft or future posts to be published, you should not publish the public/ directory generated by serve_site(). Always run blogdown::build_site() or blogdown::hugo_build() before you upload this directory to a web server.

  • If your drafts and future posts contain (time-)sensitive information, you are strongly recommended to delete the /public/ directory before you rebuild the site for publishing every time, because Hugo never deletes it, and your sensitive information may be rendered by a certain build_site(local = TRUE) call last time and left in the directory. If the website is really important, and you need to make sure you absolutely will not screw up anything every time you publish it, put the /public/ directory under version control, so you have a chance to see which files were changed before you publish the new site.


  1. If your baseurl contains a subdirectory, it will be overridden by the subdirectory name. For example, for baseurl = "http://www.example.com/project/", build_site(local = TRUE) will temporarily remove the domain name and only use the value /project/.