A template repository for creating books with Quarto. This template provides everything you need to quickly start writing your own book.
- 📚 Book-ready structure with sample chapters and references
- 🎨 Customizable themes supporting light and dark modes
- 🚀 Automatic deployment to GitHub Pages via GitHub Actions
- 🔗 Automated link checking to ensure all URLs are reachable
- 📄 Multiple output formats including HTML, PDF, EPUB, and DOCX
- 📑 Bibliography support with BibTeX integration
- 🔢 Automatic numbering of sections and cross-references
- 💅 Custom CSS for styling your book
- 🔖 Code language labels on every code block in HTML output (via the
d-morrison/code-language-labelsextension) - 🔍 PR Preview with change highlighting for pull requests
- ✅ Automated checks including spell checking and linting
- 🤖 GitHub Copilot integration with custom setup steps
- 📝 AI-powered issue summaries for new issues
- Click the "Use this template" button at the top of this repository
- Name your new repository and create it
- Clone your new repository to your local machine
git clone https://github.com/YOUR-USERNAME/YOUR-REPO.git
cd YOUR-REPOYou need to have Quarto installed. Download it from quarto.org/docs/get-started.
To verify Quarto is installed:
quarto --version-
Edit
_quarto.ymlto update:- Book title and author
- Repository URL
- Chapter list
- Theme and styling options
-
Modify
index.qmdto create your book's homepage/introduction -
Edit or create chapters (
.qmdfiles):- Modify
chapter1.qmdandchapter2.qmdas needed - Create new chapters and add them to the
chapterslist in_quarto.yml
- Modify
-
Add references to
references.bibin BibTeX format -
Customize styling in
styles.css
To preview your book with live reload during development:
quarto previewThis will open your book in a web browser and automatically refresh when you make changes.
To render the complete book:
quarto renderThe output will be generated in the docs/ directory.
This template includes a GitHub Actions workflow (.github/workflows/publish.yml) that automatically builds and publishes your book to GitHub Pages when you push to the main branch.
-
Enable GitHub Pages in your repository:
- Go to Settings → Pages
- Under "Build and deployment", set Source to "GitHub Actions"
-
Apply branch rulesets (requires admin access):
.github/scripts/apply-rulesets.sh
This protects
mainagainst direct pushes / force-pushes / deletion, requires a PR to merge, and gates the merge on the configured CI checks (check / link-checker,Spellcheck,check / check-charsandbuild-deploy). A PR is required but zero approvals are needed, so authors can self-merge. Raiserequired_approving_review_countin.github/rulesets/main.jsonto require approvals. See.github/rulesets/README.mdfor details. -
Push to main branch:
git add . git commit -m "Initial book setup" git push origin main
-
Wait for the workflow to complete (check the Actions tab)
-
Access your book at:
https://YOUR-USERNAME.github.io/YOUR-REPO/
This template includes several automated workflows to enhance your development experience:
Automatically builds and deploys your book to GitHub Pages when you push to the main branch.
Triggers: Push to main branch, manual dispatch
Creates a preview deployment for pull requests with:
- Change detection and highlighting
- DOCX files with tracked changes
- Visual indicators for modified chapters
- Banner showing what changed in the PR
Triggers: PR opened, reopened, synchronized, closed, labeled, or unlabeled
Labels:
- Add
no-preview-highlightslabel to disable change highlighting if it's glitchy
Runs automated spell checking on pushes and pull requests to maintain content quality.
Triggers: Push to main, pull requests
Checks R code style and quality using the lintr package.
Triggers: Push to main/master, pull requests
Note: Only runs if your project contains R code.
Lints only the R files a pull request changed, so a PR is flagged for lint it introduces rather than for lint that was already in the repo.
Triggers: Pull requests
Note: Complements lint-project.yaml rather than replacing it.
Whole-repo lint is what catches a file nobody has touched since lintr was added, so keep both.
Like lint-project.yaml, this only reports anything if your project contains R code, including R chunks inside .qmd chapters.
Configures the GitHub Copilot coding agent's environment with Quarto and TinyTeX.
Triggers: Workflow dispatch, changes to the setup file
Automatically generates AI-powered summaries for newly opened issues.
Triggers: New issue opened
Permissions required: The models: read permission for AI inference
Validates that all books and articles in bibliography files meet DOI requirements:
- Every book and article must have a DOI field
- Every DOI must resolve to a valid URL
- Reference information is checked against DOI metadata for consistency
Triggers: Push to main, pull requests, manual dispatch
Note: This helps maintain high-quality bibliographic references and ensures all citations are properly traceable.
.
├── _quarto.yml # Main configuration file
├── index.qmd # Book homepage/introduction
├── chapter1.qmd # Sample chapter 1
├── chapter2.qmd # Sample chapter 2
├── references.qmd # References page
├── references.bib # BibTeX bibliography
├── styles.css # Custom CSS styles
├── lychee.toml # Link checker configuration
├── .gitignore # Git ignore file
├── LICENSE # CC0 1.0 Universal License
├── README.md # This file
└── .github/
├── scripts/ # Scripts for workflows
│ ├── add-home-banner.py
│ ├── check-bibliography-dois.R
│ ├── create-docx-tracked-changes.py
│ ├── detect-changed-chapters.py
│ ├── highlight-html-changes.py
│ └── inject-preview-metadata.py
└── workflows/ # GitHub Actions workflows
├── publish.yml # Build and deploy to GitHub Pages
├── preview.yml # PR preview with change highlighting
├── check-spelling.yaml # Spell checking
├── lint-project.yaml # R code linting
├── copilot-setup-steps.yml # GitHub Copilot setup
├── summary.yml # AI-powered issue summaries
├── check-links.yml # URL reachability checker workflow
└── check-bibliography-dois.yml # Bibliography DOI validation
This template includes two GitHub Actions workflows:
Automatically builds and deploys your book to GitHub Pages when you push to the main branch.
Automatically checks that all URLs in your book are reachable:
- Runs on: Push to main, pull requests, weekly schedule (Mondays at 9:00 UTC), and manual trigger
- Checks: All links in
.qmd,.md, and.htmlfiles - Reports: Workflow fails if broken links are detected. Check the workflow logs for details on which links are broken.
- Configuration: Customize behavior in
lychee.toml - Manual override: Add the
links checked by handlabel to a PR to skip the automated link check
To manually trigger the link checker:
- Go to the Actions tab in your repository
- Select "Check Links" workflow
- Click "Run workflow"
Quarto uses markdown with extensions. Here are some quick tips:
# Chapter Title
## Section
### Subsection```python
print("Hello, World!")
```Inline: $E = mc^2$
Display:
$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$Reference a citation: @citationkey
Reference figures, tables, and sections using labels:
See @fig-example for details.For more details, see the Quarto documentation.
Edit the format.html.theme section in _quarto.yml:
format:
html:
theme:
light: cosmo # Try: cosmo, flatly, litera, minty, etc.
dark: darkly # Try: darkly, cyborg, slate, superhero, etc.- Create a new
.qmdfile (e.g.,chapter3.qmd) - Add it to the
chapterslist in_quarto.yml:
book:
chapters:
- index.qmd
- chapter1.qmd
- chapter2.qmd
- chapter3.qmd # Your new chapter
- references.qmdAdd your custom styles to styles.css.
These will override the default theme styles.
This template deliberately ships no render cache. Its own sample book renders in about four minutes, so there is nothing here to gain, and the caching options carry a correctness hazard better judged against a real book's structure than enabled by default.
Once your book is slow enough for the render time to be annoying, Quarto's freeze feature is the lever.
It caches each page's computed output and re-runs only the pages whose source changed:
execute:
freeze: autoBefore enabling it, know what freeze does not track.
It hashes a page's own source file, and nothing that page pulls in.
Two consequences matter for a book built from this template:
- A page that pulls in another file with
{{< include >}}is not re-rendered when only the included file changes, so the published page silently keeps its old content. - Every page's math depends on the
macros/submodule, and a macro definition change invalidates no page's hash at all, so editing a macro can leave the whole book rendered against the previous definitions.
So freeze: auto on its own trades render time for output that can be quietly wrong.
Enabling it safely means invalidating the affected pages yourself whenever a shared dependency changes.
Morrison-Lab/qwt does this with a script that clears the freeze entries for pages whose includes changed, and caches the _freeze directory between CI runs.
That is the shape to copy, rather than the bare option above.
One more thing to check first.
This template runs pre-render.py before every render, which regenerates macros-pdf.tex from macros/macros.qmd.
How a pre-render hook interacts with a freeze cache is not obvious, so confirm that a macro change still reaches the PDF output before relying on the cache.
This template is released under the CC0 1.0 Universal License, which means you can freely use, modify, and distribute it without any restrictions.
Other Quarto book templates worth comparing against this one:
- NOAA-quarto-book is a
type: booktemplate that also builds PDF and docx, with download links under the logo
Sibling templates from this lab, for adjacent project types rather than books:
- qwt is the Quarto website template, for a site that is not structured as a book
- rpt is the R package template
Feel free to open issues or submit pull requests to improve this template!