Open Source Documentation: By Example

John Tucker
codeburst
Published in
5 min readFeb 10, 2018

--

Through example, we will demonstrate a compelling documentation organization for an open source project.

Throughout the years, I have only contributed to open-source projects at the periphery; submitting / commenting on issues and writing blog articles about them. Recently, however, I saw that the folks maintaining redux-actions (a smallish library that I have found surprisingly useful) were looking for help. I decided that I could help with the documentation.

note: In preparation for contributing to the official documentation, I wrote a number of separate but related articles starting with Redux-Actions through Example: Part 1.

I sat down and pieced together the project’s documentation organization and found it to be well thought out (pretty much would not change anything).

Organization

The documentation has three entry points:

  • The web site at <https://redux-actions.js.org/> of HTML pages (including a search feature); useful as an entry point from the web
  • The README.md markup file in the root folder of the master branch of the repository (with links to the web site’s pages); because every respectable GitHub project has one
  • The README.md markup file in the docs folder of the master branch of the repository (with links to the markup files in the docs folder); useful as an entry point when browsing the source code

Observations:

  • The web site’s HTML pages are generated from source markup files from the master branch of the repository; these generated files are not stored in the master branch (good)
  • Because markup files are human readable, the source documentation (in the docs folder) can be read in a text editor (good)
  • There is very little duplication (good)

In order to understand how this is put together, we create an example project and recreate the documentation’s organization.

The final version of the example project (and documentation entry points) is available at:

Prerequisites

If you want to follow along, you will need to install Node.js and Git on your development machine and have a GitHub account.

You will also need to have a basic understanding of Git and GitHub.

Project

Starting with a new folder, we initialize a project with:

npm init

We create the following folders / files:

+ docs
- one.md
- README.md
README.md

docs/one.md

# OneHello from one.

docs/README.md

# hello-gitbookHello from docs.* [One](one.md)

README.md

# hello-gitbookHello from root.

We then initialize the folder as a git repository and push it to GitHub.

This finalizes one of the three entry points:

  • The README.md markup file in the docs folder of the master branch

GitBook

We are going to generate the HTML pages for the web site using GitBook.

Because it is good practice, we are going to install gitbook-cli as a development dependency with an exact version.

npm install --save-dev --save-exact gitbook-cli

We now initialize the project as a GitBook.

./node_modules/.bin/gitbook init

We update the generated SUMMARY.md (used for the web site’s navigation menu) with a link to the one.md file as follows:

SUMMARY.md

# Summary* [Introduction](README.md)
* [One](docs/one.md)

Because we want the gitbook commands to ignore all the non-GitBook files / folders, we create a .bookignore:

.bookignore

.bookignore
docs/README.md
.git
.gitignore
package.json
package-lock.json
node_modules

note: docs/README.md file is not used by GitBook.

We now can preview the generated web site with:

./node_modules/.bin/gitbook serve

We can generate the web site (generated in the _book folder) with:

./node_modules/.bin/gitbook build

Because we do not want to store generated files in the repository, we create a .gitignore file:

.gitignore

node_modules
_book

At this point, we can commit and push the changes to the master branch.

GitHub Pages

We are going to host the generated web site using GitHub Pages.

We begin by creating and checking out a branch named gh-pages in the repository.

We remove all the folders / files except:

_book
.git
.gitignore
node_modules

We then copy all the folders / files from _book folder into the root.

At this point, we can commit and push the changes to the gh-pages branch. GitHub will automatically host the branch with GitHub Pages. This (mostly) finalizes another one of the three entry points:

note: Since redux-actions is a JavaScript library, it can get a no-cost js.org DNS entry pointing to the GitHub Page, e.g, <https://redux-actions.js.org/>.

Links

Next we update the README.md markup file in the root folder in the master branch with links to the web site.

README.md

# hello-gitbookHello from root.* [One](https://larkintuckerllc.github.io/hello-gitbook/docs/one.html)

We commit and push these changes. This finalizes the final third entry points:

  • The README.md markup file in the root folder of the master branch

Update

One problem is that while we updated the README.md markup file in the root of the master branch, the generated web site is now out of date. To address this, we can:

  1. From the master branch, remove the _book folder
  2. Rebuild the _book folder with ./node_modules/.bin/gitbook build
  3. Checkout the gh-pages branch
  4. Remove the folders /files: docs, gitbook, index.html, and search_index.json
  5. Copy all the folders / files from _book folder into the root (recreates the deleted files)
  6. Commit and push the changes to the gh-pages branch

Obviously, one would want to automate this tedious process with Travis CI.

Conclusion

Through example, we demonstrated a compelling documentation organization for an open source project.

Addendum

Got to thinking about how to automate the documentation updates using Travis CI; was a little trickier than I first imagined.

First, went ahead and added a script to package.json.

package.json

...
"scripts": {
"docs": "./node_modules/.bin/gitbook build",
"test": "echo \"Error: no test specified\" && exit 1"
},
...

Then created the Travis CI configuration:

.travis.yml

language: node_js
node_js: lts/*
install:
- npm install
script:
- npm run docs
- git checkout --orphan gh-pages
- git rm -rf .
- cp -R _book/* .
- echo node_modules >> .gitignore
- echo _book >> .gitignore
- echo .gitignore >> .gitignore
- git add -A
- git commit -m "Travis CI"
- git remote add origin-pages https://${GH_TOKEN}@github.com/larkintuckerllc/hello-gitbook
- git push --force origin-pages gh-pages

Observations:

  • Because the gh-pages branch is completely generated (no need for a commit history), we create an orphan branch; the first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.
  • We also remove all the tracked files from the master branch.
  • We create a GitHub personal token and store it in a Travis CI environment variable; don’t want to commit token to the repository.
  • Finally, we have to force the push; because of the orphan branch.

--

--