jekyll-chapterbook

jekyll-chapterbook

GitHub Pages-compatible Jekyll theme for a book with chapters and parts in a style reminiscent of GitBook.


layout: home title: Jekyll Chapterbook Theme permalink: /


This is a Jekyll theme based on GitBook that adds support for easily organizing pages into book chapters and parts. It doesn't rely on any plugins, so it works natively with GitHub Pages.

This theme was originally based on Tao He’s clever and immensely helpful jekyll-gitbook theme, which in turn is based on an early theme of GitBook.

Demos

Demo on GitHub pages

jasongrimes.github.io/jekyll-chapterbook/

Also see its GitHub repo.

Example live site

A live site with a more complex configuration can be seen at book.fretboardfoundation.com.

Also see its GitHub repo.

Why this theme

This theme is intended to help with gradually writing a book over a long period of time, starting from an idea and slowly building out chapters and parts.

It was created with the following objectives:

  • Output a portable, flat folder of static html that can be used offline or hosted anywhere.
  • Support all standard parts of a book, including front matter, back matter, chapters, parts, etc.
  • Support frequently reorganizing chapters and parts without breaking existing links.
  • Make the work in progress publicly available in a useful way, while making drafts that aren't ready for public consumption available without interrupting the flow of completed chapters.
  • Support quickly editing the book on-the-fly, especially from mobile.
  • Run natively on GitHub Pages without custom plugins.
  • Automatically number parts and chapters.
  • Make the markdown source files for each chapter appear in order on the filesystem and on GitHub, regardless of the chapter name, without having to manually renumber. (This makes it easier to find the page you want to edit.)

Getting started

Install the theme

Install this theme like any other Jekyll theme. For example, you could:

remote_theme: jasongrimes/jekyll-chapterbook

Create some chapters

Each chapter is written in its own Jekyll page, and stored in the _chapters/ directory.

Name your chapters something like 010-my-chapter.md, 020-my-next-chapter.md, etc. (The numbers are used to list chapters in the desired order. More on that later.)

Create chapters with the following front matter:

---
title: 
slug:
abstract:
---
  • title: The chapter name / page title.
  • slug: Used to create the page URL. Must be unique.
  • abstract: (Optional.) Shown at the top of a chapter and in the full table of contents.

Chapters also support these other front matter variables, though they are less common.

  • published: If false, the chapter will not be rendered and will not be included in the chapter numbering.
  • disable_toc: If true, don't render the chapter's headings as a table of contents at the top of the page.
  • class: Optionally specify CSS class(es) to add to the <div> wrapping the page.

Here's the markdown for an example chapter and here is that example chapter rendered in the demo.

In the top navigation for every page, there's a link to edit that page on GitHub. This allows you to make quick edits while reviewing. Upon saving the edit form at GitHub, your GitHub Pages site can be automatically rebuilt and deployed.

This even works reasonably well from a mobile device. The ability to review and edit from mobile is one of my favorite features of this theme.

Configure the GitHub link to your own project in github_edit in _config.yml.

github_edit:
  enabled: true
  base_url: https://github.com/jasongrimes/jekyll-chapterbook/edit/master/

See the demo for an example.

To help ensure internal links don't break in different environments and support offline browsing, links to other pages in markdown should use the page's slug and include the .html extension. For example, to link to a page with slug: privacy:

{% raw %}

See the [privacy policy](privacy.html) for details.

{% endraw %}

To insert a link to a chapter, labeled with the chapter title and chapter number, use the chapter-link.html helper:

For example:

{% raw %}

See {% include chapter-link.html slug="variables" %}.

{% endraw %}

See an example chapter link in the demo.

File organization

Builds portable, flat, static html files

This theme deliberately causes all the static HTML files to be generated in the root of the _site folder, with no subfolders.

Ordinarily this might seem like a poor practice for organizing information, but in this case it works well for the following reasons.

  • There aren't that many HTML pages. With one page per chapter, even an enormous book will end up with only a handful of HTML pages.
  • The theme provides a lot of structured metadata to make the page organization explicit and clear to search engines and other automated tools. The folder hierarchy isn't needed to convey this information.
  • With a flat folder structure, the book can be reorganized without breaking existing links. Chapters can be reorganized, parts can be added and removed, titles can be changed, but as long as the slug stays the same, links continue to work.
  • A flat folder structure allows browsing the generated HTML pages offline. Perhaps surprisingly, even static site generators typically create HTML pages that depend on some routing capabilities of a web server, and can't be run on a local file system. A flat HTML folder solves this problem magically.

