Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Epub Theme

An epub theme for the Static Site Generator HUGO.

This is a simple ebook generator that creates a valid epub ebook from md files.

The epub format

I use the newer epub3 format. The file structure looks like this:

├── mimetype
│   └── container.xml
    ├── chapter
    │   ├── chapter-1.xhtml
    │   ├── chapter-1
    │   │   ├── image-1-1.jpg
    │   │   └── image-1-2.jpg
    │   ├── chapter-2.xhtml
    │   ├── chapter-3.xhtml
    │   ├── chapter-3
    │   │   └── image-3.jpg
    │   ...
    ├── content.opf
    ├── cover.jpg
    ├── css
    │   └── stylesheet.css
    ├── inhaltsverzeichnis.xhtml
    ├── titelseite.xhtml
    └── toc.ncx

How the as HUGO epub theme works

  • mimetype, container.xml and stylesheet.css are static files located in the static/ theme folder
  • cover.jpg is located in the static/OEBPS folder

The rest of the files are dynamically generated from the content of the HUGO project:

├── blog
│   ├── chapter-1
│   │   ├── image-1-1.jpg
│   │   ├── image-1-2.jpg
│   │   └──
│   ├──
│   └── chapter-3
│       ├── image-3.jpg
│       └──
└── creates the central files content.opf and toc.ncx via the configuration in config.toml and the theme layout. The setting

    publishResources: false

in frontmatter ensures that only the scaled images end up in the ebook folder and the original files are not copied along with them -- which HUGO would otherwise do by default. and create these necessary pages in the ebook. These files must not be deleted or renamed. The content comes from params in config.toml. In the frontmatter the parameter ebook: toc resp. ebook: cover ensures that the template single.xhtml handles these special cases differently from the standard.

The actual theme layout under themes/epub/layouts consists of only three files:

├── _default
│   └── single.xhtml
├── index.ncx
├── index.opf

single.xhtml creates all xhtml pages, index.ncx is the template for toc.ncx and index.opf creates content.opf. All this is controlled by config.toml. Normally these three files do not need to be changed. Also, all files used in the ebook must be registered in the manifest of content.opf. This happens automatically for all files from the content folder. But if, for example, static images are referenced in the pages, they would have to be added manually in the manifest. This happens in index.opf.

config.toml contains all meta data for the ebook and ensures that the correct file structure is created:

  • disableKinds turns off almost everything that HUGO does by default. We only generate output for pages and for the root file
  • permalinks plays an important role. Here we have to define the path for each section contained in content/. I have predefined an entry for "blog". If there should be other or further sections (these are the folders directly below content/), a line must be added in each case.
  • mediaTypes, outputFormats and outputs define the three file formats dynamically generated by HUGO: xhtml, opf and ncx. Corresponding templates are located in the layouts/ directory of the theme.
  • markup controls the interpretation of the markdown files and can be customized as desired. The setting xHTML = true must not be changed.
  • params contains the metadata for the ebook (book title, author, etc.). It also specifies how the images should be scaled. Older ebook readers seem to have problems with jpg files (at least my ancient Kindle).

How to generate the epub file

See exampleSite. To create your own ebook, you only need to change the metadata in config.toml and replace the Page-Resources in the content/blog/ folder with your own content in markdown format. In addition, the file static/OEBPS/cover.jpg should be exchanged to your own cover (ideally in portrait format). Do not change file name and format of the cover image.

Calling hugo in the HUGO root directory of the project creates the demo ebook in the public folder -- but still unpacked. To get the desired epub format, the contents of the public directory must be zipped. The zip archive must have the extension .epub.
Important: the mimetype file must be the first file in the zip archive. So the call of zip should be like this to create an ebook named ebook.epub which is located in the HUGO root directory:

cd public
zip -rX ../ebook.epub mimetype OEBPS META-INF

To avoid having file garbage in the finished ebook, the public/ directory and the zip/epub file should be deleted before re-creating the ebook. For Linux enviroment, a deploy bash script is included in the theme that does all the steps automatically:

hugo --cleanDestinationDir
cd public
rm -f ../ebook.epub
zip -rX ../ebook.epub mimetype OEBPS META-INF

Good to know

The theme uses HUGO Page Bundles to manage the images automatically. If you want to integrate images into your resources, you can do this with the shortcode
{{< image src="image name" caption="image caption" >}}
It is enough to specify a substring of the image name, as long as it is unique. The theme currently supports only jpg and png images. The automatic determination of the mimetype in the manifest of content.opf may need some improvement and can be adjusted in index.opf if needed. In general, all file and folder names should be without special characters, as this can lead to validation errors.

Who wants to embed static images from the static/ folder, must consider three things:
1. the images must be in the static/OEBPS/ directory.
2. each image file must be listed in the manifest (in the template index.opf). The already existing entry for cover.jpg can be used as an example.
3. the files must be addressed in the content relatively, e.g. ![Alt-Text](../my-image.jpg)

Epub files with validation errors are usually still displayed by the readers. However, it is of course better if the ebook is formally free of errors. The highly recommended ebook management software Calibre offers the possibility to edit books and in this context also to check for errors and debug them. Other validators: Epub online validator and pagina EPUB checker (freeware).

There is a hack in the automatic generation of the manifest in content.opf and the table of contents (single.xhtml) for which I could not think of a better solution. HUGO would generate paths for relative URLs that look like this, for example: ../OEBPS/chapter/chapter-1.xhtml. This is theoretically correct, but some ebook readers (and also Calibre) don't handle this well and destroy the chapter order. I therefore transform the path by a subsequent replace. I cut ../OEBPS/ from the path, so that it looks like chapter/chapter-1.xhtml.

By the way, for manual internal links between articles, the automatic relative HUGO paths are working fine. For this, the internal ref-shortcode should be used.

There are also two shortcodes that generate the cover page and can be customized if needed: cover.html and covertext.html.

Get the theme

Create an new Hugo site:

$ hugo new site yoursite

Run from the root of your Hugo site:

$ git clone themes/epub

Demo ebook



Creative Commons License

This Hugo theme is licensed under the Creative Commons Attribution 4.0 License.


An epub theme for the Static Site Generator HUGO.








No releases published


No packages published