Overriding a GitBook theme
GitBook is used all over the place, particularly with open source projects. Though lately folks have been moving away from the service and using other alternatives. One such example is with the kube-builder
project. I was pretty familiar with using GitBook and was asked by a colleague to help with a bug. The bug was requesting that a banner be added to the v1 docs (that were using GitBook) and redirect folks to the new site. Easy enough, right? It should be a single line of code. But it turns out modifying the a GitBook theme is not that simple. Below are my notes on how we went about solving this issue.
Disclaimer: As with most of my posts, the write up is mostly going to be my rambly notes, if you would like more information please reach out.
The gist of how to override any GitBook is to create your own theme, publish it on NPM, add it to the GitBook’s build. Here are steps you can follow.
Special shout-out to Martin Hickey for giving me a shoutout in his PR
1. Use book.json
instead of .gitbook.yaml
To build the GitBook locally you need the GitBook CLI, which is unsupported and only worked on Node v12 (more on this below). This version of GitBook reads the book config from a book.json
file, not .gitbook.yaml
that is used today.
A .gitbook.yaml
that was used for my sample repo.
root: ./docs/
structure:
readme: README.md
summary: SUMMARY.md
The corresponding book.json
(we will add to this later).
{
"root": "/docs"
}
2. About the gitbook
CLI
As mentioned earlier, the gitbook
CLI has been unsupported for some time and appears to have stopped working in v12 of Node.js. If you try to compile and build a GitBook with Node.js v14 or v16 you’ll get a TypeError: cb.apply is not a function
exception.
There are many ways around this problem in the issues and StackOverflow article I linked but the easiest way I found to workaround it was to just use a backlevel version of Node.js using n
to do my Node.js version management.
If you don’t already have n
, install it with:
npm install -g n
And swith to whatever Node.js version you’d like, for instance:
n install 12
Once your Node version is set appropriately you can install the gitbook
CLI.
npm install -g gitbook-cli
And use that to build the site locally:
gitbook install
And to check it out on localhost:9000
run the following:
gitbook serve .
Once you’ve got that working locally you can build a custom theme and test it out.
3. Build a custom theme
For my example check out this repo
Based on my experience, the layout.html
and page.html
were required in the _layouts
directory. I also couldn’t figure out a way to have the files inherit from their parent, so I copy and pasted the entire original theme. (Check it out here)
.
├── .github
│ └── workflows
│ └── npm-publish.yml
├── README.md
├── _layouts
│ └── website
│ ├── layout.html
│ └── page.html
├── package-lock.json
└── package.json
At this point you can change the layout.html
or page.html
templates however you’d like. In my example we just added the following line to page.html
<h3>Viewing legacy documentation for kubebuilder, check out the <a href="https://book.kubebuilder.io">latest</a> documentation instead.</h3>
The one thing worth noting is that GitBook plugins follow a strict naming convention. They must start with gitbook-plugin-
. So your repo name can be whatever you’d like but your published package on NPM must follow that convention or the gitbook install
command will not be able to find your plugin.
The package.json
for my example:
{
"name": "gitbook-plugin-stevemar-archive",
"version": "0.2.2",
"description": "A test for adding archives",
"engines": {
"gitbook": ">1.x.x"
},
"gitbook": {
"properties": {}
}
}
Oh, also, if you’re not sure how to publish to NPM, there’s an easy GitHub Action for that. I had used it for the first time and was able to publish a package in about 15 minutes.
4. Using the extension in the GitBook
Assuming you’ve been able to publish a package to NPM you can now pull in your extension to your GitBook, to do that modify the book.json
file to include the plugin. For example:
{
"root": "/docs",
"plugins": [ "stevemar-archive" ]
}
In this case, it’ll look for a package called gitbook-plugin-stevemar-archive
on NPM.
Build the site locally, and pull in any plugins:
gitbook install
Check out the site locally:
gitbook serve .
Done!