Chapter file names

Each chapter is written in its own Jekyll page, and stored in the _chapters/ directory.

The file name of a chapter is never shown in the book---chapters are automatically numbered, and the chapter name and link comes from the front matter title and slug. The chapter file name is only used for determining the order of the chapters. It should begin with a number and a dash, so it appears in the correct order, plus a name that makes it easy for you to identify.

For example:

_chapters/
    010-intro.md
    020-thesis.md
    030-antithesis.md
    040-conclusion.md

By using 3-digit numbers and incrementing them by 10 in this way, we can easily reorganize files without having to rename them all. For example, we could add a "synthesis" chapter between "30-antithesis" and "40-conclusion" by prefixing it with a number between 30 and 40.

_chapters/
    010-intro.md
    020-thesis.md
    030-antithesis.md
    035-synthesis.md
    040-conclusion.md

Part directories

Chapters can optionally be grouped into "Parts", by adding subdirectories to the _chapters directory, and moving the chapter files into them. Part directory names should begin with a number so they appear in the correct order, just like chapters. But unlike chapters, the directory name (without the numeric prefix) is also shown in the book as the part name.

_chapters/
    010-thesis/
        010-overview.md
        020-blah-blah.md
    020-antithesis/
        010-underview.md
        030-blather.md

Special parts for book front and back matter

Books typically include material at the front, like a table of contents and introduction, and material at the back, like a glossary or index. (In book publishing, this is called "front matter" and "back matter", not to be confused with the "front matter" variables in Jekyll pages).

This front and back matter is not included in the rest of the book's chapter and page numbering, and it is never grouped into a "part", even when the other chapters are.

To support this special material, there are two optional special part directories: 000-front/ and 999-back/. Chapter pages stored in these special part directories appear before or after the other parts, and the chapters within them are not numbered.

_chapters/
    000-front/
        010-contents.md
        015-preface.md
        020-introduction.md
    010-thesis/
        010-overview.md
        020-blah-blah.md
    050-antithesis/
        010-underview.md
        030-not-blah.md
    999-back/
        010-references.md

The above would render as something like this:

  • Contents
  • Preface
  • Introduction
  • Part I: Thesis
    • Chapter 1: Overview of my thesis
    • Chapter 2: Blah, I say
  • Part II: Antithesis
    • Chapter 3: Under the overview
    • Chapter 4: Not blah, I retort
  • References

See a live site with multiple parts and front and back matter at fretboardfoundation.com and its _chapters/ directory.

Part index pages

To add a dedicated page for a part, with a subset of the table of contents for just the chapters in that part, create a part index page.

In the part folder, add a file named 000-index.md. Give it the following front matter:

---
slug: your-part-name
layout: part
---

See an example part index in the demo, and its source at _chapters/010-chapterbook-theme/000-index.md.

Drafts and outlines

A chapter can be marked as a "draft" by renaming the file and adding .draft to the numeric prefix, like this:

010.draft-introduction.md

