6.2 GitHub

You can host your book on GitHub for free via GitHub Pages (https://pages.github.com). GitHub supports Jekyll (http://jekyllrb.com), a static website builder, to build a website from Markdown files. That may be the more common use case of GitHub Pages, but GitHub also supports arbitrary static HTML files, so you can just host the HTML output files of your book on GitHub. The key is to create a hidden file .nojekyll that tells GitHub that your website is not to be built via Jekyll, since the bookdown HTML output is already a standalone website.

# assume you have initialized the git repository,
# and are under the directory of the book repository now

# create a hidden file .nojekyll
touch .nojekyll
# add to git here because will not show up in RStudio
git add .nojekyll

If you are on Windows, you may not have the touch command, and you can create the file in R using file.create('.nojekyll').

One approach is to publish your book as a GitHub Pages site from a /docs folder on your master branch as described in GitHub Help. First, set the output directory of your book to be /docs by adding the line output_dir: "docs" to the configuration file _bookdown.yml. Then, after pushing your changes to GitHub, go to your repository’s settings and under “GitHub Pages” change the “Source” to be “master branch /docs folder”. In this case, the .nojekyll file has to be in the /docs folder.

An alternative approach is to create a gh-pages branch in your repository, build the book, put the HTML output (including all external resources like images, CSS, and JavaScript files) in this branch, and push the branch to the remote repository. If your book repository does not have the gh-pages branch, you may use the following commands to create one:

# assume you have initialized the git repository,
# and are under the directory of the book repository now

# create a branch named gh-pages and clean up everything
git checkout --orphan gh-pages
git rm -rf .

# create a hidden file .nojekyll
touch .nojekyll
git add .nojekyll

git commit -m"Initial commit"
git push origin gh-pages

After you have set up GIT, the rest of work can be automated via a script (Shell, R, or Makefile, depending on your preference). Basically, you compile the book to HTML, then run git commands to push the files to GitHub, but you probably do not want to do this over and over again manually and locally. It can be very handy to automate the publishing process completely on the cloud, so once it is set up correctly, all you have to do next is write the book and push the Rmd source files to GitHub, and your book will always be automatically built and published from the server side.

One service that you can utilize is Travis CI (https://travis-ci.org). It is free for public repositories on GitHub, and was designed for continuous integration (CI) of software packages. Travis CI can be connected to GitHub in the sense that whenever you push to GitHub, Travis can be triggered to run certain commands/scripts on the latest version of your repository.12 These commands are specified in a YAML file named .travis.yml in the root directory of your repository, and they are usually for the purpose of testing software, but in fact they are quite open-ended, meaning that you can run arbitrary commands on a Travis (virtual) machine. That means you can certainly run your own scripts to build your book on Travis. Note that Travis only supports Ubuntu and Mac OS X at the moment, so you should have some basic knowledge about Linux/Unix commands.

The next question is, how to publish the book built on Travis to GitHub? Basically you have to grant Travis write access to your GitHub repository. This authorization can be done in several ways, and the easiest one to beginners may be a personal access token. Here are a few steps you may follow:

  1. Create a personal access token for your account on GitHub (make sure to enable the “repo” scope so that using this token will enable writing to your GitHub repos).
  2. Encrypt it in the environment variable GITHUB_PAT via command line travis encrypt and store it in .travis.yml, e.g travis encrypt GITHUB_PAT=TOKEN. If you do not know how to install or use the Travis command-line tool, simply save this environment variable via https://travis-ci.org/user/repo/settings where user is your GitHub ID, and repo is the name of the repository.
  3. You can clone this gh-pages branch on Travis using your GitHub token, add the HTML output files from R Markdown (do not forget to add figures and CSS style files as well), and push to the remote repository.

Assume you are in the master branch right now (where you put the Rmd source files), and have compiled the book to the _book directory. What you can do next on Travis is:

# configure your name and email if you have not done so
git config --global user.email "you@example.com"
git config --global user.name "Your Name"

# clone the repository to the book-output directory
git clone -b gh-pages \
  https://${GITHUB_PAT}@github.com/${TRAVIS_REPO_SLUG}.git \
cd book-output
git rm -rf *
cp -r ../_book/* ./
git add --all *
git commit -m"Update the book"
git push -q origin gh-pages

The variable name GITHUB_PAT and the directory name book-output are arbitrary, and you can use any names you prefer, as long as the names do not conflict with existing environment variable names or directory names. This script, together with the build script we mentioned in Section 5.1, can be put in the master branch as Shell scripts, e.g., you can name them as _build.sh and _deploy.sh. Then your .travis.yml may look like this:

language: r


  - chmod +x ./_build.sh
  - chmod +x ./_deploy.sh

  - ./_build.sh
  - ./_deploy.sh

The language key tells Travis to use a virtual machine that has R installed. The secure key is your encrypted personal access token. If you have already saved the GITHUB_PAT variable using the web interface on Travis instead of the command-line tool travis encrypt, you can leave out this key.

Since this Travis service is primarily for checking R packages, you will also need a (fake) DESCRIPTION file as if the book repository were an R package. The only thing in this file that really matters is the specification of dependencies. All dependencies will be installed via the devtools package. If a dependency is on CRAN or BioConductor, you can simply list it in the Imports field of the DESCRIPTION file. If it is on GitHub, you may use the Remotes field to list its repository name. Below is an example:

Package: placeholder
Type: Book
Title: Does not matter.
Version: 0.0.1
Imports: bookdown, ggplot2
Remotes: rstudio/bookdown

If you use the container-based infrastructure on Travis, you can enable caching by using sudo: false in .travis.yml. Normally you should cache at least two types of directories: the figure directory (e.g., _main_files) and the cache directory (e.g., _main_cache). These directory names may also be different if you have specified the knitr chunk options fig.path and cache.path, but I’d strongly recommend you not to change these options. The figure and cache directories are stored under the _bookdown_files directory of the book root directory. A .travis.yml file that has enabled caching of knitr figure and cache directories may have additional configurations sudo and cache like this:

sudo: false

  packages: yes
    - $TRAVIS_BUILD_DIR/_bookdown_files

If your book is very time-consuming to build, you may use the above configurations on Travis to save time. Note that packages: yes means the R packages installed on Travis are also cached.

All above scripts and configurations can be found in the bookdown-demo repository: https://github.com/rstudio/bookdown-demo/. If you copy them to your own repository, please remember to change the secure key in .travis.yml using your own encrypted variable GITHUB_PAT.

GitHub and Travis CI are certainly not the only choices to build and publish your book. You are free to store and publish the book on your own server.

  1. You need to authorize the Travis CI service for your repository on GitHub first. See https://docs.travis-ci.com/user/getting-started/ for how to get started with Travis CI.↩︎