Draft chapters are not listed in the table of contents, and they are not included in the chapter numberings. (To see in your dev environment how all the drafts would be numbered if they weren't drafts, set show_drafts_in_dev: true in _config.yml.)

But drafts are listed in the book "outline". This enables a workflow in which you start with an outline of your book, made with empty draft chapters having just a title and maybe an abstract, ordered and grouped into parts as needed (and frequently reorganized).

Then you can flesh out the chapters over time, and when ready, remove the .draft from the file name so it appears in the book.

See an example draft chapter and an example outline.

Non-book pages

Your site will probably have other pages besides the contents of your book (like an about page, a home page, etc.).

Create these like a regular Jekyll page and store them in the _pages directory. In the page front matter, set layout: page and make sure to set the title and slug.

title: About this site
slug: about
layout: page

Then manually add links to the page using the slug.

Here's an example of a non-book page.

Home page

Create your site's home page at _pages/index.md, and use layout: home.

---
layout: home
title: Fretboard Foundation
subtitle: Practical building-blocks for intermediate guitarists.
---

If there is no _pages/index.md, the /README.md will be used instead.

The book's automatically-generated table of contents is shown in the sidebar.

To show additional links above the table of contents in the sidebar, define them in sidebar_nav_top in _config.yml.

sidebar_nav_top:
- label: About this site
  url: about.html

To show additional links at the bottom of the sidebar, define them in sidebar_nav_bottom in _config.yml.

sidebar_nav_bottom:
- label: Privacy statement
  url: privacy.html

Bottom of page

To change the links shown at the bottom of every page, define them in bottom_nav in _config.yml.

bottom_nav:
- label: Home
  url: index.html
- label: Book
  url: book.html
- label: GitHub
  url: https://github.com/jasongrimes/jekyll-chapterbook
- label: Privacy
  url: privacy.html

To configure links to the book title page and table of contents in the chapter breadcrumbs, specify the urls in bookcrumbs in _config.yml. Each item is optional; comment it out to disable it.

bookcrumbs:
  book_url: book.html
  contents_url: contents.html
  book_icon: assets/gitbook/images/apple-touch-icon-precomposed-152.png

Include "helpers"

In order for this theme to work natively with GitHub pages, it can't use any custom Jekyll plugins. But it can do any logic and data manipulation supported by the template language, Liquid.

So this theme makes extensive use of Liquid templates to act as "helpers", by including them in a page and passing them parameters using Jekyll's standard include tag.

See helpers in the demo for details.

The chapter-link.html helper renders a link to the chapter with the specified slug, using its current title and chapter number.

For example: {% raw %}

See {% include chapter-link.html slug="harmony-intro" %}.

{% endraw %}

Parameters:

  • slug: Required. The slug of the chapter to link to.
  • anchor: An optional anchor tag to append to the chapter link.

See an example chapter link.

Tables of contents

The chapterbook-toc.html helper allows you to make a table of contents page, including chapter abstracts (if any).

Parameters:

  • show_drafts: If true, also show draft chapters. Useful for showing an "outline" view of the book.

{% raw %}

{% include chapterbook-toc.html %}

{% endraw %}

See an example table of contents and draft outline in the demo.

Figures

The figure.html helper renders images as figures in the book.

Parameters:

  • url: The relative URL to the image (appended to site.baseurl).
  • caption: An optional caption to render beneath the figure.
  • class: an optional class attribute to add to the the HTML <figure> tag.

See an example figure in the demo.

Theme variables

The chapter-vars.html helper sets a number of variables related to chapters and parts which can be accessed in markdown files or Liquid templates. It can also render the variables for inspection, to help with debugging.

Parameters:

  • id: The page.id of the chapter page for which to set variables.
  • slug: The page.slug of the chapter page for which to set variables (ignored if id is passed).
  • withnum: For performance reasons, chapter and part numbers are not computed unless withnum is true. (To compute only chapter or only part numbers, set withnum=part or withnum=chapter instead.)
  • inspect: If true, render the variables to the page, for debugging.

See example chapter vars in the demo.

Wide tables

Tables can be created using normal GitHub-flavored markdown.

To prevent wide tables from breaking the book layout on mobile devices, wrap them in a <div> directly in the markdown file, with class="table-wrapper" and the attribute markdown="block".

See an example of mobile-friendly wide tables in the demo.

References and citations

See example citations and references list in the demo.

Extra CSS or javascript files

You can add extra CSS or JavaScript references in _config.yml:

  • extra_css: for additional style sheets. If the url does not start with http, the path must be relative to the root of the site, without a starting /.
  • extra_header_js: for additional scripts to be included in the <head> tag, after the extra_css has been added. If the url does not start by http, the path must be relative to the root of the site, without a starting /.
  • extra_footer_js: for additional scripts to be included at the end of the HTML document, just before the site tracking script. If the url does not start by http, the path must be relative to the root of the site, without a starting /.

Customizing font settings

The fonts can be customized by modifying the .book.font-family-0 and .book.font-family-1 entry in ./assets/gitbook/custom.css.

.book.font-family-0 {
    font-family: Georgia, serif;
}
.book.font-family-1 {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

License

Copyright © 2023 Jason Grimes.

This work is open source, made available under the Apache License, Version 2.0.

Originally based on jekyll-gitbook, which was Copyright 2019 Tao He, and licensed under the Apache License, Version 2.0.